From 98c62d09fd115a5b320e580164bbd219bfbfd0ff Mon Sep 17 00:00:00 2001 From: Ghanshyam Singh Date: Sat, 14 Mar 2026 22:12:21 +0530 Subject: [PATCH] add: workflows --- .github/pull_request_template.md | 11 ++ .github/workflows/peer-review-reminder.yml | 114 ++++++++++++++++++++ .github/workflows/pr-title-format-check.yml | 19 ++++ 3 files changed, 144 insertions(+) create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/peer-review-reminder.yml create mode 100644 .github/workflows/pr-title-format-check.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2d43bf5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## What does this PR change? + + +## Why is this needed? + + +## Checklist +- [ ] Code runs locally +- [ ] Tests pass +- [ ] No hardcoded secrets +- [ ] Documentation updated \ No newline at end of file diff --git a/.github/workflows/peer-review-reminder.yml b/.github/workflows/peer-review-reminder.yml new file mode 100644 index 0000000..7656b5c --- /dev/null +++ b/.github/workflows/peer-review-reminder.yml @@ -0,0 +1,114 @@ +name: Peer Review Reminder + +on: + pull_request_target: + types: [opened, reopened, synchronize, ready_for_review] + pull_request_review: + types: [submitted, dismissed] + +permissions: + pull-requests: write + +jobs: + check-peer-review: + runs-on: ubuntu-latest + name: Check PR has a peer review + steps: + - name: Check for approved peer review and comment if missing + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const repo = context.repo; + const pr = context.payload.pull_request; + const prNumber = pr.number; + + // Skip draft PRs + if (pr.draft) { + console.log(`PR #${prNumber} is a draft, skipping peer review check`); + return; + } + + // Check for exempt users (bots and maintainers) + const exemptUsers = ['A1L13N', 'copilot-swe-agent[bot]', 'copilot[bot]', 'github-copilot[bot]', 'dependabot[bot]']; + if (exemptUsers.includes(pr.user.login)) { + console.log(`PR author ${pr.user.login} is exempt from peer review requirement`); + return; + } + + // Check if PR branch is a copilot branch + if (pr.head.ref.startsWith('copilot/')) { + console.log(`PR branch ${pr.head.ref} starts with 'copilot/', exempt from peer review requirement`); + return; + } + + // Fetch all reviews for this PR + const { data: reviews } = await github.rest.pulls.listReviews({ + owner: repo.owner, + repo: repo.repo, + pull_number: prNumber, + }); + + // Check if there is at least one APPROVED review from someone other than the PR author + const approvedReview = reviews.find( + review => review.state === 'APPROVED' && review.user.login !== pr.user.login + ); + + const botUserName = 'github-actions[bot]'; + const commentMarker = ''; + + // Fetch existing comments + const { data: comments } = await github.rest.issues.listComments({ + owner: repo.owner, + repo: repo.repo, + issue_number: prNumber, + }); + + const previousComment = comments.find( + comment => comment.user.login === botUserName && comment.body.includes(commentMarker) + ); + + if (approvedReview) { + console.log(`PR #${prNumber} has an approved review from ${approvedReview.user.login}`); + + // Remove the reminder comment if it exists and PR now has approval + if (previousComment) { + await github.rest.issues.deleteComment({ + owner: repo.owner, + repo: repo.repo, + comment_id: previousComment.id, + }); + console.log(`Removed peer review reminder comment from PR #${prNumber}`); + } + return; + } + + // No approved review found — post a reminder if not already posted + if (previousComment) { + console.log(`Already commented about missing peer review on PR #${prNumber}, skipping duplicate`); + return; + } + + const message = [ + commentMarker, + '## 👀 Peer Review Required', + '', + `Hi @${pr.user.login}! This pull request does not yet have a **peer review**.`, + '', + 'Before this PR can be merged, please request a review from one of your peers:', + '', + '- Go to the PR page and click **"Reviewers"** on the right sidebar.', + '- Select a team member or contributor to review your changes.', + '- Once they approve, this reminder will be automatically removed.', + '', + 'Thank you for contributing! 🎉', + ].join('\n'); + + await github.rest.issues.createComment({ + owner: repo.owner, + repo: repo.repo, + issue_number: prNumber, + body: message, + }); + + console.log(`Posted peer review reminder on PR #${prNumber}`); \ No newline at end of file diff --git a/.github/workflows/pr-title-format-check.yml b/.github/workflows/pr-title-format-check.yml new file mode 100644 index 0000000..17d225c --- /dev/null +++ b/.github/workflows/pr-title-format-check.yml @@ -0,0 +1,19 @@ +name: PR Title Format Check + +on: + pull_request: + types: [opened, edited, reopened] + +jobs: + check-title: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prTitle = context.payload.pull_request.title; + const valid = /^(fix|feat|docs|add|update):/i.test(prTitle); + if (!valid) { + throw new Error('PR title must start with fix:, feat:, docs:, add:, or update:'); + } \ No newline at end of file