Skip to content

Commit 3af063c

Browse files
feat(ci): add PR bump preview workflow
Adds a workflow that runs cz bump --dry-run on incoming pull requests and posts (or updates) a sticky comment summarising the would-be version bump and changelog entries. This makes unexpected version bumps visible to reviewers before merging, addressing #1510. The pattern is documented in docs/tutorials/github_actions.md so other projects can copy/paste the same workflow. Closes #1510 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a656af5 commit 3af063c

2 files changed

Lines changed: 185 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: PR bump preview
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, reopened, synchronize, ready_for_review]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
jobs:
12+
bump-preview:
13+
if: ${{ github.event.pull_request.draft == false }}
14+
runs-on: ubuntu-latest
15+
steps:
16+
# Using pull_request_target means GITHUB_TOKEN has write access to PR
17+
# comments even for fork PRs. We deliberately only run `cz bump --dry-run`
18+
# against the checked-out PR commits — no PR-controlled scripts are
19+
# executed, so this is safe.
20+
- name: Check out PR head
21+
uses: actions/checkout@v6
22+
with:
23+
ref: ${{ github.event.pull_request.head.sha }}
24+
fetch-depth: 0
25+
fetch-tags: true
26+
27+
- name: Set up Commitizen
28+
uses: commitizen-tools/setup-cz@main
29+
with:
30+
set-git-config: false
31+
32+
- name: Run cz bump --dry-run
33+
id: dry-run
34+
run: |
35+
set +e
36+
output="$(cz bump --dry-run --yes 2>&1)"
37+
status=$?
38+
set -e
39+
{
40+
echo "status=${status}"
41+
echo "output<<__CZ_BUMP_PREVIEW__"
42+
printf '%s\n' "${output}"
43+
echo "__CZ_BUMP_PREVIEW__"
44+
} >> "$GITHUB_OUTPUT"
45+
46+
- name: Build comment body
47+
env:
48+
STATUS: ${{ steps.dry-run.outputs.status }}
49+
OUTPUT: ${{ steps.dry-run.outputs.output }}
50+
run: |
51+
{
52+
echo "<!-- commitizen-bump-preview -->"
53+
echo "## 🔍 Commitizen bump preview"
54+
echo ""
55+
case "${STATUS}" in
56+
0)
57+
echo "Merging this PR will produce the following bump:"
58+
echo ""
59+
echo '```'
60+
printf '%s\n' "${OUTPUT}"
61+
echo '```'
62+
;;
63+
21)
64+
echo "No commits in this PR are eligible for a version bump."
65+
;;
66+
*)
67+
echo "⚠️ \`cz bump --dry-run\` exited with status \`${STATUS}\`:"
68+
echo ""
69+
echo '```'
70+
printf '%s\n' "${OUTPUT}"
71+
echo '```'
72+
;;
73+
esac
74+
} > comment.md
75+
76+
- name: Post or update PR comment
77+
uses: peter-evans/create-or-update-comment@v4
78+
with:
79+
token: ${{ secrets.GITHUB_TOKEN }}
80+
issue-number: ${{ github.event.pull_request.number }}
81+
body-path: comment.md
82+
body-includes: "<!-- commitizen-bump-preview -->"
83+
edit-mode: replace

docs/tutorials/github_actions.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,108 @@ jobs:
123123

124124
You can find the complete workflow in our repository at [bumpversion.yml](https://github.com/commitizen-tools/commitizen/blob/master/.github/workflows/bumpversion.yml).
125125

126+
### Previewing the version bump on pull requests
127+
128+
To help reviewers spot unexpected version bumps before merging, you can run
129+
`cz bump --dry-run` on every pull request and post (or update) a sticky
130+
comment summarizing the would-be version bump and changelog entries.
131+
132+
Create `.github/workflows/pr-bump-preview.yml`:
133+
134+
```yaml title=".github/workflows/pr-bump-preview.yml"
135+
name: PR bump preview
136+
137+
on:
138+
pull_request_target:
139+
types: [opened, reopened, synchronize, ready_for_review]
140+
141+
permissions:
142+
contents: read
143+
pull-requests: write
144+
145+
jobs:
146+
bump-preview:
147+
if: ${{ github.event.pull_request.draft == false }}
148+
runs-on: ubuntu-latest
149+
steps:
150+
- name: Check out PR head
151+
uses: actions/checkout@v6
152+
with:
153+
ref: ${{ github.event.pull_request.head.sha }}
154+
fetch-depth: 0
155+
fetch-tags: true
156+
- uses: commitizen-tools/setup-cz@main
157+
with:
158+
set-git-config: false
159+
- name: Run cz bump --dry-run
160+
id: dry-run
161+
run: |
162+
set +e
163+
output="$(cz bump --dry-run --yes 2>&1)"
164+
status=$?
165+
set -e
166+
{
167+
echo "status=${status}"
168+
echo "output<<__CZ_BUMP_PREVIEW__"
169+
printf '%s\n' "${output}"
170+
echo "__CZ_BUMP_PREVIEW__"
171+
} >> "$GITHUB_OUTPUT"
172+
- name: Build comment body
173+
env:
174+
STATUS: ${{ steps.dry-run.outputs.status }}
175+
OUTPUT: ${{ steps.dry-run.outputs.output }}
176+
run: |
177+
{
178+
echo "<!-- commitizen-bump-preview -->"
179+
echo "## 🔍 Commitizen bump preview"
180+
echo ""
181+
case "${STATUS}" in
182+
0)
183+
echo "Merging this PR will produce the following bump:"
184+
echo ""
185+
echo '```'
186+
printf '%s\n' "${OUTPUT}"
187+
echo '```'
188+
;;
189+
21)
190+
echo "No commits in this PR are eligible for a version bump."
191+
;;
192+
*)
193+
echo "⚠️ \`cz bump --dry-run\` exited with status \`${STATUS}\`:"
194+
echo ""
195+
echo '```'
196+
printf '%s\n' "${OUTPUT}"
197+
echo '```'
198+
;;
199+
esac
200+
} > comment.md
201+
- uses: peter-evans/create-or-update-comment@v4
202+
with:
203+
token: ${{ secrets.GITHUB_TOKEN }}
204+
issue-number: ${{ github.event.pull_request.number }}
205+
body-path: comment.md
206+
body-includes: "<!-- commitizen-bump-preview -->"
207+
edit-mode: replace
208+
```
209+
210+
#### How it works
211+
212+
- **Trigger**: `pull_request_target` runs in the context of the base
213+
repository, which gives the workflow `pull-requests: write` permission
214+
even for PRs from forks. The job only runs `cz bump --dry-run`, a
215+
read-only command, so it does not execute any PR-controlled scripts.
216+
- **Setup**: [`commitizen-tools/setup-cz`](https://github.com/commitizen-tools/setup-cz)
217+
installs the Commitizen CLI; no language-specific build tooling is required.
218+
- **Dry-run**: `cz bump --dry-run --yes` computes the next version and the
219+
changelog entries that would be produced. Exit code `21` (`NoneIncrementExit`)
220+
is treated as "no eligible bump" rather than a failure.
221+
- **Sticky comment**: The hidden HTML marker `<!-- commitizen-bump-preview -->`
222+
lets [`peter-evans/create-or-update-comment`](https://github.com/peter-evans/create-or-update-comment)
223+
find and replace the previous preview on every push, instead of leaving a
224+
growing trail of comments.
225+
226+
You can find the complete workflow in our repository at [pr-bump-preview.yml](https://github.com/commitizen-tools/commitizen/blob/master/.github/workflows/pr-bump-preview.yml).
227+
126228
### Publishing a Python package
127229

128230
After a new version tag is created by the bump workflow, you can automatically publish your package to PyPI.

0 commit comments

Comments
 (0)