11name : Label PR based on title
22
3- # pull_request_target event sends an admin GH token to forks
4- # this however depends on another workflow so it all runs within the base repo safely
5- # "Record PR number" workflow safely captures PR title and number
6- # This workflow uses this information to label the PR based on its semantic title
73on :
84 workflow_run :
9- workflows : ["Record PR number "]
5+ workflows : ["Record PR details "]
106 types :
117 - completed
128
139jobs :
14- label_pr :
15- runs-on : ubuntu-latest
10+ get_pr_details :
1611 # Guardrails to only ever run if PR recording workflow was indeed
1712 # run in a PR event and ran successfully
18- if : >
19- ${{ github.event.workflow_run.event == 'pull_request' &&
20- github.event.workflow_run.conclusion == 'success' }}
13+ if : ${{ github.event.workflow_run.conclusion == 'success' }}
14+ uses : ./.github/workflows/reusable_export_pr_details.yml
15+ with :
16+ record_pr_workflow_id : ${{ github.event.workflow_run.id }}
17+ workflow_origin : ${{ github.event.repository.full_name }}
18+ secrets :
19+ token : ${{ secrets.GITHUB_TOKEN }}
20+ label_pr :
21+ needs : get_pr_details
22+ runs-on : ubuntu-latest
2123 steps :
22- - name : ' Download artifact'
23- uses : actions/github-script@v6
24- # For security, we only download artifacts tied to the successful PR recording workflow
25- with :
26- script : |
27- const fs = require('fs');
28-
29- const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
30- owner: context.repo.owner,
31- repo: context.repo.repo,
32- run_id: ${{github.event.workflow_run.id }},
33- });
34-
35- const matchArtifact = artifacts.data.artifacts.filter(artifact => artifact.name == "pr")[0];
36-
37- const artifact = await github.rest.actions.downloadArtifact({
38- owner: context.repo.owner,
39- repo: context.repo.repo,
40- artifact_id: matchArtifact.id,
41- archive_format: 'zip',
42- });
43-
44- fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(artifact.data));
45- # NodeJS standard library doesn't provide ZIP capabilities; use system `unzip` command instead
46- - run : unzip pr.zip
47-
48- - name : ' Label PR based on title'
24+ - name : Checkout repository
25+ uses : actions/checkout@v3
26+ - name : " Label PR based on title"
4927 uses : actions/github-script@v6
28+ env :
29+ PR_NUMBER : ${{ needs.get_pr_details.outputs.prNumber }}
30+ PR_TITLE : ${{ needs.get_pr_details.outputs.prTitle }}
5031 with :
5132 github-token : ${{ secrets.GITHUB_TOKEN }}
5233 # This safely runs in our base repo, not on fork
5334 # thus allowing us to provide a write access token to label based on PR title
5435 # and label PR based on semantic title accordingly
5536 script : |
56- const fs = require('fs');
57- const pr_number = Number(fs.readFileSync('./number'));
58- const pr_title = fs.readFileSync('./title', 'utf-8').trim();
59-
60- const FEAT_REGEX = /feat(\((\w+)\))?(\:.+)/
61- const BUG_REGEX = /(fix|bug)(\((\w+)\))?(\:.+)/
62- const DOCS_REGEX = /(docs|doc)(\((\w+)\))?(\:.+)/
63- const CHORE_REGEX = /(chore)(\((\w+)\))?(\:.+)/
64- const DEPRECATED_REGEX = /(deprecated)(\((\w+)\))?(\:.+)/
65- const REFACTOR_REGEX = /(refactor)(\((\w+)\))?(\:.+)/
66-
67- const labels = {
68- "feature": FEAT_REGEX,
69- "bug": BUG_REGEX,
70- "documentation": DOCS_REGEX,
71- "internal": CHORE_REGEX,
72- "enhancement": REFACTOR_REGEX,
73- "deprecated": DEPRECATED_REGEX,
74- }
75-
76- for (const label in labels) {
77- const matcher = new RegExp(labels[label])
78- const isMatch = matcher.exec(pr_title)
79- if (isMatch != null) {
80- console.info(`Auto-labeling PR ${pr_number} with ${label}`)
81-
82- await github.rest.issues.addLabels({
83- issue_number: pr_number,
84- owner: context.repo.owner,
85- repo: context.repo.repo,
86- labels: [label]
87- })
88-
89- break
90- }
91- }
37+ const script = require('.github/scripts/label_pr_based_on_title.js')
38+ await script({github, context, core})
0 commit comments