| [ Web Proxy ] |
| Viewing: https://commitizen-tools.github.io/commitizen/tutorials/github_actions/ | [Back] [Original] |
[logo]
This guide shows you how to automatically bump versions, create changelogs, and publish releases using Commitizen in GitHub Actions.
Before setting up the workflow, you'll need:
To automatically execute cz bump in your CI and push the new commit and tag back to your repository, follow these steps:
repo scope to grant full repository accessImportant: Use Personal Access Token, not GITHUB_TOKEN
If you use GITHUB_TOKEN instead of PERSONAL_ACCESS_TOKEN, the workflow won't trigger another workflow run. This is a GitHub security feature to prevent infinite loops. The GITHUB_TOKEN is treated like using [skip ci] in other CI systems.
Settings > Secrets and variables > ActionsPERSONAL_ACCESS_TOKENCreate a new file .github/workflows/bumpversion.yml in your repository with the following content:
name: Bump version
on:
push:
branches:
- master # or 'main' if that's your default branch
jobs:
bump-version:
if: "!startsWith(github.event.head_commit.message, 'bump:')"
runs-on: ubuntu-latest
name: "Bump version and create changelog with commitizen"
steps:
- name: Check out
uses: actions/checkout@v6
with:
token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
fetch-depth: 0
- name: Create bump and changelog
uses: commitizen-tools/commitizen-action@master
with:
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
master branch (or main if you change it)if condition prevents infinite loops by skipping the job if the commit message starts with bump:fetch-depth: 0)commitizen-action automatically:pyproject.toml or other config)Once you push this workflow file to your repository, it will automatically run on the next push to your default branch.
Check out commitizen-action for more details.
To automatically create a GitHub release when a new version is bumped, you can extend the workflow above.
The commitizen-action creates an environment variable called REVISION containing the newly created version. You can use this to create a release with the changelog content.
name: Bump version
on:
push:
branches:
- master # or 'main' if that's your default branch
jobs:
bump-version:
if: "!startsWith(github.event.head_commit.message, 'bump:')"
runs-on: ubuntu-latest
name: "Bump version and create changelog with commitizen"
steps:
- name: Check out
uses: actions/checkout@v6
with:
token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
fetch-depth: 0
- name: Create bump and changelog
uses: commitizen-tools/commitizen-action@master
with:
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
changelog_increment_filename: body.md
- name: Release
uses: ncipollo/release-action@v1
with:
tag: v${{ env.REVISION }}
bodyFile: "body.md"
skipIfReleaseExists: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
You can find the complete workflow in our repository at bumpversion.yml.
To help reviewers spot unexpected version bumps before merging, you can run
cz bump --dry-run on every pull request and post (or update) a sticky
comment summarizing the would-be version bump.
Create .github/workflows/pr-bump-preview.yml:
name: PR bump preview
on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review]
permissions:
contents: read
pull-requests: write
jobs:
bump-preview:
# Skip drafts and fork PRs (see "How it works" below).
if: >
${{
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name ==
github.event.pull_request.base.repo.full_name
}}
runs-on: ubuntu-latest
steps:
- name: Check out PR head
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
fetch-tags: true
persist-credentials: false
- uses: commitizen-tools/setup-cz@main
with:
set-git-config: false
- name: Run cz bump --dry-run
id: dry-run
run: |
set +e
output="$(cz bump --dry-run --yes 2>&1)"
status=$?
set -e
{
echo "status=${status}"
echo "output<<__CZ_BUMP_PREVIEW__"
printf '%s\n' "${output}"
echo "__CZ_BUMP_PREVIEW__"
} >> "$GITHUB_OUTPUT"
- name: Build comment body
env:
STATUS: ${{ steps.dry-run.outputs.status }}
OUTPUT: ${{ steps.dry-run.outputs.output }}
run: |
{
echo "<!-- commitizen-bump-preview -->"
echo "## Commitizen bump preview"
echo ""
case "${STATUS}" in
0)
echo "Merging this PR will produce the following bump:"
echo ""
echo '```'
printf '%s\n' "${OUTPUT}"
echo '```'
;;
21)
echo "No commits in this PR are eligible for a version bump."
;;
*)
echo " \`cz bump --dry-run\` exited with status \`${STATUS}\`:"
echo ""
echo '```'
printf '%s\n' "${OUTPUT}"
echo '```'
;;
esac
} > comment.md
- name: Find existing preview comment
id: find-comment
uses: peter-evans/find-comment@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- commitizen-bump-preview -->"
- uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body-path: comment.md
edit-mode: replace
pull_request_target runs in the context of the base
repository, which gives the workflow pull-requests: write permission
even for PRs from forks. We deliberately gate the job to same-repo PRs
only (head.repo == base.repo); fork PRs are skipped. This is because
cz bump renders Jinja templates from the working directory
whenever update_changelog_on_bump is
enabled, and the renderer is not sandboxed running it against
fork-controlled files under a write token would risk arbitrary code
execution and token exfiltration. Same-repo PRs are written by
collaborators who already have push access, so the same risk doesn't
apply.commitizen-tools/setup-cz
installs the Commitizen CLI; no language-specific build tooling is required.persist-credentials: false on actions/checkout
keeps the workflow token out of the local git config.cz bump --dry-run --yes computes the next version (and, if
update_changelog_on_bump is set in your config, also the changelog
entries that would be produced). Exit code 21 (NoneIncrementExit)
is treated as "no eligible bump" rather than a failure.peter-evans/find-comment
looks up an existing comment by the hidden HTML marker
<!-- commitizen-bump-preview --> and bot author, then
peter-evans/create-or-update-comment
edits it in place (or creates a new one on the first run when the
marker is not yet present), instead of leaving a growing trail of
comments.You can find the complete workflow in our repository at pr-bump-preview.yml.
After a new version tag is created by the bump workflow, you can automatically publish your package to PyPI.
Using trusted publishing (recommended)
Instead of API tokens, consider using PyPI trusted publishing with OpenID Connect (OIDC). This is more secure as it doesn't require storing secrets. The pypa/gh-action-pypi-publish action supports trusted publishing when you configure it in your PyPI project settings.
Settings > Secrets and variables > ActionsPYPI_PASSWORDCreate a new file .github/workflows/pythonpublish.yml that triggers on tag pushes:
name: Upload Python Package
on:
push:
tags:
- "*" # Will trigger for every tag, alternative: 'v*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: latest
virtualenvs-in-project: true
virtualenvs-create: true
- name: Install dependencies
run: |
poetry --version
poetry install
- name: Build and publish
env:
POETRY_HTTP_BASIC_PYPI_USERNAME: __token__
POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: poetry publish --build
This workflow uses Poetry to build and publish the package. You can find the complete workflow in our repository at pythonpublish.yml.
Alternative publishing methods
You can also use pypa/gh-action-pypi-publish or other build tools like setuptools, flit, or hatchling to publish your package.
| Web Proxy Viewer | New URL | Original Page |