FASTAPI FOUNDATION SERIES
How to Setup Automatic Versioning for your FastAPI App
Part 3: Versioning
In this part, I explain why versioning is crucial for FastAPI applications and how to automate it with semantic versioning, Git commit messages, and the python-semantic-release
package.
By the end, you’ll have an automatic versioning system for your FastAPI projects.
How Does Versioning Help Us?
- Avoid Confusion: Versioning helps keep track of changes and avoids confusion about which version is being used.
- Maintain Compatibility: Ensures new updates work with older versions, preventing issues for users.
- Easier Debugging: Knowing the exact version makes it easier to identify and fix bugs.
- Clear Communication: Clearly communicates what changes have been made to other developers and users.
- Smooth Updates: Facilitates smooth and predictable updates without breaking the application.
Understanding Semantic Versioning
Semantic Versioning (SemVer) is the most famous versioning standard. it uses a three-part version number: MAJOR.MINOR.PATCH
.
- MAJOR version increments when you make incompatible API changes.
- MINOR version increments when you add functionality in a backward-compatible manner.
- PATCH version increments when you make backward-compatible bug fixes.
To learn more about SemVer read the following article or refer to the original docs.
Setting Up Automatic Version Bumping
There are a couple of versioning packages out there. semantic-release
is one of the most famous and popular tools for versioning in the Javascript community.
We are going to use thepython-semantic-release
which is the Python implementation of semantic-release
package.
We Integrate it with out FastAPI project using the three simple steps:
1. Install python-semantic-release
first, install python-semantic-release
in your environment.
Use poetry
to add python-semantic-release
to dev dependencies or the default pip
in your activated environment.
(proj-env) user@host:~$ poerty add -G dev python-semantic-release
(proj-env) user@host:~$ pip install python-semantic-release
2. Generate Configuration
Generate the configuration for your project and append it to the pyproject.toml
using the following command.
semantic-release generate-config --pyproject >> pyproject.toml
Here is the default config that semantic-release
generates:
[tool.semantic_release]
assets = []
build_command_env = []
commit_message = "{version}\n\nAutomatically generated by python-semantic-release"
commit_parser = "angular"
logging_use_named_masks = false
major_on_zero = true
allow_zero_version = true
no_git_verify = false
tag_format = "v{version}"
version_variables = ["src/app/version.py:__version__"] # we added this
[tool.semantic_release.branches.main]
match = "(main|master)"
prerelease_token = "rc"
prerelease = false
[tool.semantic_release.changelog]
template_dir = "templates"
changelog_file = "CHANGELOG.md"
exclude_commit_patterns = []
[tool.semantic_release.changelog.environment]
block_start_string = "{%"
block_end_string = "%}"
variable_start_string = "{{"
variable_end_string = "}}"
comment_start_string = "{#"
comment_end_string = "#}"
trim_blocks = false
lstrip_blocks = false
newline_sequence = "\n"
keep_trailing_newline = false
extensions = []
autoescape = true
[tool.semantic_release.commit_author]
env = "GIT_COMMIT_AUTHOR"
default = "semantic-release <semantic-release>"
[tool.semantic_release.commit_parser_options]
allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "style", "refactor", "test"]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
default_bump_level = 0
[tool.semantic_release.remote]
name = "origin"
type = "github"
ignore_token_for_push = false
insecure = false
[tool.semantic_release.publish]
dist_glob_patterns = ["dist/*"]
upload_to_vcs_release = true
3. Add the Version File
Create a Python file to store your version information. Place it in the root folder of your source:
# /src/app/version.py
"""
Version Information
This module provides the code version and is
automatically updated by the python-semantic-release package.
DO NOT EDIT IT MANUALLY.
"""
__version__ = 0.1.0
Next, update your pyproject.toml
to let semantic-release
know how to use this file:
[tool.semantic_release]
# ... other configs
version_variables = ["src/app/version.py:__version__"]
And voila! 🎉
Now you can automatically bump your version using the format of your Git Commit Messages.
Automatic Versioning Using Git Commit Messages
python-semantic-release
rely on commit messages to detect how to bump to the next version. This ensures versioning is consistent and based on the type of changes made.
By default, it uses the Angular style.
Commit messages should follow a precise format to maintain readability and generate changelogs.
Commit Message Format
- Header: Includes type, scope (optional), and subject.
- Body: Details about the change.
- Footer: Notes on breaking changes or issue references.
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Types
Commit message types determine the next version of your app. For example, the feat
type increases the MINOR version number, while the fix
type increases the PATCH number. Here are the standard types:
feat
: New featurefix
: Bug fixdocs
: Documentation changesstyle
: Code style changesrefactor
: Code changes without fixing bugs or adding featuresperf
: Performance improvementstest
: Testing changeschore
: Build process or auxiliary tool changes
You can also define custom types in the allowed_tags
list in your pyproject.toml
file.
Let’s Version
Now, let’s see it in action. Add your changes and commit with the standard format:
(proj-env) user@host:~$ git commit -m "feat: add automatic versioning"
Using semantic-release
, you can automatically bump your version based on your commit message. This dry-run command shows the next version without making any changes. Our next version is v0.2.0
(proj-env) user@host:~$ semantic-release --noop version --print
🛡 You are running in no-operation mode, because the '--noop' flag
was supplied
0.2.0
To create the next version, run:
(proj-env) user@host:~$ semantic-release version
0.2.0
The next version is: 0.2.0! 🚀
semantic-release
will update the version file, commit the changes, tag the commit, and push everything to your remote server.
Now you can also add this version
to your FastAPI app:
from app.version import __version__
app = FastAPI(
version=__version__,
)
Automate Using GitHub Actions
You can also set up your CI/CD pipeline to use semantic-release
for automatic versioning after each successful merge into the main branch.
Create the Workflow File
Save the following YAML configuration as .github/workflows/version-bump.yml
in your repository.
name: Bump Version
on:
push:
branches:
- main
jobs:
bump-version:
runs-on: ubuntu-latest
permissions:
actions: write
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Bump version using semantic-release
uses: python-semantic-release/python-semantic-release@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
Now every time you push or merge other branches into the main branch, It will bump your code version depending on the commit messages, tag it, and make a release for that version in GitHub.
Conclusion
Versioning is essential for clarity and control in FastAPI projects. Automating it using semantic versioning, Git commit messages, and python-semantic-release
improves clarity and maintainability.
By following this guide, you'll have an efficient versioning system for your FastAPI applications, ensuring smooth updates, easier debugging, and clear communication with your team. Automate your versioning to keep your FastAPI projects organized and future-proof.