From 5b373f40c14b15d44dbea88c596ca7e7a1e569bb Mon Sep 17 00:00:00 2001 From: Aditya8369 Date: Mon, 18 May 2026 23:07:22 +0530 Subject: [PATCH] Auto labelling opened PRs with gssoc:approved --- .../workflows/sync-gssoc-approved-label.yml | 99 +++++++++++++++++++ docs/contributing.md | 2 + 2 files changed, 101 insertions(+) create mode 100644 .github/workflows/sync-gssoc-approved-label.yml diff --git a/.github/workflows/sync-gssoc-approved-label.yml b/.github/workflows/sync-gssoc-approved-label.yml new file mode 100644 index 000000000..519840e6d --- /dev/null +++ b/.github/workflows/sync-gssoc-approved-label.yml @@ -0,0 +1,99 @@ +name: Sync gssoc approved label + +on: + pull_request_review: + types: [submitted, dismissed] + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + sync-approved-label: + runs-on: ubuntu-latest + steps: + - name: Sync gssoc:approved label + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const labelName = 'gssoc:approved'; + const pullRequest = context.payload.pull_request || context.payload.review?.pull_request; + + if (!pullRequest?.number) { + core.info('No pull request context found.'); + return; + } + + const owner = context.repo.owner; + const repo = context.repo.repo; + const pullNumber = pullRequest.number; + + const { data: currentPullRequest } = await github.rest.pulls.get({ + owner, + repo, + pull_number: pullNumber, + }); + + const headSha = currentPullRequest.head.sha; + const reviews = await github.paginate(github.rest.pulls.listReviews, { + owner, + repo, + pull_number: pullNumber, + per_page: 100, + }); + + const latestReviewsByUser = new Map(); + + for (const review of reviews) { + if (!review.user || review.user.type === 'Bot' || !review.submitted_at) { + continue; + } + + const existing = latestReviewsByUser.get(review.user.login); + const reviewTime = Date.parse(review.submitted_at); + const existingTime = existing ? Date.parse(existing.submitted_at) : -1; + + if (!existing || reviewTime >= existingTime) { + latestReviewsByUser.set(review.user.login, review); + } + } + + const approvedOnCurrentHead = [...latestReviewsByUser.values()].some( + (review) => review.state === 'APPROVED' && review.commit_id === headSha + ); + + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ + owner, + repo, + issue_number: pullNumber, + }); + + const hasLabel = labels.some((label) => label.name === labelName); + + if (approvedOnCurrentHead && !hasLabel) { + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: pullNumber, + labels: [labelName], + }); + core.info(`Added ${labelName} to PR #${pullNumber}.`); + return; + } + + if (!approvedOnCurrentHead && hasLabel) { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: pullNumber, + name: labelName, + }); + core.info(`Removed ${labelName} from PR #${pullNumber}.`); + return; + } + + core.info(`No label change needed for PR #${pullNumber}.`); \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md index 90ace7e59..f63cab5f2 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -71,6 +71,8 @@ When proposing an enhancement, describe: 4. Include screenshots for visible UI changes. 5. Reference the related issue if one exists. +If label automation is enabled in the repository, `gssoc:approved` is added when the PR has an approval on its current head commit and is removed again if that approval becomes stale after new commits. + ## Code Style - Keep the frontend vanilla unless a change explicitly needs otherwise.