Finalize Review Scores #519
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "Finalize Ranking Scores (Scheduled)" | |
| on: | |
| schedule: | |
| - cron: "0 */2 * * *" # Runs every 2 hours | |
| workflow_dispatch: | |
| jobs: | |
| finalize-ranking: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Process Unranked Nominations | |
| uses: actions/github-script@v6 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { repo, owner } = context.repo; | |
| const threshold = 3.0; | |
| const scoreRegex = /^score:\s*(\d)/i; | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner, | |
| repo, | |
| state: "open", | |
| labels: "nomination" | |
| }); | |
| for (const issue of issues.data) { | |
| const issue_number = issue.number; | |
| const currentLabels = issue.labels.map(label => label.name); | |
| if (currentLabels.includes("ranked")) continue; // Skip already ranked | |
| const comments = await github.rest.issues.listComments({ | |
| owner, | |
| repo, | |
| issue_number | |
| }); | |
| let totalScore = 0; | |
| let numScores = 0; | |
| const reviewers = new Set(); | |
| const reviewerList = []; | |
| comments.data.forEach(comment => { | |
| const match = comment.body.match(scoreRegex); | |
| const author = comment.user.login; | |
| if (match && !reviewers.has(author)) { | |
| const score = parseInt(match[1]); | |
| if (score >= 1 && score <= 5) { | |
| totalScore += score; | |
| numScores++; | |
| reviewers.add(author); | |
| reviewerList.push(`@${author}`); | |
| } | |
| } | |
| }); | |
| if (numScores === 0) continue; | |
| const avg = totalScore / numScores; | |
| const finalLabel = avg >= threshold ? "approved" : "rejected"; | |
| const oppositeLabel = finalLabel === "approved" ? "rejected" : "approved"; | |
| if (currentLabels.includes(oppositeLabel)) { | |
| await github.rest.issues.removeLabel({ | |
| owner, | |
| repo, | |
| issue_number, | |
| name: oppositeLabel | |
| }); | |
| } | |
| if (!currentLabels.includes(finalLabel)) { | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number, | |
| labels: [finalLabel] | |
| }); | |
| } | |
| if (currentLabels.includes("pending-review")) { | |
| await github.rest.issues.removeLabel({ | |
| owner, | |
| repo, | |
| issue_number, | |
| name: "pending-review" | |
| }); | |
| } | |
| if (finalLabel === "rejected") { | |
| await github.rest.issues.update({ | |
| owner, | |
| repo, | |
| issue_number, | |
| state: "closed" | |
| }); | |
| } | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number, | |
| body: `🧮 Final average score from ${numScores} reviewer(s): **${avg.toFixed(2)}**\n👥 Reviewed by: ${reviewerList.join(", ")}\n📌 Final decision: **${finalLabel.toUpperCase()}**` | |
| }); | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number, | |
| labels: ["ranked"] | |
| }); | |
| } |