From 8001a9a6bfeab08065e44f75f0824a5fbfa1d6b7 Mon Sep 17 00:00:00 2001 From: Alfredo Gutierrez Date: Thu, 23 May 2024 15:41:58 -0600 Subject: [PATCH] Adding a GHA to check that PRs have label(s) and milestone assigned. Signed-off-by: Alfredo Gutierrez --- .github/scripts/check-pr.js | 66 +++++++++++++++++++ .../workflows/pr-label-milestone-check.yml | 27 ++++++++ 2 files changed, 93 insertions(+) create mode 100644 .github/scripts/check-pr.js create mode 100644 .github/workflows/pr-label-milestone-check.yml diff --git a/.github/scripts/check-pr.js b/.github/scripts/check-pr.js new file mode 100644 index 0000000000..bdee5cf2bd --- /dev/null +++ b/.github/scripts/check-pr.js @@ -0,0 +1,66 @@ +const axios = require('axios'); + +const githubToken = process.env.GITHUB_TOKEN; +const { GITHUB_REPOSITORY, GITHUB_PR_NUMBER } = process.env; + +const [owner, repo] = GITHUB_REPOSITORY.split('/'); + +async function getPRDetails() { + const url = `https://api.github.com/repos/${owner}/${repo}/pulls/${GITHUB_PR_NUMBER}`; + const response = await axios.get(url, { + headers: { + Authorization: `token ${githubToken}` + } + }); + return response.data; +} + +async function getIssueDetails(issueNumber) { + const url = `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`; + const response = await axios.get(url, { + headers: { + Authorization: `token ${githubToken}` + } + }); + return response.data; +} + +async function run() { + try { + const pr = await getPRDetails(); + const { labels: prLabels, milestone: prMilestone, body: prBody } = pr; + + if (prLabels.length === 0) { + throw new Error('The PR has no labels.'); + } + if (!prMilestone) { + throw new Error('The PR has no milestone.'); + } + + const issueNumberMatches = prBody.match(/#(\d+)/g); + + if (!issueNumberMatches) { + console.log('No associated issues found in PR description.'); + } else { + for (const match of issueNumberMatches) { + const issueNumber = match.replace('#', ''); + const issue = await getIssueDetails(issueNumber); + const { labels: issueLabels, milestone: issueMilestone } = issue; + + if (issueLabels.length === 0) { + throw new Error(`Associated issue #${issueNumber} has no labels.`); + } + if (!issueMilestone) { + throw new Error(`Associated issue #${issueNumber} has no milestone.`); + } + } + } + + console.log('PR and all associated issues have labels and milestones.'); + } catch (error) { + console.error(error.message); + process.exit(1); + } +} + +run(); diff --git a/.github/workflows/pr-label-milestone-check.yml b/.github/workflows/pr-label-milestone-check.yml new file mode 100644 index 0000000000..6bccff5aee --- /dev/null +++ b/.github/workflows/pr-label-milestone-check.yml @@ -0,0 +1,27 @@ +name: PR Label and Milestone Check + +on: + pull_request: + types: [opened, edited, labeled, unlabeled, synchronize] + +jobs: + check_pr: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + + - name: Install dependencies + run: npm install axios + + - name: Check PR labels and milestones + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_NUMBER: ${{ github.event.number }} + run: node .github/scripts/check-pr.js