What is Versioning?¶
Versioning is the process of assigning unique version numbers to distinct states of software projects, allowing developers and users to track progress, manage changes, and ensure compatibility between different components. It plays a critical role in software development and release management, offering a structured way to reflect the history, stability, and compatibility of software products over time. Through versioning, teams can effectively communicate the impact of changes, manage dependencies, and facilitate the adoption of new features while maintaining the integrity of existing systems.
What is Semantic Versioning?¶
Semantic Versioning, often abbreviated as SemVer, is a versioning scheme that aims to convey meaning about the underlying changes in a release through the version number itself. Defined by Semantic Versioning 2.0.0, it adopts a structured format of MAJOR.MINOR.PATCH to differentiate between the types of changes made to a project:
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backward-compatible manner, and
PATCH version when you make backward-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
The principles of Semantic Versioning help ensure a consistent, predictable approach to versioning that is directly tied to the significance of the changes made. It allows developers and consumers of software to make informed decisions about upgrading and integrating with other systems. By adhering to SemVer, projects can communicate the nature of changes efficiently, reduce the potential for conflicts, and facilitate easier dependency management in the complex ecosystem of software development.
Automate Semantic Versioning with Python Semantic Release¶
Using python-semantic-release to automate semantic versioning in projects managed with uv on GitHub involves setting up python-semantic-release in your project, configuring it to work with uv, and automating the release process through GitHub Actions.
Setup Your Python Project with uv¶
Let’s start by creating a new Python project using uv and navigating to its root directory.
uv init my-package-with-semverInitialized project `my-package-with-semver` at `/home/runner/work/msdp-book/home/ch52/my-package-with-semver`
Navigate to the root folder of the project.
cd my-package-with-semverInstall Python Semantic Release¶
Since this dependency is only needed for development and release management, it’s best to add it as a development dependency. This way, it won’t be included in the production environment or when users install your package.
uv add --dev python-semantic-releasewarning: `VIRTUAL_ENV=/home/runner/work/msdp-book/msdp-book/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
Using CPython 3.13.13
Creating virtual environment at: .venv
Resolved 32 packages in 205ms
Prepared 23 packages in 100ms
Installed 30 packages in 24ms
+ annotated-types==0.7.0
+ certifi==2026.4.22
+ charset-normalizer==3.4.7
+ click==8.1.8
+ click-option-group==0.5.9
+ deprecated==1.3.1
+ dotty-dict==1.3.1
+ gitdb==4.0.12
+ gitpython==3.1.50
+ idna==3.15
+ importlib-resources==6.5.2
+ jinja2==3.1.6
+ markdown-it-py==4.2.0
+ markupsafe==3.0.3
+ mdurl==0.1.2
+ pydantic==2.13.4
+ pydantic-core==2.46.4
+ pygments==2.20.0
+ python-gitlab==6.5.0
+ python-semantic-release==10.5.3
+ requests==2.34.0
+ requests-toolbelt==1.0.0
+ rich==14.3.4
+ shellingham==1.5.4
+ smmap==5.0.3
+ tomlkit==0.13.3
+ typing-extensions==4.15.0
+ typing-inspection==0.4.2
+ urllib3==2.7.0
+ wrapt==2.1.2
this command will add python-semantic-release to the [tool.uv.dev-dependencies] section of your pyproject.toml file, ensuring that it’s only installed in development environments.
Configure Python Semantic Release¶
To configure python-semantic-release, we will add a [tool.semantic_release] section to your pyproject.toml file.
[tool.semantic_release]
branch = "main"
commit_parser = "conventional"
version_toml = ["pyproject.toml:project.version"]This tells PSR:
which branch is the release branch
how to interpret commit messages
which version field to update
Important naming note:
the name in
[project].nameis your published distribution nameif that name is already taken on TestPyPI or PyPI, choose another one before you publish
if the name changes, keep your docs and publishing setup consistent with that choice
Create a new repository¶
Create a new empty repository in Github and name it my-package-with-semver.
and commit and push your code to the new repository:
git add .
git commit -m "feat: setup project with semantic release"
git branch -M main
git remote add origin https://github.com/mcallara/my-package-with-semver.git
git push -u origin main[main (root-commit) 4ecee4e] feat: setup project with semantic release
6 files changed, 575 insertions(+)
create mode 100644 .gitignore
create mode 100644 .python-version
create mode 100644 README.md
create mode 100644 main.py
create mode 100644 pyproject.toml
create mode 100644 uv.lock
Enumerating objects: 8, done.
Counting objects: 12% (1/8)
Counting objects: 25% (2/8)
Counting objects: 37% (3/8)
Counting objects: 50% (4/8)
Counting objects: 62% (5/8)
Counting objects: 75% (6/8)
Counting objects: 87% (7/8)
Counting objects: 100% (8/8)
Counting objects: 100% (8/8), done.
Delta compression using up to 4 threads
Compressing objects: 16% (1/6)
Compressing objects: 33% (2/6)
Compressing objects: 50% (3/6)
Compressing objects: 66% (4/6)
Compressing objects: 83% (5/6)
Compressing objects: 100% (6/6)
Compressing objects: 100% (6/6), done.
Writing objects: 12% (1/8)
Writing objects: 25% (2/8)
Writing objects: 37% (3/8)
Writing objects: 50% (4/8)
Writing objects: 62% (5/8)
Writing objects: 75% (6/8)
Writing objects: 87% (7/8)
Writing objects: 100% (8/8)
Writing objects: 100% (8/8), 26.00 KiB | 8.67 MiB/s, done.
Total 8 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/mcallara/my-package-with-semver.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
Note that uv does not automatically create a Git repository for you, so you need to initialize it yourself (no need to run git init). Also, make sure to replace mcallara with your actual GitHub username in the remote URL.
Determining Version Bumps with Commit Messages¶
To correctly determine version bumps, python-semantic-release relies on the commit messages in your repository. By following a certain commit message format (by default, the conventional commit format), you can ensure that PSR accurately identifies the type of changes made and increments the version number accordingly.
The conventional commit format typically includes a type (e.g., fix, feat, BREAKING CHANGE), an optional scope, and a description of the change. For example:
fix:means patch releasefeat:means minor releasefeat!:orBREAKING CHANGE:means major release
python-semantic-release will analyze your commit history and determine the appropriate version bump based on these commit messages. This allows for a more automated and consistent release process, as the version number will be updated according to the significance of the changes made in each commit.
To actually perform a release with this information, python-semantic-release offers the version command, which calculates the next version number based on the commit history and updates the version in your pyproject.toml file, creates a new git tag, and generates a changelog entry.
You can test version calculation locally without creating a real release by using the --noop flag, which simulates the release process and shows what would happen without making any changes.
uv run semantic-release -vv --noop version --printwarning: `VIRTUAL_ENV=/home/runner/work/msdp-book/msdp-book/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
[14:09:35] DEBUG logging level set to: DEBUG ]8;id=1446565;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/main.py\main.py]8;;\:]8;id=1446566;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/main.py#130\130]8;;\
🛡 You are running in no-operation mode, because the '--noop' flag was supplied
DEBUG global cli options: ]8;id=1446572;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/main.py\main.py]8;;\:]8;id=1446573;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/main.py#142\142]8;;\
GlobalCommandLineOptions(noop=True, verbosity=2,
config_file='pyproject.toml', strict=False)
INFO Loading configuration from pyproject.toml ]8;id=1446580;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/util.py\util.py]8;;\:]8;id=1446581;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/util.py#77\77]8;;\
DEBUG Trying to parse configuration pyproject.toml in ]8;id=1446587;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/util.py\util.py]8;;\:]8;id=1446588;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/util.py#80\80]8;;\
TOML format
INFO Using group 'main' options, as '(main|master)' ]8;id=1446595;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/config.py\config.py]8;;\:]8;id=1446596;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/config.py#590\590]8;;\
matches 'main'
DEBUG Parsing git url ]8;id=1446603;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/helpers.py\helpers.py]8;;\:]8;id=1446604;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/helpers.py#245\245]8;;\
'https://github.com/mcallara/my-package-with-
semver.git'
DEBUG setting up default session authentication ]8;id=1446611;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/hvcs/util.py\util.py]8;;\:]8;id=1446612;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/hvcs/util.py#49\49]8;;\
DEBUG inverted tag_format 'v{version}' to ]8;id=1446619;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/translator.py\translator.py]8;;\:]8;id=1446620;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/translator.py#44\44]8;;\
'v(?P<version>.+)'
DEBUG Adding redact pattern ]8;id=1446627;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/masking_filter.py\masking_filter.py]8;;\:]8;id=1446628;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/masking_filter.py#34\34]8;;\
''context.hvcs_client.token'' to
redact_patterns
DEBUG Adding redact pattern ]8;id=1446633;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/masking_filter.py\masking_filter.py]8;;\:]8;id=1446634;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/masking_filter.py#34\34]8;;\
''context.hvcs_client.token'' to
redact_patterns
DEBUG is_forced_prerelease: as_prerelease = False, ]8;id=1446641;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/version.py\version.py]8;;\:]8;id=1446642;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/cli/commands/version.py#71\71]8;;\
forced_level_bump = None, prerelease = False
DEBUG attempting to parse string '0.0.0' as Version ]8;id=1446649;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py\version.py]8;;\:]8;id=1446650;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py#116\116]8;;\
DEBUG version string 0.0.0 parsed as a ]8;id=1446656;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py\version.py]8;;\:]8;id=1446657;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py#140\140]8;;\
non-prerelease
DEBUG parsed build metadata '' from version string ]8;id=1446663;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py\version.py]8;;\:]8;id=1446664;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py#143\143]8;;\
0.0.0
INFO found 0 previous tags ]8;id=1446671;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446672;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#60\60]8;;\
INFO No full releases found in this branch's ]8;id=1446678;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446679;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#298\298]8;;\
history
INFO The latest release in this branch's history ]8;id=1446685;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446686;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#328\328]8;;\
was 0.0.0
INFO Found 1 commits since the last release! ]8;id=1446692;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446693;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#340\340]8;;\
DEBUG parsed the following distinct levels from ]8;id=1446699;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446700;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#378\378]8;;\
the commits since the last release:
{<LevelBump.MINOR: 3>}
INFO The type of the next release release is: ]8;id=1446706;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446707;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#384\384]8;;\
minor
DEBUG Bumping major version as 0.x.x versions are ]8;id=1446713;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446714;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#139\139]8;;\
disabled because of
allow_zero_version=False
DEBUG prerelease=False and the latest version ]8;id=1446720;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446721;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#155\155]8;;\
0.0.0 is not a prerelease
DEBUG Bumping 0.0.0 with a major bump ]8;id=1446727;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446728;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#230\230]8;;\
DEBUG performing a major level bump ]8;id=1446734;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py\version.py]8;;\:]8;id=1446735;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/version.py#227\227]8;;\
DEBUG Incremented 0.0.0 to 1.0.0 ]8;id=1446741;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446742;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#240\240]8;;\
1.0.0
INFO found 0 previous tags ]8;id=1446747;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py\algorithm.py]8;;\:]8;id=1446748;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/version/algorithm.py#60\60]8;;\
DEBUG getting repository owner and name from ]8;id=1446755;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/hvcs/github.py\github.py]8;;\:]8;id=1446756;file:///home/runner/work/msdp-book/home/ch52/my-package-with-semver/.venv/lib/python3.13/site-packages/semantic_release/hvcs/github.py#199\199]8;;\
environment variables
Let’s unpack what PSR is telling us here, line by line:
No-op mode banner (
🛡 You are running in no-operation mode): the--noopflag means PSR will compute the next version and show its reasoning, but it will not write topyproject.toml, create a tag, or push anything. This makes the command safe to run repeatedly while you experiment.Loading configuration from
pyproject.toml: PSR found and parsed the[tool.semantic_release]section we added earlier.Using group ‘main’ options, as
(main|master)matches ‘main’: PSR confirms it is treating the current branch as the release branch, per ourbranch = "main"setting.WARNING Token value is missing!: no GitHub token is configured locally. That is expected and harmless for--noopbecause we are not publishing a release; in CI, GitHub Actions will provideGITHUB_TOKENautomatically.found 0 previous tagsandNo full releases found in this branch's history: this is a brand-new repository with no version tags, so PSR falls back to a synthetic baseline of0.0.0(The latest release in this branch's history was 0.0.0).Found 1 commits since the last release!: the single commit we made (feat: setup project with semantic release) is the only one PSR needs to analyze.parsed the following distinct levels ... {<LevelBump.MINOR: 3>}andThe type of the next release release is: minor: the conventional-commit parser saw thefeat:prefix and classified the change as a minor bump.Bumping major version as 0.x.x versions are disabled because of allow_zero_version=False: here PSR overrides the minor decision. By defaultallow_zero_versionisFalse, meaning PSR refuses to stay on a0.x.yseries and will promote the very first release straight to1.0.0. If you wanted to keep the0.x.ynumbering during early development, you would setallow_zero_version = truein the config.Incremented 0.0.0 to 1.0.0followed by the bare1.0.0line: the final answer. The--printflag asks PSR to write only the resulting version number to standard output, which is what makes this command useful in scripts and CI pipelines.
In short: PSR read our config, looked at the commit history, classified the only commit as a feature, applied the allow_zero_version=False rule, and concluded that the next release should be 1.0.0. Because of --noop, nothing was changed on disk or in Git.
Setup GitHub Actions to use Python Semantic Release¶
We don’t want to run python-semantic-release manually every time we want to make a release. Instead, we can automate the process using GitHub Actions, which will run the release workflow whenever we push changes to the main branch.
This workflow will automatically determine the next version number based on the commit messages, update the version in pyproject.toml, and create a new release on GitHub.
We will create a workflow file named .github/workflows/release.yml with the following steps:
actions/checkout: brings your repository onto the runnerastral-sh/setup-uv: installsuvin the job environmentuv run semantic-release version: computes and applies the next releaseuv build: builds a wheel and source distribution
name: Semantic Release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout the code
uses: actions/checkout@main
with:
fetch-depth: 0
- name: Set up uv
uses: astral-sh/setup-uv@main
- name: Run Semantic Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: uv run semantic-release versionAfter adding the workflow file, commit and push your changes to the main branch to trigger the workflow.
git add .
git commit -m "feat: add GitHub Actions workflow for semantic release"
git push -u origin main[main 0187f31] feat: add GitHub Actions workflow for semantic release
1 file changed, 23 insertions(+)
create mode 100644 .github/workflows/release.yml
Enumerating objects: 6, done.
Counting objects: 16% (1/6)
Counting objects: 33% (2/6)
Counting objects: 50% (3/6)
Counting objects: 66% (4/6)
Counting objects: 83% (5/6)
Counting objects: 100% (6/6)
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 33% (1/3)
Compressing objects: 66% (2/3)
Compressing objects: 100% (3/3)
Compressing objects: 100% (3/3), done.
Writing objects: 20% (1/5)
Writing objects: 40% (2/5)
Writing objects: 60% (3/5)
Writing objects: 80% (4/5)
Writing objects: 100% (5/5)
Writing objects: 100% (5/5), 633 bytes | 633.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 0% (0/1)
remote: Resolving deltas: 100% (1/1)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/mcallara/my-package-with-semver.git
4ecee4e..0187f31 main -> main
branch 'main' set up to track 'origin/main'.
Checking that the workflow runs correctly¶
Open the repository on GitHub.
Open the Actions tab in GitHub.
Wait for the workflow to finish.
Confirm the version bump, tag, and GitHub release.
Expected outputs:
the workflow should complete successfully
there is a new commit with the version number
1.0.0(the new version number) that was automatically generated by PSR in the workflowpyproject.tomlversion changeda new git tag was created
a new GitHub release was created
the
CHANGELOG.mdfile was generated with the details of the release
Since the workflow generates a new commit on the remote repository, you need to pull the latest changes to see the new commit and updated pyproject.toml in your local repository.
git pullAlready up to date.
If you add more local commits and push them without pulling the latest changes, you may encounter a merge conflict because the workflow’s commit will be ahead of your local branch. To avoid this, always pull the latest changes before making new commits.
If you created more local commits without pulling, you can resolve the merge conflict by rebasing your commits on top of the latest changes from the remote repository. Here’s how you can do that:
git pull --rebase origin mainUpdating the lockfile in the workflow¶
If we check the lock file that appears in the repository, we can see that the version of our package in the lock file does not match the new version generated by PSR. This is because the workflow only updates the version in pyproject.toml and creates a new commit, but it does not update the lock file. To ensure that the lock file is updated with the new version, we can add a step in the workflow to run uv lock after the version bump. This will regenerate the lock file with the correct version.
Replace the Run Semantic Release step in the workflow with the following steps:
- name: Run Semantic Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
uv run semantic-release -v version --skip-build --no-commit --no-tag --no-changelog
uv lock
git add uv.lock
uv run semantic-release -v versionThis will first run the version command but only update the version in pyproject.toml without creating a commit or tag. Then it will update the lock file, add it to the staging area, and finally run the version command again to create the commit and tag with the updated version.
Testing the workflow with new commits¶
To see how the workflow handles different types of commits, you can make additional commits with different conventional commit messages and push them to the main branch.
For example, let’s say we commit two bug fix and a new feature:
git pull
git commit --allow-empty -m "fix: correct a minor bug"
git commit --allow-empty -m "fix: correct another minor bug"
git commit --allow-empty -m "feat: add a new feature"
git pushThis will trigger the workflow again, and you should see a new release with a minor version bump (e.g., 1.1.0) because of the feat: commit, while the fix: commits will contribute to the patch level but won’t trigger a patch release on their own since they are overshadowed by the feature commit.
To see a MAJOR release, you can use a commit message that indicates a breaking change. For example:
git pull
git commit --allow-empty -m 'feat!: introduce a breaking change'
git pushThis will trigger a major release (e.g., 2.0.0)
Finally, to see a patch release, you can make a commit with a fix: message without any feat: or breaking change commits:
git pull
git commit --allow-empty -m "fix: correct a minor bug"
git pushThis will trigger a patch release (e.g., 2.0.1).