Quickstart¶
This guide walks through setting up scriv-release in a Python project that already has, or wants to add, scriv-managed changelog fragments.
1. Install¶
The [bump-my-version] extra installs the default version provider. Other providers (hatch, uv, shell) are exposed via entry points — see "Version providers" below.
2. Configure scriv¶
If you don't already have a scriv config, add this to pyproject.toml:
[tool.scriv]
categories = ["Added", "Changed", "Deprecated", "Removed", "Fixed", "Security", "Chore"]
format = "md"
md_header_level = 2
3. Configure scriv-release¶
Add the [tool.scriv-release] section. All keys are optional — defaults match the table below.
[tool.scriv-release]
version_provider = "bump-my-version"
preview_branch = "scriv-release-preview"
unknown_category_policy = "warn" # "warn" | "error" | "patch"
release_detection = "history" # "history" | "pr-body-marker" | "auto"
zero_major_policy = "downshift" # "downshift" | "strict"
[tool.scriv-release.category_semver_map]
Added = "minor"
Changed = "minor"
Deprecated = "minor"
Removed = "major"
Fixed = "patch"
Security = "patch"
Chore = "patch"
zero_major_policy¶
Per SemVer §4, 0.x.y releases have no stable public API and may break at any minor bump. zero_major_policy controls how this interacts with category_semver_map while the current version's major is 0:
| Mode | Behavior while major == 0 |
|---|---|
downshift |
Default. A "major"-level fragment (e.g. Removed) bumps the minor position. 0.5.0 → 0.6.0. |
strict |
Apply bumps positionally regardless. 0.5.0 + Removed → 1.0.0. |
When you're ready to graduate to 1.0.0, set zero_major_policy = "strict" (or manually set the version to 1.0.0 in your version-bearing file before the next release). Once the major is 1 or higher this setting is a no-op.
4. Configure bump-my-version¶
scriv-release delegates the actual version bump to your chosen version provider. For bump-my-version, see its docs — the minimum is a [tool.bumpversion] section in pyproject.toml pointing at your version string.
5. Wire up the GitHub Action¶
Add .github/workflows/release.yml:
on:
push:
branches: [main]
permissions: {}
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- uses: whitphx/scriv-release@v0.4.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
app-private-key: ${{ secrets.RELEASE_APP_KEY }}
The action installs scriv-release into a private venv under $RUNNER_TEMP — it does not run setup-python or pollute the caller's site-packages, so it can sit alongside a job that already has its own Python toolchain. By default the install source is the action's own pinned checkout ($GITHUB_ACTION_PATH[bump-my-version]), so the workflow ref is the only place a version is named: @v0.4.0 always installs the v0.4.0 source. To use a different extra or a published wheel, pass install-spec (any pip-style requirement):
See token-setup.md for the GitHub App and why the default GITHUB_TOKEN isn't enough.
6. Author flow¶
For each PR, contributors run:
This opens an editor on a new file in changelog.d/. Fill in the relevant section(s) (### Added, ### Fixed, …) and commit it with the PR.
When the PR is merged to main, the action opens (or updates) a "Changelog Preview for Next Release" PR. Merging that PR triggers a tagged release.
CLI cheatsheet¶
scriv-release bump-level # major | minor | patch | (empty)
scriv-release next-version # e.g. 1.4.0
scriv-release detect-release # bump level for an in-progress release, per release_detection
scriv-release collect # runs `scriv collect --version <next>`
scriv-release print --next # changelog body for the next version
scriv-release tag --push # bump + tag + push (local release)
Version providers¶
Configured via [tool.scriv-release].version_provider. Built-ins:
| Name | Notes |
|---|---|
bump-my-version |
Default. Requires the [bump-my-version] extra. Uses bump-my-version bump to update version-bearing files declared in [tool.bumpversion] (if any). Tag is v{version}. |
hatch |
Uses hatch version to update the version. Requires [tool.hatch.version] to be configured (non-vcs source). Tag is v{version}. |
uv |
Uses uv version --bump to update [project].version. Tag is v{version}. |
shell |
Runs user-supplied commands. See below. |
Third parties can register additional providers via the scriv_release.version_providers entry-point group.
Shell provider¶
Configure the commands under [tool.scriv-release.shell]:
[tool.scriv-release]
version_provider = "shell"
[tool.scriv-release.shell]
current = "cat VERSION"
apply = "./scripts/bump.sh" # receives $LEVEL and $NEW_VERSION; writes the new version into source
# next = "..." # optional; defaults to packaging-based major/minor/patch bump of `current`
The apply command must update version-bearing files in the working tree. scriv-release runs it as part of the preview PR so the bump is captured in the same commit as the changelog edit, then tags HEAD at release time.
Release detection¶
release_detection controls how the action knows that the current main HEAD is the merged preview PR (i.e. the moment to tag a release).
| Mode | Behavior |
|---|---|
history |
Default. If HEAD has no fragments and HEAD~1 did, treat as release. Survives squash/rebase/merge. |
pr-body-marker |
Look up the PR for HEAD via gh api, parse a marker like scriv-release-bump: minor from the body, and use it as the bump level. |
auto |
Try pr-body-marker first; fall back to history if no marker is present. |
The marker key defaults to scriv-release-bump and can be customized: