Skip to content

Commit 620264e

Browse files
authored
GHA to prompt reviewers to think about dependency changes when backporting (#37800)
1 parent 2e5b5de commit 620264e

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
name: Backported Dependency Changes
3+
4+
on:
5+
# The pull_request_target trigger event allows PRs raised from forks to have write permissions and access secrets.
6+
# We uses it in this workflow to enable writing comments to the PR.
7+
pull_request_target:
8+
types:
9+
- opened
10+
- synchronize
11+
- labeled
12+
- unlabeled
13+
pull_request:
14+
types:
15+
- opened
16+
- synchronize
17+
- labeled
18+
- unlabeled
19+
20+
# This workflow runs for not-yet-reviewed external contributions.
21+
# Following a pull_request_target trigger the workflow would have write permissions,
22+
# so we intentionally restrict the permissions to only include write access on pull-requests.
23+
permissions:
24+
contents: read
25+
pull-requests: write
26+
27+
jobs:
28+
deps-change-comment:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: "Identify if go.mod files have changed"
32+
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
33+
id: changedfiles
34+
with:
35+
filters: |
36+
root-go-mod:
37+
- 'go.mod'
38+
nested-go-mod:
39+
- '**/*/go.mod'
40+
list-files: json
41+
42+
# This step will create or delete an existing comment; responds to changes in the PR.
43+
- name: "Comment on PR if necessary"
44+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
45+
with:
46+
script: |
47+
// SETUP - values needed for function definitions below.
48+
const commentStart = "## Backported dependency change";
49+
50+
const { number: issue_number } = context.issue;
51+
const { owner, repo } = context.repo;
52+
53+
// List all comments
54+
const allComments = (await github.rest.issues.listComments({
55+
issue_number,
56+
owner,
57+
repo,
58+
})).data;
59+
const existingComment = allComments.find(c => c.body.startsWith(commentStart));
60+
const comment_id = existingComment?.id;
61+
62+
async function createOrUpdateComment(commentDetails) {
63+
const body = commentStart + "\n\n" + commentDetails;
64+
let resp
65+
if (existingComment) {
66+
resp = await github.rest.issues.updateComment({
67+
owner,
68+
repo,
69+
comment_id,
70+
body,
71+
});
72+
} else {
73+
resp = await github.rest.issues.createComment({
74+
owner,
75+
repo,
76+
issue_number,
77+
body,
78+
});
79+
}
80+
if (resp.status != 200){
81+
console.error("creating/updating comment failed, here's the response:", resp )
82+
core.setFailed("creating/updating comment failed with status code " + resp.status)
83+
}
84+
}
85+
86+
async function deleteCommentIfExists() {
87+
if (existingComment) {
88+
const resp = await github.rest.issues.deleteComment({
89+
owner,
90+
repo,
91+
comment_id,
92+
});
93+
if (resp.status >= 300 ){
94+
// Allow all status codes in 2XX range; deleting a non-existing comment is 204
95+
console.error("deleting comment failed, here's the response:", resp )
96+
core.setFailed("deleting comment failed with status code " + resp.status)
97+
}
98+
}
99+
}
100+
101+
async function getPrLabels() {
102+
const labelsResp = await github.rest.issues.listLabelsOnIssue({
103+
owner,
104+
repo,
105+
issue_number,
106+
});
107+
if (labelsResp.status != 200){
108+
console.error("getting the PR's labels failed, here's the response:", resp )
109+
core.setFailed("getting the PR's labels failed with status code " + resp.status)
110+
}
111+
return labelsResp
112+
}
113+
114+
// INSPECT PR & UPDATE COMMENT
115+
116+
const labels = await getPrLabels()
117+
const filteredLabels = labels.data.filter( label => {
118+
return label.name.includes("backport")
119+
})
120+
const hasBackportLabel = filteredLabels.length > 0
121+
const changedRootGoMod = ${{steps.changedfiles.outputs.root-go-mod}};
122+
const changedNestedGoMod = ${{steps.changedfiles.outputs.nested-go-mod}};
123+
const changesPresent = changedRootGoMod || changedNestedGoMod
124+
if (!changesPresent){
125+
console.log("This PR isn't attempting to change dependencies. No comment needed.")
126+
await deleteCommentIfExists()
127+
} else if (!hasBackportLabel) {
128+
console.log(`This PR contains changes to dependency-related files but doesn't have a backport label. No comment needed.` +
129+
`\nChanged root go.mod? = ${changedRootGoMod}`+
130+
`\nChanged a nested go.mod? = ${changedNestedGoMod}`)
131+
await deleteCommentIfExists()
132+
} else {
133+
console.log("This PR contains changes to dependency-related files and is labelled for backport. Making sure comment is present.")
134+
const comment = "This PR makes changes to dependencies in go.mod file(s) and is labelled for backport.\n\n" +
135+
"Notice to the maintainer: Before merging the backport of this PR please follow our security scanning processes."
136+
await createOrUpdateComment(comment)
137+
}

0 commit comments

Comments
 (0)