FASTAPI FOUNDATION SERIES

How to Setup Automatic Versioning for your FastAPI App

Part 3: Versioning

Amir Lavasani
5 min readJun 16, 2024

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?

  1. Avoid Confusion: Versioning helps keep track of changes and avoids confusion about which version is being used.
  2. Maintain Compatibility: Ensures new updates work with older versions, preventing issues for users.
  3. Easier Debugging: Knowing the exact version makes it easier to identify and fix bugs.
  4. Clear Communication: Clearly communicates what changes have been made to other developers and users.
  5. Smooth Updates: Facilitates smooth and predictable updates without breaking the application.
Dall-E generated image with the following concept: Two abstract sides: the left side shows tangled strings representing chaos, and the right side shows a single, straight string representing clarity.

Understanding Semantic Versioning

Semantic Versioning (SemVer) is the most famous versioning standard. it uses a three-part version number: MAJOR.MINOR.PATCH.

  1. MAJOR version increments when you make incompatible API changes.
  2. MINOR version increments when you add functionality in a backward-compatible manner.
  3. 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-releasepackage.

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 feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes
  • refactor: Code changes without fixing bugs or adding features
  • perf: Performance improvements
  • test: Testing changes
  • chore: 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.

Read More 📜

Resources

--

--

Amir Lavasani

I delve into machine learning 🤖 and software architecture 🏰 to enhance my expertise while sharing insights with Medium readers. 📃