Skip to content

Commit 78976b5

Browse files
committed
chore(governance): check for related issue in new PRs
1 parent 91411f3 commit 78976b5

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
on:
2+
workflow_call:
3+
inputs:
4+
record_pr_workflow_id:
5+
required: true
6+
type: number
7+
secrets:
8+
token:
9+
required: true
10+
# Map the workflow outputs to job outputs
11+
outputs:
12+
prNumber:
13+
description: "The first output string"
14+
value: ${{ jobs.export_pr_details.outputs.prNumber }}
15+
prTitle:
16+
description: "The second output string"
17+
value: ${{ jobs.export_pr_details.outputs.prTitle }}
18+
prBody:
19+
description: "The second output string"
20+
value: ${{ jobs.export_pr_details.outputs.prBody }}
21+
prAuthor:
22+
description: "The second output string"
23+
value: ${{ jobs.export_pr_details.outputs.prAuthor }}
24+
prAction:
25+
description: "The second output string"
26+
value: ${{ jobs.export_pr_details.outputs.prAction }}
27+
28+
name: Export Pull Request details from fork
29+
jobs:
30+
export_pr_details:
31+
runs-on: ubuntu-latest
32+
# Map the job outputs to step outputs
33+
outputs:
34+
prNumber: ${{ steps.prNumber.outputs.prNumber }}
35+
prTitle: ${{ steps.prTitle.outputs.prTitle }}
36+
prBody: ${{ steps.prBody.outputs.prBody }}
37+
prAuthor: ${{ steps.prAuthor.outputs.prAuthor }}
38+
prAction: ${{ steps.prAction.outputs.prAction }}
39+
steps:
40+
- name: "Download artifact"
41+
uses: actions/github-script@v6
42+
# For security, we only download artifacts tied to the successful PR recording workflow
43+
with:
44+
github-token: ${{ inputs.token }}
45+
script: |
46+
const fs = require('fs');
47+
48+
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
49+
owner: context.repo.owner,
50+
repo: context.repo.repo,
51+
run_id: ${{inputs.record_pr_workflow_id}},
52+
});
53+
54+
const matchArtifact = artifacts.data.artifacts.filter(artifact => artifact.name == "pr")[0];
55+
56+
const artifact = await github.rest.actions.downloadArtifact({
57+
owner: context.repo.owner,
58+
repo: context.repo.repo,
59+
artifact_id: matchArtifact.id,
60+
archive_format: 'zip',
61+
});
62+
63+
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(artifact.data));
64+
# NodeJS standard library doesn't provide ZIP capabilities; use system `unzip` command instead
65+
- run: unzip pr.zip
66+
- id: prNumber
67+
run: echo ::set-output name=prNumber::$(cat ./number)
68+
- id: prTitle
69+
run: echo ::set-output name=prTitle::$(cat ./title)
70+
- id: prBody
71+
run: echo ::set-output name=prBody::$(cat ./body)
72+
- id: prAuthor
73+
run: echo ::set-output name=prAuthor::$(cat ./author)
74+
- id: prAction
75+
run: echo ::set-output name=prAction::$(cat ./action)

.github/workflows/on_opened_pr.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
on:
2+
workflow_run:
3+
workflows: ["Record PR number"]
4+
types:
5+
- completed
6+
7+
env:
8+
BLOCK_LABEL: "do-not-merge"
9+
BLOCK_REASON_LABEL: "need-issue"
10+
11+
jobs:
12+
get_pr_details:
13+
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
14+
uses: ./.github/workflows/lib/export_pr_details.yml
15+
with:
16+
record_pr_workflow_id: ${{ github.event.workflow_run.id }}
17+
secrets:
18+
token: ${{ secrets.GITHUB_TOKEN }}
19+
check_related_issue:
20+
needs: get_pr_details
21+
if: >
22+
${{ needs.get_pr_details.outputs.prAuthor != 'dependabot[bot]' &&
23+
needs.get_pr_details.outputs.prAction == 'opened'
24+
}}
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: "Ensure related issue is present"
28+
uses: actions/github-script@v6
29+
with:
30+
# Maintenance: convert into a standalone JS like post_release.js
31+
script: |
32+
const prBody = ${{ needs.get_pr_details.outputs.prBody }};
33+
const prNumber = ${{ needs.get_pr_details.outputs.prNumber }};
34+
const blockLabel = process.env.BLOCK_LABEL;
35+
const blockReasonLabel = process.env.BLOCK_REASON_LABEL;
36+
37+
const RELATED_ISSUE_REGEX = /Issue number:.+(\d)/
38+
39+
const matcher = new RegExp(RELATED_ISSUE_REGEX)
40+
const isMatch = matcher.exec(prBody)
41+
if (isMatch == null) {
42+
console.info(`No related issue found, maybe the author didn't use the template but there is one.`)
43+
44+
let msg = `⚠️ No related issues found. Please ensure there is an open issue related to this change to avoid significant delays or closure. ⚠️`;
45+
await github.rest.issues.createComment({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
body: msg,
49+
issue_number: prNumber,
50+
});
51+
52+
await github.rest.issues.addLabels({
53+
issue_number: prNumber,
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
labels: [blockLabel, blockReasonLabel]
57+
})
58+
}

.github/workflows/record_pr.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515
mkdir -p ./pr
1616
echo ${{ github.event.number }} > ./pr/number
1717
echo "${{ github.event.pull_request.title }}" > ./pr/title
18+
echo "${{ github.event.pull_request.body }}" > ./pr/body
19+
echo "${{ github.event.pull_request.user.login }}" > ./pr/author
20+
echo "${{ github.event.action }}" > ./pr/action
1821
- uses: actions/upload-artifact@v3
1922
with:
2023
name: pr

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,5 @@ api/
304304
site/
305305
!404.html
306306
!docs/overrides/*.html
307+
308+
!.github/workflows/lib

0 commit comments

Comments
 (0)