Skip to content

Commit 0653842

Browse files
authored
Update downstream check script on 21.x branch (#466)
The downstream change checking script has received a number of improvements on trunk which should be cherry-picked to the release branch, ahead of changes that fail to make branching being made. This includes: Check review approvals in downstream changes 0361b4e #408 Disable review approval portion of downstream change check 5522f06 #449 Allow additional whitespace in downstream issue tagging 52fc4c2 #459 Together, these make the following changes: * The GutHub token being used is changed to one automatically generated for the Action, instead of the LLVM Sync token which has different permissions. * When a pull request is detected as making a downstream change, a comment is left by the bot to explain the downstream patch policy, and the existence of the check. * The pull request making the downstream change, and the tracking issue are both automatically labelled with the downstream change tag. * The regular expression for searching for the tagging line in the pull request has been relaxed to allow for additional whietspace. * A dry run option is added to script so it can be run to check without the aboce automatic comment/labelling. This patch series also added an additional check on who has reviewed the downsteam change, but this check is reverted within the same series.
1 parent d9463ed commit 0653842

File tree

2 files changed

+110
-11
lines changed

2 files changed

+110
-11
lines changed

.github/workflows/check_downstream_changes.yml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,10 @@ jobs:
3434
if: github.repository == 'arm/arm-toolchain'
3535

3636
steps:
37-
# Generate a token for gh tool
38-
- name: Configure Access Token
39-
uses: actions/create-github-app-token@v1
40-
id: generate-token
41-
with:
42-
app-id: ${{ secrets.SYNC_APP_ID }}
43-
private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }}
44-
4537
- name: Checkout
4638
uses: actions/checkout@v4
4739

4840
- name: Run Check Script
4941
run: python3 arm-software/ci/check_downstream_changes.py --repo ${{ github.repository }} --pr ${{ github.event.pull_request.number }}
5042
env:
51-
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
43+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

arm-software/ci/check_downstream_changes.py

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
logger = logging.getLogger(__name__)
3030

3131
MERGE_IGNORE_PATHSPEC_FILE = Path(__file__).parent / ".automerge_ignore"
32+
HELP_COMMENT_TEXT = """This pull review modifies files outside of the `arm-software` directory, so please ensure it follows the [Downstream Patch Policy](https://github.com/arm/arm-toolchain/blob/arm-software/CONTRIBUTING.md#downstream-patch-policy).
33+
An automated check will test if the tagging requirements have been met. Please wait for approving reviews from both Arm Toolchain for Embedded and Arm Toolchain for Linux teams before merging."""
34+
DOWNSTREAM_CHANGE_LABEL = "downstream-change"
3235

3336

3437
# Check gh is working before using it
@@ -55,7 +58,16 @@ def check_gh_status() -> None:
5558

5659
# Use gh to get information about the pull request.
5760
def get_pr_json(pr_num: str, repo: str) -> dict:
58-
args = ["gh", "pr", "view", pr_num, "--repo", repo, "--json", "body,files,title"]
61+
args = [
62+
"gh",
63+
"pr",
64+
"view",
65+
pr_num,
66+
"--repo",
67+
repo,
68+
"--json",
69+
"body,comments,files,labels,title",
70+
]
5971
logger.debug(f"Running `{shlex.join(args)}`")
6072
try:
6173
p = subprocess.run(
@@ -159,7 +171,7 @@ def has_downstream_changes(input_json: dict) -> bool:
159171
def find_pr_issue(input_json: dict) -> str:
160172
logger.debug("body text: %s", input_json["body"])
161173
matches = re.findall(
162-
"^((?:removes )?downstream issue: *#([0-9]+))",
174+
r"^\s*((?:removes )?downstream issue: *#([0-9]+))",
163175
input_json["body"],
164176
flags=re.I | re.M,
165177
)
@@ -180,6 +192,91 @@ def find_pr_issue(input_json: dict) -> str:
180192
return issue_num
181193

182194

195+
# Add a label to a pull request.
196+
def add_pr_label(pr_num: str, repo: str, input_json: dict) -> None:
197+
# Check if the issue is already labelled.
198+
for label_json in input_json["labels"]:
199+
if label_json["name"] == DOWNSTREAM_CHANGE_LABEL:
200+
return
201+
args = [
202+
"gh",
203+
"pr",
204+
"edit",
205+
pr_num,
206+
"--repo",
207+
repo,
208+
"--add-label",
209+
DOWNSTREAM_CHANGE_LABEL,
210+
]
211+
logger.debug(f"Running `{shlex.join(args)}`")
212+
try:
213+
p = subprocess.run(
214+
args,
215+
check=True,
216+
capture_output=True,
217+
text=True,
218+
)
219+
except subprocess.CalledProcessError as error:
220+
logger.error(
221+
f"Check error. Failure adding pr label\ncmd:{shlex.join(error.cmd)}\ncode:{error.returncode}\nstdout:{error.stdout}\nstderr:{error.stderr}"
222+
)
223+
sys.exit(1)
224+
225+
226+
# Add a label to an issue.
227+
def add_issue_label(issue_num: str, repo: str, input_json: dict) -> None:
228+
# Check if the issue is already labelled.
229+
for label_json in input_json["labels"]:
230+
if label_json["name"] == DOWNSTREAM_CHANGE_LABEL:
231+
return
232+
args = [
233+
"gh",
234+
"issue",
235+
"edit",
236+
issue_num,
237+
"--repo",
238+
repo,
239+
"--add-label",
240+
DOWNSTREAM_CHANGE_LABEL,
241+
]
242+
logger.debug(f"Running `{shlex.join(args)}`")
243+
try:
244+
p = subprocess.run(
245+
args,
246+
check=True,
247+
capture_output=True,
248+
text=True,
249+
)
250+
except subprocess.CalledProcessError as error:
251+
logger.error(
252+
f"Check error. Failure adding issue label\ncmd:{shlex.join(error.cmd)}\ncode:{error.returncode}\nstdout:{error.stdout}\nstderr:{error.stderr}"
253+
)
254+
sys.exit(1)
255+
256+
257+
# Add a comment explaining the additional requirements for downstream changes
258+
def add_help_comment(pr_num: str, repo: str, input_json: dict) -> None:
259+
# Check if the comment has already been made first, so as not to repost
260+
# every time the script runs.
261+
for comment_json in input_json["comments"]:
262+
if comment_json["body"] == HELP_COMMENT_TEXT:
263+
return
264+
args = ["gh", "pr", "comment", pr_num, "--repo", repo, "--body", HELP_COMMENT_TEXT]
265+
logger.debug(f"Running `{shlex.join(args)}`")
266+
try:
267+
p = subprocess.run(
268+
args,
269+
check=True,
270+
capture_output=True,
271+
text=True,
272+
)
273+
except subprocess.CalledProcessError as error:
274+
logger.error(
275+
f"Check error. Failure adding comment\ncmd:{shlex.join(error.cmd)}\ncode:{error.returncode}\nstdout:{error.stdout}\nstderr:{error.stderr}"
276+
)
277+
sys.exit(1)
278+
279+
183280
def main():
184281
parser = argparse.ArgumentParser(description=__doc__)
185282
parser.add_argument(
@@ -197,6 +294,11 @@ def main():
197294
action="store_true",
198295
help="Print verbose log messages",
199296
)
297+
parser.add_argument(
298+
"--dryrun",
299+
action="store_true",
300+
help="Don't make modifications such as comments or labels",
301+
)
200302

201303
args = parser.parse_args()
202304

@@ -213,6 +315,9 @@ def main():
213315

214316
link_text = "Please check https://github.com/arm/arm-toolchain/blob/arm-software/CONTRIBUTING.md#downstream-patch-policy for information on the downstream patch policy and how changes need to be tracked."
215317
if needs_tagging:
318+
if not args.dryrun:
319+
add_pr_label(args.pr, args.repo, pr_json)
320+
add_help_comment(args.pr, args.repo, pr_json)
216321
if issue_num is None:
217322
logger.info(
218323
f"Check failed. Pull request #{args.pr} contains downstream changes, but does not have a correctly formatted link to a downstream tracking issue. {link_text}"
@@ -225,6 +330,8 @@ def main():
225330
)
226331
sys.exit(1)
227332
else:
333+
if not args.dryrun:
334+
add_issue_label(args.pr, args.repo, pr_json)
228335
logger.info(
229336
f"Check passed. Pull request #{args.pr} contains downstream changes, and a correctly formatted link to a downstream tracking issue."
230337
)

0 commit comments

Comments
 (0)