diff --git a/.github/assets/label_pr.js b/.github/assets/label_pr.js new file mode 100644 index 0000000..2bdd740 --- /dev/null +++ b/.github/assets/label_pr.js @@ -0,0 +1,65 @@ +// Filter function for labels we do not want on PRs automatically. +function shouldIncludeLabel(label) { + const isStatus = label.startsWith("S-"); + const isPreventStale = label === "M-prevent-stale"; + const isDifficulty = label.startsWith("D-"); + + return !isStatus && !isPreventStale && !isDifficulty; +} + +// Get the issue number from an issue link in the forms +// ` ` or ` #`. +function getIssueLink(repoUrl, body) { + if (!body) return undefined; + + const urlPattern = new RegExp( + `(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) ${repoUrl}/issues/(?\\d+)`, + "i" + ); + const issuePattern = new RegExp( + `(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #(?\\d+)`, + "i" + ); + + const urlRe = body.match(urlPattern); + const issueRe = body.match(issuePattern); + if (urlRe?.groups?.issue_number) { + return urlRe.groups.issue_number; + } else { + return issueRe?.groups?.issue_number; + } +} + +module.exports = async ({ github, context }) => { + try { + const prNumber = context.payload.pull_request.number; + const prBody = context.payload.pull_request.body; + const repo = context.repo; + + const repoUrl = context.payload.repository.html_url; + const issueNumber = getIssueLink(repoUrl, prBody); + if (!issueNumber) { + console.log("No issue reference found in PR description."); + return; + } + + const issue = await github.rest.issues.get({ + ...repo, + issue_number: issueNumber, + }); + + const issueLabels = issue.data.labels + .map((label) => label.name) + .filter(shouldIncludeLabel); + if (issueLabels.length > 0) { + await github.rest.issues.addLabels({ + ...repo, + issue_number: prNumber, + labels: issueLabels, + }); + } + } catch (err) { + console.error("Failed to label PR"); + console.error(err); + } +}; diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml new file mode 100644 index 0000000..78da262 --- /dev/null +++ b/.github/workflows/label-pr.yml @@ -0,0 +1,23 @@ +name: Label PRs + +on: + pull_request: + types: [opened] + +jobs: + label_prs: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Label PRs + uses: actions/github-script@v8 + with: + script: | + const label_pr = require('./.github/assets/label_pr.js') + await label_pr({github, context})