From 288a4eea798ca4596cb39d3455ecf46f72ac0418 Mon Sep 17 00:00:00 2001 From: Ravindra Singh Budgurjar Date: Mon, 22 Dec 2025 19:37:17 +0530 Subject: [PATCH] chore: sync organization templates Updated from organization .github repository: - .github/ISSUE_TEMPLATE/bug_report.yaml - .github/ISSUE_TEMPLATE/config.yml - .github/ISSUE_TEMPLATE/feature_request.yaml - .github/ISSUE_TEMPLATE/security_report.yaml - .github/ISSUE_TEMPLATE/support_question.yaml - .github/PULL_REQUEST_TEMPLATE/pr_form.yml - .github/PULL_REQUEST_TEMPLATE/pull_request_template.md - .github/workflows/pr_checks.yml - .github/workflows/commit-msg-validation.yml - SECURITY.md This PR was automatically generated to keep repository templates in sync with organization standards. --- .github/ISSUE_TEMPLATE/bug_report.yaml | 74 +++++++ .github/ISSUE_TEMPLATE/config.yml | 9 + .github/ISSUE_TEMPLATE/feature_request.yaml | 53 +++++ .github/ISSUE_TEMPLATE/security_report.yaml | 43 ++++ .github/ISSUE_TEMPLATE/support_question.yaml | 39 ++++ .github/PULL_REQUEST_TEMPLATE/pr_form.yml | 155 +++++++++++++ .../pull_request_template.md | 77 +++++++ .github/workflows/commit-msg-validation.yml | 179 +++++++++++++++ .github/workflows/pr_checks.yml | 206 ++++++++++++++++++ SECURITY.md | 25 +++ 10 files changed, 860 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yaml create mode 100644 .github/ISSUE_TEMPLATE/security_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/support_question.yaml create mode 100644 .github/PULL_REQUEST_TEMPLATE/pr_form.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_template.md create mode 100644 .github/workflows/commit-msg-validation.yml create mode 100644 .github/workflows/pr_checks.yml create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..1b34a7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,74 @@ +name: "🐞 Bug report" +description: "Report a reproducible bug so we can investigate and fix it quickly." +title: "[BUG] " +labels: ["bug", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thanks for filing a bug — please fill in the details below. Provide as much context as you can to help us reproduce and fix the issue. + - type: input + id: summary + attributes: + label: Short summary + description: A one-line summary of the bug. + placeholder: e.g. "Crash when opening settings with locale=fr" + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Step-by-step list to reproduce the bug. + placeholder: | + 1. Go to ... + 2. Click ... + 3. See error + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: What you expected to happen. + placeholder: "Settings should open without crashing." + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: What actually happened. + placeholder: "App crashes with stacktrace ..." + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs / error output / stack trace (if any) + description: Attach or paste logs. Use backticks for code blocks. + placeholder: "Paste logs, stack traces, or attach files." + - type: checkboxes + id: attachments + attributes: + label: Attachments + description: Add screenshots, recordings, or example files if helpful. + options: + - label: I have attached necessary screenshots / repro assets + - type: dropdown + id: severity + attributes: + label: Severity + options: + - "blocker — blocks development or release" + - "major — feature broken or severe bug" + - "minor — small bug, workaround exists" + - "cosmetic — UI/typo" + validations: + required: true + - type: textarea + id: notes + attributes: + label: Additional notes + description: Anything else the maintainers should know. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..e967290 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,9 @@ +# Organization-level Issue Form config +blank_issues_enabled: false +contact_links: + - name: Security policy (private) + url: https://github.com/RKInnovate/.github/blob/main/SECURITY.md + about: "Report security vulnerabilities (private channel). Use this for sensitive security issues only." + - name: General support + url: https://github.com/RKInnovate/.github/ISSUE_TEMPLATE#support--questions + about: "Use the 'Support / Question' template for product/help requests." diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 0000000..662591f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,53 @@ +name: "💡 Feature request" +description: "Suggest an improvement or new feature — include the problem it solves." +title: "[FEATURE] " +labels: ["enhancement", "triage", "proposal"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please describe the use-case and why it's valuable. + - type: input + id: title_short + attributes: + label: Short summary + placeholder: "Add CSV export to reporting UI" + validations: + required: true + - type: textarea + id: problem + attributes: + label: Problem statement + description: What problem does this feature solve? Who benefits? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution / design + description: How would you like this to work? Include examples, mockups or API changes. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Any alternatives or workarounds you tried. + - type: dropdown + id: priority + attributes: + label: Business priority + options: + - "P0 — critical" + - "P1 — important" + - "P2 — nice-to-have" + - "P3 — low priority" + validations: + required: true + - type: input + id: contacts + attributes: + label: Contacts + description: Who requested this, who will be impacted, or what triggered this request? + placeholder: "team@example.com/in email from user@example.com" diff --git a/.github/ISSUE_TEMPLATE/security_report.yaml b/.github/ISSUE_TEMPLATE/security_report.yaml new file mode 100644 index 0000000..90330a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/security_report.yaml @@ -0,0 +1,43 @@ +name: "🔐 Security vulnerability report" +description: "Report a potential security vulnerability. Do NOT include sensitive secrets or PII in this issue — use the private disclosure channel described below." +title: "[SECURITY] " +labels: ["security", "triage", "private"] +assignees: [] +body: + - type: markdown + attributes: + value: | + **Security disclosure instructions** + * Do NOT post exploits, PII, credentials, or sensitive attachments in a public issue. + * If you have sensitive details, email: security@ORG-DOMAIN (or use our private disclosure process) — see SECURITY.md. + * If this is non-sensitive proof-of-concept information safe for public view, fill the form below. + - type: input + id: summary + attributes: + label: Short summary + placeholder: "SQL injection in /api/endpoint" + validations: + required: true + - type: textarea + id: impact + attributes: + label: Impact + description: What could an attacker do? Data exposure, RCE, privilege escalation, etc. + validations: + required: true + - type: textarea + id: poc + attributes: + label: Proof-of-concept (non-sensitive) + description: Steps or code to reproduce (do NOT include secrets). + - type: input + id: disclosure_contact + attributes: + label: Contact email (for private follow-up) + validations: + required: true + - type: textarea + id: notes + attributes: + label: Additional notes + description: Anything else maintainers should know. diff --git a/.github/ISSUE_TEMPLATE/support_question.yaml b/.github/ISSUE_TEMPLATE/support_question.yaml new file mode 100644 index 0000000..86da624 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support_question.yaml @@ -0,0 +1,39 @@ +name: "❓ Support / Question" +description: "Ask for help with using the project, configuration, or setup issues." +title: "[SUPPORT] " +labels: ["support", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Use this template for usage questions, configuration help, or troubleshooting that is not a bug. + - type: input + id: summary + attributes: + label: Short summary + placeholder: "How to configure X with Y?" + validations: + required: true + - type: textarea + id: context + attributes: + label: Context / background + description: Where are you running this? What versions/config did you try? + placeholder: "I am using docker-compose on Ubuntu 22.04..." + validations: + required: true + - type: textarea + id: attempt + attributes: + label: What you tried + placeholder: "I tried ... but got ..." + - type: textarea + id: expected + attributes: + label: What you expected to happen + - type: input + id: contact + attributes: + label: Preferred contact (email / handle) + description: If maintainers need follow-up, how should we reach you? diff --git a/.github/PULL_REQUEST_TEMPLATE/pr_form.yml b/.github/PULL_REQUEST_TEMPLATE/pr_form.yml new file mode 100644 index 0000000..3a66e20 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pr_form.yml @@ -0,0 +1,155 @@ +name: "📦 Pull Request" +description: "Submit a PR with structured details for review." +title: "[PR] " +labels: [] +body: + - type: markdown + attributes: + value: | + # 📦 Pull Request + Thanks for contributing! Please fill in all required fields to ensure smooth review. + + - type: input + id: summary + attributes: + label: Short summary (one line) + description: "e.g., feat(auth): add SSO login" + placeholder: "Short descriptive title" + validations: + required: true + + - type: textarea + id: description + attributes: + label: Description + description: "What does this PR do? Why is it needed?" + placeholder: "Provide context for the change..." + validations: + required: true + + - type: dropdown + id: type_of_change + attributes: + label: Type of change + options: + - Bug fix + - New feature + - Breaking change + - Chore / refactor / documentation + validations: + required: true + + - type: textarea + id: related_issues + attributes: + label: Related tickets / issues + description: "List related issue numbers, e.g., Closes #123" + placeholder: "Closes #123" + validations: + required: false + + - type: textarea + id: changes + attributes: + label: Proposed changes + description: "List key changes included in this PR." + placeholder: | + - Added ... + - Updated ... + - Removed ... + validations: + required: true + + - type: textarea + id: test_instructions + attributes: + label: How to test / QA + description: "Provide clear steps for reviewers/testers." + placeholder: | + 1. Checkout branch... + 2. Run tests... + 3. Verify behavior... + validations: + required: true + + - type: checkboxes + id: checklist + attributes: + label: Checklist (required) + description: Ensure your PR meets these requirements. + options: + - label: Tests added/updated and passing locally + - label: Documentation updated (if applicable) + - label: Linting and formatting completed + - label: PR title follows repo conventions (e.g., conventional commits) + - label: No sensitive data or secrets are included + validations: + required: true + + - type: textarea + id: rollout + attributes: + label: Rollout plan & backwards compatibility + description: "List deployment steps, flags, compatibility notes." + placeholder: "This change is backward compatible because..." + validations: + required: false + + - type: textarea + id: migrations + attributes: + label: Database migrations (if any) + description: "Describe any migrations and whether they are safe/additive." + placeholder: | + - Migration script: /sql/migrations/xxx.sql + - Up: ... + - Down: ... + validations: + required: false + + - type: textarea + id: security + attributes: + label: Security considerations + description: "Does this PR affect auth, secrets, PII, or permissions?" + placeholder: | + - No sensitive data + - Touches auth: added validation... + validations: + required: false + + - type: textarea + id: performance + attributes: + label: Performance considerations + description: "Any impact on speed, memory, or scaling?" + placeholder: "No measurable performance impact." + validations: + required: false + + - type: textarea + id: screenshots + attributes: + label: Screenshots / recordings + description: "If UI changed, include visuals." + placeholder: "Attach before/after screenshots..." + validations: + required: false + + - type: input + id: changelog + attributes: + label: Changelog entry + description: "Short entry for release notes." + placeholder: "Added support for X in API Y" + validations: + required: false + + - type: input + id: reviewers + attributes: + label: Suggested reviewers + description: "Tag team members or @teams as needed." + placeholder: "@your-team" + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..7971669 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,77 @@ +# Pull Request + +> Short summary (one line) +**Title:** + +## Description +Provide a short description of the change and the motivation. +Explain *why* this change is necessary and what problem it solves. + +## Type of change +(Select or remove those that do not apply) +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) +- [ ] Chore / refactor / documentation + +## Related tickets / issues +- Closes: # +- Related: # + +## Proposed changes +List the main changes made in this PR (files, modules, behaviour). +- Change 1 +- Change 2 +- Change 3 + +## How to test / QA +Step-by-step instructions for testing (include test data / commands / env vars). +1. Checkout branch `...` +2. Run `make test` or `npm run test` +3. Steps to reproduce behavior +4. Expected result + +## Checklist (required) +Make sure your PR adheres to the org standards: +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] I have added or updated relevant documentation (README, code comments, CHANGELOG) +- [ ] I have run the test suite locally and all tests pass +- [ ] Linted and formatted code (`prettier`, `golangci-lint`, `rustfmt`, etc.) +- [ ] I updated any necessary config or infra files +- [ ] PR title follows conventional commit / repo convention + +## Rollout plan & backwards compatibility +Explain rollout steps, feature flags, and whether this change is backward compatible. If a database migration is present, state whether it is additive or destructive and migration instructions. + +## Database migrations +- [ ] Migration script included +- Migration notes: + - Up: `sql/migrations/xxxx_up.sql` + - Down: `sql/migrations/xxxx_down.sql` + +## Security considerations +If this change affects authentication, authorization, secrets, data exposure, or external dependencies, describe the risk and mitigation. +- Sensitive data included? (Yes / No) +- If yes — how is it protected? + +## Performance considerations +Note any performance implications and how you measured them (benchmarks, profiling). + +## Screenshots / recordings +If UI changes, include before/after screenshots or a short recording. + +## Release notes / changelog entry +Suggested changelog entry (one sentence). + +## Reviewers / Assignees +- Requested reviewers: @team-or-user +- Code owners: (will be assigned by CODEOWNERS if present) + +--- + +### Optional: Quick PR template for tiny fixes +For trivial changes (typo, small doc tweak), add `#trivial` in the title to indicate expedited review. + +### Releated Issue +#{{ISSUE_NUMBERs}} + diff --git a/.github/workflows/commit-msg-validation.yml b/.github/workflows/commit-msg-validation.yml new file mode 100644 index 0000000..c92306e --- /dev/null +++ b/.github/workflows/commit-msg-validation.yml @@ -0,0 +1,179 @@ +name: "Commit message validation" + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + validate_commits: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate commit messages + uses: actions/github-script@v7 + with: + script: | + const prNumber = context.payload.pull_request.number; + const baseSha = context.payload.pull_request.base.sha; + const headSha = context.payload.pull_request.head.sha; + + // Get all commits in the PR + const { data: commits } = await github.rest.repos.compareCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + base: baseSha, + head: headSha + }); + + const conventionalCommitPattern = /^(Merge|feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+/; + const errors = []; + const warnings = []; + const passed = []; + + // Validate each commit message + for (const commit of commits.commits) { + const message = commit.commit.message.split('\n')[0]; // First line only + const shortSha = commit.sha.substring(0, 7); + + if (!conventionalCommitPattern.test(message)) { + errors.push({ + sha: shortSha, + message: message, + issue: 'Does not follow conventional commit format' + }); + } else { + passed.push(`✅ \`${shortSha}\`: ${message}`); + } + + // Check length + if (message.length > 100) { + warnings.push({ + sha: shortSha, + message: message, + issue: `Too long (${message.length} characters, recommended: ≤ 100)` + }); + } + } + + // Generate report in table format + let commentBody = '## 🤖 Commit Message Validation Report\n\n'; + + // Summary table + const totalCommits = commits.commits.length; + const validCommits = totalCommits - errors.length; + const statusEmoji = errors.length > 0 ? '❌' : (warnings.length > 0 ? '⚠️' : '✅'); + const statusText = errors.length > 0 ? 'Failed' : (warnings.length > 0 ? 'Passed with warnings' : 'All valid'); + + commentBody += '### Summary\n\n'; + commentBody += '| Status | Total Commits | Valid | Invalid | Warnings |\n'; + commentBody += '|--------|---------------|-------|---------|----------|\n'; + commentBody += `| ${statusEmoji} **${statusText}** | ${totalCommits} | ${validCommits} | ${errors.length} | ${warnings.length} |\n\n`; + + // Detailed results table + if (errors.length > 0 || warnings.length > 0 || passed.length > 0) { + commentBody += '### Commit Details\n\n'; + commentBody += '| Status | SHA | Commit Message | Issue |\n'; + commentBody += '|--------|-----|----------------|-------|\n'; + + // Add errors first + errors.forEach(error => { + const truncatedMsg = error.message.length > 60 ? error.message.substring(0, 57) + '...' : error.message; + commentBody += `| ❌ | \`${error.sha}\` | ${truncatedMsg} | ${error.issue} |\n`; + }); + + // Add warnings (commits with length issues) + warnings.forEach(warning => { + const truncatedMsg = warning.message.length > 60 ? warning.message.substring(0, 57) + '...' : warning.message; + commentBody += `| ⚠️ | \`${warning.sha}\` | ${truncatedMsg} | ${warning.issue} |\n`; + }); + + // Add passed commits (show first 5 only to keep table compact) + const passedToShow = passed.slice(0, 5); + passedToShow.forEach(check => { + const match = check.match(/`([^`]+)`: (.+)/); + if (match) { + const sha = match[1]; + const msg = match[2]; + const truncatedMsg = msg.length > 60 ? msg.substring(0, 57) + '...' : msg; + commentBody += `| ✅ | \`${sha}\` | ${truncatedMsg} | — |\n`; + } + }); + + if (passed.length > 5) { + commentBody += `| ✅ | ... | *${passed.length - 5} more valid commit(s)* | — |\n`; + } + + commentBody += '\n'; + } + + // Help section for errors + if (errors.length > 0) { + commentBody += '
\n'; + commentBody += '📖 How to fix invalid commit messages\n\n'; + commentBody += '**Expected format:** `type(scope): description`\n\n'; + commentBody += '**Valid types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`\n\n'; + commentBody += '**Examples:**\n'; + commentBody += '- `feat(auth): add SSO login support`\n'; + commentBody += '- `fix: resolve memory leak in cache`\n'; + commentBody += '- `docs(readme): update installation steps`\n\n'; + commentBody += '**Fix options:**\n'; + commentBody += '1. Use `git rebase -i HEAD~N` to reword commit messages\n'; + commentBody += '2. Squash commits into one with a valid message\n'; + commentBody += '3. If using "Squash and merge", ensure PR title is valid (this is enforced separately)\n\n'; + commentBody += '
\n\n'; + } + + commentBody += '---\n\n'; + + if (errors.length > 0) { + commentBody += '⚠️ **Note:** This is a warning only. If you\'re using "Squash and merge", the PR title will be used for the final commit (which is validated separately).\n\n'; + } + + commentBody += 'This check validates that all commit messages follow conventional commit format.'; + + // Post/Update comment + const botCommentIdentifier = ''; + commentBody = botCommentIdentifier + '\n\n' + commentBody; + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber + }); + + const existingComment = comments.find(comment => + comment.body && comment.body.includes(botCommentIdentifier) + ); + + if (existingComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: commentBody + }); + console.log('Updated existing commit validation comment'); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody + }); + console.log('Posted new commit validation comment'); + } + + // Set check status (make it a warning, not a failure, since PR title will be used for merge) + if (errors.length > 0) { + core.warning(`Found ${errors.length} commit(s) with invalid messages. Please fix or ensure PR title is valid for squash merge.`); + } else { + console.log('✅ All commit messages are valid!'); + } diff --git a/.github/workflows/pr_checks.yml b/.github/workflows/pr_checks.yml new file mode 100644 index 0000000..24b07af --- /dev/null +++ b/.github/workflows/pr_checks.yml @@ -0,0 +1,206 @@ +name: "PR checks" +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + validate_pr: + runs-on: ubuntu-latest + steps: + - name: Validate PR title and body + uses: actions/github-script@v7 + with: + script: | + const title = context.payload.pull_request.title || ""; + const body = context.payload.pull_request.body || ""; + const prNumber = context.payload.pull_request.number; + + const errors = []; + const warnings = []; + const passed = []; + + // ============================================ + // 1. Validate PR Title (Conventional Commits) + // ============================================ + const conventionalCommitPattern = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+/; + + if (!conventionalCommitPattern.test(title)) { + errors.push({ + type: 'title', + message: 'PR title does not follow conventional commit format', + details: 'Expected format: `type(scope): description`\n\nValid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert\n\nExamples:\n- `feat(auth): add SSO login support`\n- `fix: resolve memory leak in cache`\n- `docs(readme): update installation steps`' + }); + } else { + passed.push('✅ PR title follows conventional commit format'); + } + + // Check title length + if (title.length > 100) { + warnings.push({ + type: 'title', + message: 'PR title is too long', + details: `Title length: ${title.length} characters (recommended: ≤ 100)` + }); + } else { + passed.push('✅ PR title length is appropriate'); + } + + // ============================================ + // 2. Validate PR Body Sections + // ============================================ + const requiredSections = [ + { pattern: /##?\s*Description/i, name: 'Description' }, + { pattern: /##?\s*How to test|##?\s*Test/i, name: 'How to test / QA' }, + { pattern: /##?\s*Checklist/i, name: 'Checklist' }, + ]; + + const missingSections = []; + for (const section of requiredSections) { + if (!section.pattern.test(body)) { + missingSections.push(section.name); + } else { + passed.push(`✅ Contains "${section.name}" section`); + } + } + + if (missingSections.length > 0) { + errors.push({ + type: 'body', + message: 'PR body is missing required sections', + details: `Missing sections:\n${missingSections.map(s => `- ${s}`).join('\n')}` + }); + } + + // Check for issue references + const issueRefPattern = /#\d+|fixes|closes|resolves/i; + if (!issueRefPattern.test(body)) { + warnings.push({ + type: 'body', + message: 'No issue reference found', + details: 'Consider linking related issues using `Closes #123` or `Fixes #456`' + }); + } else { + passed.push('✅ Contains issue reference'); + } + + // Check for empty description + const descriptionMatch = body.match(/##?\s*Description\s*\n\s*(.+?)(?=\n##|$)/is); + if (descriptionMatch) { + const description = descriptionMatch[1].trim(); + if (description.length < 10) { + warnings.push({ + type: 'body', + message: 'Description seems too short', + details: 'Please provide a detailed description of your changes' + }); + } + } + + // ============================================ + // 3. Generate Report in Table Format + // ============================================ + const hasErrors = errors.length > 0; + const hasWarnings = warnings.length > 0; + + let commentBody = '## 🤖 PR Validation Report\n\n'; + + // Summary table + const totalChecks = errors.length + warnings.length + passed.length; + const statusEmoji = hasErrors ? '❌' : (hasWarnings ? '⚠️' : '✅'); + const statusText = hasErrors ? 'Failed' : (hasWarnings ? 'Passed with warnings' : 'All checks passed'); + + commentBody += '### Summary\n\n'; + commentBody += '| Status | Total Checks | Errors | Warnings | Passed |\n'; + commentBody += '|--------|--------------|--------|----------|--------|\n'; + commentBody += `| ${statusEmoji} **${statusText}** | ${totalChecks} | ${errors.length} | ${warnings.length} | ${passed.length} |\n\n`; + + // Detailed results table + if (errors.length > 0 || warnings.length > 0 || passed.length > 0) { + commentBody += '### Detailed Results\n\n'; + commentBody += '| Status | Check | Details |\n'; + commentBody += '|--------|-------|----------|\n'; + + // Add errors first + errors.forEach(error => { + const details = error.details.replace(/\n/g, '
'); + commentBody += `| ❌ | **${error.message}** | ${details} |\n`; + }); + + // Add warnings + warnings.forEach(warning => { + const details = warning.details.replace(/\n/g, '
'); + commentBody += `| ⚠️ | **${warning.message}** | ${details} |\n`; + }); + + // Add passed checks + passed.forEach(check => { + const checkText = check.replace('✅ ', ''); + commentBody += `| ✅ | ${checkText} | — |\n`; + }); + + commentBody += '\n'; + } + + commentBody += '---\n\n'; + + if (hasErrors) { + commentBody += '### 📋 Next Steps\n\n'; + commentBody += '1. ✏️ Update your PR title and/or description to address the errors above\n'; + commentBody += '2. 🔄 The checks will automatically re-run when you make changes\n\n'; + } else if (hasWarnings) { + commentBody += '💡 **Tip:** Consider addressing the warnings above to improve your PR quality.\n\n'; + } + + commentBody += 'This check validates PR title format and ensures all required sections are present in the PR description.'; + + // ============================================ + // 4. Post/Update Comment + // ============================================ + const botCommentIdentifier = ''; + commentBody = botCommentIdentifier + '\n\n' + commentBody; + + // Find existing bot comment + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber + }); + + const existingComment = comments.find(comment => + comment.body && comment.body.includes(botCommentIdentifier) + ); + + if (existingComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: commentBody + }); + console.log('Updated existing validation comment'); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody + }); + console.log('Posted new validation comment'); + } + + // ============================================ + // 5. Set Check Status + // ============================================ + if (hasErrors) { + const errorSummary = errors.map(e => e.message).join(', '); + core.setFailed(`PR validation failed: ${errorSummary}`); + } else { + console.log('✅ All PR validation checks passed!'); + } diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..6980f02 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,25 @@ +# Security Policy + +All repositories under this organization are private and used internally. + +If you discover a security concern, vulnerability, or sensitive issue within any project, please report it directly to the internal engineering team. + +## 📩 Reporting Security Issues + +Please DO NOT open a public issue. + +Instead, contact: + +**security@rkinnovate.com** + +If email is not available, reach out directly to the engineering lead or via your internal communication channel (Slack/Teams). + +## 🔒 Disclosure Policy + +- Report issues privately. +- Do not share exploit details or internal code outside the organization. +- The engineering team will acknowledge and triage issues based on severity. + +## 🛡 Scope + +This policy applies to all repositories and services under this GitHub organization.