Skip to content

Commit b2d1bf0

Browse files
authored
chore(release): allow comments to trigger actions, update releasing docs (#3891)
Updates the release documentation to reflect the new process using the Release Tracking Issue, comments (/prepare, /create-rc, /process-backports), and automated workflows.
1 parent f3fa8da commit b2d1bf0

12 files changed

Lines changed: 468 additions & 124 deletions

File tree

.github/ISSUE_TEMPLATE/release_tracking_template.md

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,21 @@ labels: ['type: release']
1212

1313
## Backports
1414

15-
<details>
16-
<summary><b>How to add backports</b></summary>
17-
18-
To request a backport:
19-
1. Add a new checklist item under the `## Backports` section.
20-
2. The format must be: `- [ ] #<PR_NUMBER>` (e.g., `- [ ] #1234`).
21-
3. Trigger the [Process Backports Workflow][process_backports].
22-
</details>
15+
To request a backport, add it to the checklist below and process it. See [RELEASING.md: How to add backports](https://github.com/bazel-contrib/rules_python/blob/main/RELEASING.md#how-to-add-backports) for details.
2316

2417
---
25-
*Maintainers: Automation will react to changes on this issue.*
2618

27-
<details>
28-
<summary><b>Manual Editing</b></summary>
29-
30-
You can manually edit this issue to control the release flow.
31-
The checklist items use metadata suffix: `| key=value key2=value2`.
32-
- **Retry Prepare Release**: Reset to `- [ ] Prepare Release | status=awaiting-preparation`.
33-
- **Force Task Done**: Check the box `- [x]` and add appropriate metadata (e.g. `status=done`).
34-
</details>
19+
To manually control the release flow, see the [RELEASING.md: Manual Editing](https://github.com/bazel-contrib/rules_python/blob/main/RELEASING.md#manual-editing-of-tracking-issue) section.
3520

3621
<details>
3722
<summary><b>Available Commands</b></summary>
3823

39-
Maintainers can trigger automation by:
40-
- Running manual workflows:
41-
- [Process Backports Workflow][process_backports]
42-
- [Create RC Workflow][create_rc]
43-
- [Promote RC to Final Release Workflow][promote_rc]
44-
- Commenting on this issue (requires the issue to have the `type: release`
45-
label):
46-
- `/prepare` at the beginning of a line to trigger the Release Prepare
47-
workflow.
48-
- `/create-rc` at the beginning of a line to trigger the Create RC
49-
workflow.
50-
- `/process-backports` at the beginning of a line to trigger the Process
51-
Backports workflow.
24+
Comment commands:
25+
- `/prepare`: Determines version, creates tracking issue and preparation PR.
26+
- `/create-rc`: Tags and publishes a new release candidate (RC).
27+
- `/process-backports`: Cherry-picks pending backports.
28+
- `/add-backports <PRs>`: Adds PRs to the backports and processes backports.
29+
- `/promote`: Promotes the latest RC to final release.
5230

31+
See [RELEASING.md](https://github.com/bazel-contrib/rules_python/blob/main/RELEASING.md) for details on how to use them.
5332
</details>
54-
55-
[process_backports]: https://github.com/bazel-contrib/rules_python/actions/workflows/release_process_backports.yaml
56-
[create_rc]: https://github.com/bazel-contrib/rules_python/actions/workflows/release_create_rc.yaml
57-
[promote_rc]: https://github.com/bazel-contrib/rules_python/actions/workflows/release_promote_rc.yaml

.github/workflows/on_issue_comment.yaml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,41 @@ jobs:
2727
outputs:
2828
command: ${{ steps.parse.outputs.command }}
2929
issue_number: ${{ github.event.issue.number }}
30+
backports: ${{ steps.parse.outputs.backports }}
3031
steps:
3132
- name: Parse comment
3233
id: parse
3334
env:
3435
COMMENT_BODY: ${{ github.event.comment.body }}
36+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3537
run: |
3638
if echo "$COMMENT_BODY" | grep -qE '^[[:space:]]*/create-rc([[:space:]]|$)'; then
3739
echo "command=create-rc" >> "$GITHUB_OUTPUT"
3840
elif echo "$COMMENT_BODY" | grep -qE '^[[:space:]]*/prepare([[:space:]]|$)'; then
3941
echo "command=prepare" >> "$GITHUB_OUTPUT"
4042
elif echo "$COMMENT_BODY" | grep -qE '^[[:space:]]*/process-backports([[:space:]]|$)'; then
4143
echo "command=process-backports" >> "$GITHUB_OUTPUT"
44+
elif echo "$COMMENT_BODY" | grep -qE '^[[:space:]]*/add-backports([[:space:]]|$)'; then
45+
args=$(echo "$COMMENT_BODY" | grep -E '^[[:space:]]*/add-backports([[:space:]]|$)' | sed -E 's/^[[:space:]]*\/add-backports[[:space:]]*//')
46+
# Strip leading/trailing spaces and commas
47+
args=$(echo "$args" | sed -e 's/^[[:space:],]*//' -e 's/[[:space:],]*$//')
48+
# Replace internal spaces/commas with single comma
49+
csv=$(echo "$args" | sed -E 's/[[:space:],]+/ /g' | tr ' ' ',')
50+
if [ -n "$csv" ]; then
51+
echo "command=add-backports" >> "$GITHUB_OUTPUT"
52+
echo "backports=$csv" >> "$GITHUB_OUTPUT"
53+
else
54+
echo "command=none" >> "$GITHUB_OUTPUT"
55+
echo "Error: No PRs specified for add-backports." >&2
56+
gh api \
57+
--method POST \
58+
-H "Accept: application/vnd.github+json" \
59+
-H "X-GitHub-Api-Version: 2022-11-28" \
60+
/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \
61+
-f "content=-1"
62+
fi
63+
elif echo "$COMMENT_BODY" | grep -qE '^[[:space:]]*/promote([[:space:]]|$)'; then
64+
echo "command=promote" >> "$GITHUB_OUTPUT"
4265
else
4366
echo "command=none" >> "$GITHUB_OUTPUT"
4467
fi
@@ -61,8 +84,20 @@ jobs:
6184

6285
call_process_backports:
6386
needs: parse_comment
64-
if: needs.parse_comment.outputs.command == 'process-backports'
87+
if: |
88+
needs.parse_comment.outputs.command == 'process-backports' ||
89+
needs.parse_comment.outputs.command == 'add-backports'
6590
uses: ./.github/workflows/release_process_backports.yaml
91+
with:
92+
issue: ${{ needs.parse_comment.outputs.issue_number }}
93+
add_backports: ${{ needs.parse_comment.outputs.command == 'add-backports' && needs.parse_comment.outputs.backports || '' }}
94+
comment_id: "${{ github.event.comment.id }}"
95+
secrets: inherit
96+
97+
call_promote:
98+
needs: parse_comment
99+
if: needs.parse_comment.outputs.command == 'promote'
100+
uses: ./.github/workflows/release_promote_rc.yaml
66101
with:
67102
issue: ${{ needs.parse_comment.outputs.issue_number }}
68103
secrets: inherit

.github/workflows/release_process_backports.yaml

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,28 @@ on:
77
description: 'The Release Tracking Issue Number (e.g., 142)'
88
required: true
99
type: string
10+
add_backports:
11+
description: 'CSV list of PR numbers to add and process (optional)'
12+
required: false
13+
type: string
14+
comment_id:
15+
description: 'The ID of the comment that triggered this run (optional)'
16+
required: false
17+
type: string
1018
workflow_call:
1119
inputs:
1220
issue:
1321
description: 'The Release Tracking Issue Number (e.g., 142)'
1422
required: true
1523
type: string
24+
add_backports:
25+
description: 'CSV list of PR numbers to add and process (optional)'
26+
required: false
27+
type: string
28+
comment_id:
29+
description: 'The ID of the comment that triggered this run (optional)'
30+
required: false
31+
type: string
1632

1733
permissions:
1834
contents: write
@@ -40,7 +56,18 @@ jobs:
4056
4157
- name: Process Pending Backports
4258
run: |
43-
bazel run //tools/private/release -- \
44-
process-backports --issue ${{ inputs.issue }} --remote origin --no-dry-run
59+
ARGS=()
60+
if [ -n "${{ inputs.add_backports }}" ]; then
61+
ARGS+=("--add=${{ inputs.add_backports }}")
62+
fi
63+
if [ -n "${{ inputs.comment_id }}" ]; then
64+
ARGS+=("--triggering-comment=${{ inputs.comment_id }}")
65+
fi
66+
67+
bazel run //tools/private/release -- process-backports \
68+
--issue ${{ inputs.issue }} \
69+
--remote origin \
70+
--no-dry-run \
71+
"${ARGS[@]}"
4572
env:
4673
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release_promote_rc.yaml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ on:
77
description: 'The final version to release (e.g., 0.38.0)'
88
required: true
99
type: string
10+
workflow_call:
11+
inputs:
12+
version:
13+
description: 'The final version to release (e.g., 0.38.0)'
14+
required: false
15+
type: string
16+
issue:
17+
description: 'The tracking issue number'
18+
required: true
19+
type: string
1020

1121
permissions:
1222
contents: write
@@ -33,7 +43,16 @@ jobs:
3343
3444
- name: Run Promote RC
3545
run: |
36-
bazel run //tools/private/release -- \
37-
promote-rc ${{ inputs.version }} --remote origin
46+
ARGS=()
47+
if [ -n "${{ inputs.version }}" ]; then
48+
ARGS+=("${{ inputs.version }}")
49+
fi
50+
if [ -n "${{ inputs.issue }}" ]; then
51+
ARGS+=("--issue" "${{ inputs.issue }}")
52+
fi
53+
ARGS+=("--remote" "origin")
54+
ARGS+=("--no-dry-run")
55+
56+
bazel run //tools/private/release -- promote-rc "${ARGS[@]}"
3857
env:
3958
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

RELEASING.md

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,40 @@ existing Bazel workspace to sanity check functionality.
88

99
## Releasing from HEAD
1010

11-
These are the steps for a regularly scheduled release from HEAD.
11+
Releases are managed using a semi-automated process centered around a GitHub
12+
Release Tracking Issue and automated workflows triggered by comments or issue edits.
13+
14+
> [!NOTE]
15+
> Comment-based commands must be posted by project maintainers (Owner,
16+
> Member, or Collaborator) and must be on their own line (leading and trailing
17+
> whitespace is ignored).
1218
1319
### Steps
1420

15-
1. Update the changelog and replace the version placeholders by running the
16-
release tool. The next version number will be automatically determined
17-
based on the presence of `VERSION_NEXT_*` placeholders and git tags. The
18-
tool will read all news entry files in the `news/` directory, assemble
19-
them into the changelog, and delete the processed news files.
20-
21-
```shell
22-
bazel run //tools/private/release
23-
```
24-
25-
If you want to append news entries to an already existing release section in
26-
the changelog (for example, to update a drafted release or a release
27-
branch), you can specify the version explicitly:
28-
29-
```shell
30-
bazel run //tools/private/release -- X.Y.Z
31-
```
32-
33-
1. Send these changes for review and get them merged.
34-
1. Create a branch for the new release, named `release/X.Y`
35-
```
36-
git branch --no-track release/X.Y upstream/main && git push upstream release/X.Y
37-
```
38-
39-
The next step is to create tags to trigger release workflow, **however**
40-
we start by using release candidate tags (`X.Y.Z-rcN`) before tagging the
41-
final release (`X.Y.Z`).
42-
43-
1. Create release candidate tag and push. The first RC uses `N=0`. Increment
44-
`N` for each RC.
45-
```
46-
git tag X.Y.0-rcN upstream/release/X.Y && git push upstream tag X.Y.0-rcN
47-
```
48-
2. Announce the RC release: see [Announcing Releases]
49-
3. Wait a week for feedback.
50-
* Follow [Patch release with cherry picks] to pull bug fixes into the
51-
release branch.
52-
* Repeat the RC tagging step, incrementing `N`.
53-
4. Finally, tag the final release tag:
54-
```shell
55-
git tag X.Y.0 upstream/release/X.Y && git push upstream tag X.Y.0
56-
```
57-
58-
Release automation will create a GitHub release and BCR pull request.
21+
1. **Prepare the Release**: Run the [Release: Prepare](https://github.com/bazel-contrib/rules_python/actions/workflows/release_prepare.yaml)
22+
workflow manually. You can trigger it from the GitHub Actions UI or using
23+
the GitHub CLI:
24+
```shell
25+
gh workflow run release_prepare.yaml --repo bazel-contrib/rules_python
26+
```
27+
This will automatically determine the next version, create a release tracking
28+
issue, and send a preparation PR.
29+
30+
2. **Approve and Merge**: Approve and merge the PR. Once merged, a release
31+
branch will be created automatically.
32+
33+
3. **Add Backports (if needed)**: If there are backports, add them following
34+
the [How to add backports](#how-to-add-backports) steps.
35+
36+
4. **Create an RC**: Comment `/create-rc` on the tracking issue. All pending
37+
backports must be successfully processed before creating the RC.
38+
39+
5. **Iterate**: Repeat steps 3 and 4 until backports and RCs are no longer
40+
needed.
41+
42+
6. **Finalize the Release**: Comment `/promote` on the tracking issue to
43+
finalize the release.
44+
5945

6046
### Manually triggering the release workflow
6147

@@ -87,6 +73,31 @@ the `VERSION_NEXT_*` placeholders in the codebase. To see what changes are
8773
being accumulated for the next release, review the pending news entries in the
8874
`news/` directory.
8975

76+
## How to add backports
77+
78+
To add backports to an active release, you can use one of the following
79+
methods:
80+
81+
### Method A: Manual Checklist Update
82+
1. Manually add checklist items under the `## Backports` section of the
83+
Release Tracking Issue. The format must be: `- [ ] #<PR_NUMBER>` (e.g.,
84+
`- [ ] #1234`).
85+
2. When ready, comment `/process-backports` on the tracking issue to trigger
86+
processing.
87+
88+
### Method B: Comment Shortcut
89+
1. Comment `/add-backports <PR_NUMBER> [<PR_NUMBER> ...]` (space or comma
90+
separated) on the tracking issue. This will automatically add the PRs to the
91+
checklist and trigger processing.
92+
93+
### Failure Behavior
94+
If a backport fails to process (e.g., due to cherry-pick conflicts):
95+
* The failed backport checklist item will remain unchecked with
96+
`status=error-<reason>`.
97+
* You must resolve the conflict manually: checkout the release branch,
98+
cherry-pick the PR, resolve conflicts, push to remote, and manually check
99+
the box on the tracking issue checklist with `status=done` metadata.
100+
90101
## Patch release with cherry picks
91102

92103
If a patch release from head would contain changes that aren't appropriate for
@@ -105,8 +116,8 @@ The fix being included is commit `deadbeef`.
105116
If multiple commits need to be applied, repeat the `git cherry-pick` step for
106117
each.
107118
108-
Once the release branch is in the desired state, use `git tag` to tag it, as
109-
done with a release from head. Release automation will do the rest.
119+
Once the release branch is in the desired state, comment `/create-rc` on the
120+
tracking issue to tag it, as done with a release from head.
110121
111122
### Announcing releases
112123
@@ -139,6 +150,14 @@ The two points of no return are:
139150
If release steps fail _prior_ to those steps, then its OK to change the tag. You
140151
may need to manually delete the GitHub release.
141152

153+
## Manual Editing of Tracking Issue
154+
155+
You can manually edit the Release Tracking Issue to control the release flow.
156+
The checklist items use metadata suffix: `| key=value key2=value2`.
157+
158+
* **Retry Prepare Release**: Reset the task to `- [ ] Prepare Release | status=awaiting-preparation`.
159+
* **Force Task Done**: Check the box `- [x]` and add appropriate metadata (e.g. `status=done`).
160+
142161
## Secrets
143162

144163
### PyPI user rules-python

0 commit comments

Comments
 (0)