Skip to content

Commit 8442bc0

Browse files
committed
Release process: Automatically rebuild PRs
1 parent c8a3492 commit 8442bc0

4 files changed

Lines changed: 80 additions & 18 deletions

File tree

.github/actions/prepare-mergeback-branch/action.yml

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,38 @@ runs:
4141
git add .
4242
git commit -m "Update changelog and version after ${VERSION}"
4343
44-
git push origin "${NEW_BRANCH}"
44+
# Update the build artifacts with the new version number
45+
- name: Rebuild the Action
46+
shell: bash
47+
run: |
48+
set -exu
49+
npm ci
50+
npm run build
51+
52+
- name: Check for rebuild changes
53+
id: rebuild_changes
54+
shell: bash
55+
run: |
56+
set -exu
57+
git add --all
58+
if git diff --cached --quiet; then
59+
echo "has_changes=false" >> "${GITHUB_OUTPUT}"
60+
else
61+
echo "has_changes=true" >> "${GITHUB_OUTPUT}"
62+
fi
63+
64+
- name: Commit rebuild
65+
if: steps.rebuild_changes.outputs.has_changes == 'true'
66+
shell: bash
67+
run: |
68+
set -exu
69+
git commit -m "Rebuild"
70+
71+
- name: Push mergeback branch
72+
shell: bash
73+
env:
74+
NEW_BRANCH: "${{ inputs.branch }}"
75+
run: git push origin "${NEW_BRANCH}"
4576

4677
- name: Create PR
4778
shell: bash
@@ -60,8 +91,6 @@ runs:
6091
6192
Please do the following:
6293
63-
- [ ] Remove and re-add the "Rebuild" label to the PR to trigger just this workflow.
64-
- [ ] Wait for the "Rebuild" workflow to push a commit updating the distribution files.
6594
- [ ] Mark the PR as ready for review to trigger the full set of PR checks.
6695
- [ ] Approve and merge the PR. When merging the PR, make sure "Create a merge commit" is
6796
selected rather than "Squash and merge" or "Rebase and merge".
@@ -74,7 +103,6 @@ runs:
74103
--head "${NEW_BRANCH}" \
75104
--base "${BASE_BRANCH}" \
76105
--title "${pr_title}" \
77-
--label "Rebuild" \
78106
--body "${pr_body}" \
79107
--assignee "${GITHUB_ACTOR}" \
80108
--draft

.github/actions/release-initialise/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ runs:
1818
- name: Set up Node
1919
uses: actions/setup-node@v6
2020
with:
21-
node-version: 20
22-
cache: 'npm'
21+
node-version: 24
22+
cache: 'npm' # shared with the "Rebuild Action" workflow
2323

2424
- name: Set up Python
2525
uses: actions/setup-python@v6

.github/update-release-branch.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
# Changing it requires a transition period where both old and new versions are supported.
2020
BACKPORT_COMMIT_MESSAGE = 'Update version and changelog for v'
2121

22+
# Commit message used for rebuild commits, both those produced by this script and those produced
23+
# by the `Rebuild Action` workflow (`.github/workflows/rebuild.yml`).
24+
REBUILD_COMMIT_MESSAGE = 'Rebuild'
25+
2226
# Name of the remote
2327
ORIGIN = 'origin'
2428

@@ -43,6 +47,28 @@ def run_git(*args, allow_non_zero_exit_code=False):
4347
raise Exception(f'Call to {" ".join(cmd)} exited with code {p.returncode} stderr: {p.stderr.decode("ascii")}.')
4448
return p.stdout.decode('ascii')
4549

50+
# Runs the given command, streaming output to the console.
51+
# Raises an error if the command does not exit successfully.
52+
def run_command(*args):
53+
cmd = list(args)
54+
print(f'Running `{" ".join(cmd)}`.')
55+
subprocess.run(cmd, check=True)
56+
57+
# Rebuilds the action and commits any changes.
58+
def rebuild_action():
59+
# For backports, the only source-level change vs the source branch is the new version number,
60+
# so we just need to refresh the version embedded in `lib/`.
61+
run_command('npm', 'ci')
62+
run_command('npm', 'run', 'build')
63+
64+
run_git('add', '--all')
65+
# `git diff --cached --quiet` exits 0 if there are no staged changes, 1 if there are.
66+
if subprocess.run(['git', 'diff', '--cached', '--quiet']).returncode == 0:
67+
print('Rebuild produced no changes; skipping Rebuild commit.')
68+
else:
69+
run_git('commit', '-m', REBUILD_COMMIT_MESSAGE)
70+
print('Created Rebuild commit.')
71+
4672
# Returns true if the given branch exists on the origin remote
4773
def branch_exists_on_remote(branch_name):
4874
return run_git('ls-remote', '--heads', ORIGIN, branch_name).strip() != ''
@@ -98,20 +124,18 @@ def open_pr(
98124
body.append('Please do the following:')
99125
if len(conflicted_files) > 0:
100126
body.append(' - [ ] Ensure `package.json` file contains the correct version.')
101-
body.append(' - [ ] Add commits to this branch to resolve the merge conflicts ' +
127+
body.append(' - [ ] Add a commit to this branch to resolve the merge conflicts ' +
102128
'in the following files:')
103-
body.extend([f' - [ ] `{file}`' for file in conflicted_files])
129+
body.extend([f' - `{file}`' for file in conflicted_files])
130+
body.append('')
131+
body.append(' Rebuild the Action (`npm run build`) and add any changes to the built output in `lib` to this commit.')
104132
body.append(' - [ ] Ensure another maintainer has reviewed the additional commits you added to this ' +
105133
'branch to resolve the merge conflicts.')
106134
body.append(' - [ ] Ensure the CHANGELOG displays the correct version and date.')
107135
body.append(' - [ ] Ensure the CHANGELOG includes all relevant, user-facing changes since the last release.')
108136
body.append(f' - [ ] Check that there are not any unexpected commits being merged into the `{target_branch}` branch.')
109137
body.append(' - [ ] Ensure the docs team is aware of any documentation changes that need to be released.')
110138

111-
if not is_primary_release:
112-
body.append(' - [ ] Remove and re-add the "Rebuild" label to the PR to trigger just this workflow.')
113-
body.append(' - [ ] Wait for the "Rebuild" workflow to push a commit updating the distribution files.')
114-
115139
body.append(' - [ ] Mark the PR as ready for review to trigger the full set of PR checks.')
116140
body.append(' - [ ] Approve and merge this PR. Make sure `Create a merge commit` is selected rather than `Squash and merge` or `Rebase and merge`.')
117141

@@ -120,13 +144,11 @@ def open_pr(
120144
body.append(' - [ ] Merge all backport PRs to older release branches, that will automatically be created once this PR is merged.')
121145

122146
title = f'Merge {source_branch} into {target_branch}'
123-
labels = ['Rebuild'] if not is_primary_release else []
124147

125148
# Create the pull request
126149
# PR checks won't be triggered on PRs created by Actions. Therefore mark the PR as draft so that
127150
# a maintainer can take the PR out of draft, thereby triggering the PR checks.
128151
pr = repo.create_pull(title=title, body='\n'.join(body), head=new_branch_name, base=target_branch, draft=True)
129-
pr.add_to_labels(*labels)
130152
print(f'Created PR #{str(pr.number)}')
131153

132154
# Assign the conductor
@@ -385,8 +407,9 @@ def main():
385407
# releases.
386408
run_git('revert', vOlder_update_commits[0], '--no-edit')
387409

388-
# Also revert the "Rebuild" commit created by Actions.
389-
rebuild_commit = run_git('log', '--grep', '^Rebuild$', '--format=%H').split()[0]
410+
# Also revert the "Rebuild" commit, whether created by this script or by the
411+
# `Rebuild Action` workflow.
412+
rebuild_commit = run_git('log', '--grep', f'^{REBUILD_COMMIT_MESSAGE}$', '--format=%H').split()[0]
390413
print(f' Reverting {rebuild_commit}')
391414
run_git('revert', rebuild_commit, '--no-edit')
392415

@@ -401,9 +424,10 @@ def main():
401424
run_git('add', '.')
402425
run_git('commit', '--no-edit')
403426

404-
# Migrate the package version number from a vLatest version number to a vOlder version number
427+
# Migrate the package version number from a vLatest version number to a vOlder version number.
428+
# `package-lock.json` is updated as part of the subsequent rebuild step (see `rebuild_action`).
405429
print(f'Setting version number to {version} in package.json')
406-
replace_version_package_json(get_current_version(), version) # We rely on the `Rebuild` workflow to update package-lock.json
430+
replace_version_package_json(get_current_version(), version)
407431
run_git('add', 'package.json')
408432

409433
# Migrate the changelog notes from vLatest version numbers to vOlder version numbers
@@ -426,6 +450,13 @@ def main():
426450
run_git('add', 'CHANGELOG.md')
427451
run_git('commit', '-m', f'Update changelog for v{version}')
428452

453+
if not is_primary_release:
454+
if len(conflicted_files) == 0:
455+
print('Rebuilding the Action.')
456+
rebuild_action()
457+
else:
458+
print(f'Skipping automatic rebuild because the merge produced conflicts in {conflicted_files}.')
459+
429460
run_git('push', ORIGIN, new_branch_name)
430461

431462
# Open a PR to update the branch

.github/workflows/post-release-mergeback.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ jobs:
4848
with:
4949
fetch-depth: 0 # ensure we have all tags and can push commits
5050
- uses: actions/setup-node@v6
51+
with:
52+
node-version: 24
53+
cache: 'npm' # shared with the "Rebuild Action" workflow
5154
- uses: actions/setup-python@v6
5255
with:
5356
python-version: '3.12'

0 commit comments

Comments
 (0)