5.2 Software Versioning#
What is Versioning?#
Versioning is the process of assigning unique version 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 in Poetry Projects with Python Semantic Release#
We can use a python package called python-semantic-release
to automate semantic versioning in projects managed with Poetry on Gitlab. This package automates the process of determining the next version number based on the changes made to the project, generating release notes, and publishing the release to a repository. By integrating python-semantic-release
with Gitlab CI/CD, we can automate the entire release process, ensuring that version numbers are incremented correctly and that releases are published consistently.
Automating the semantic versioning of My Package#
Let’s see how to automate semantic versioning in a Python project managed with Poetry using python-semantic-release
and Gitlab CI/CD. We will use the my-package
project that we created in the previous section and configure it to use python-semantic-release
for versioning and release management.
Creating a personal access token#
To allow python-semantic-release
to interact with your Gitlab repository, you need to create a personal access token. This token will be used to authenticate the tool when it performs actions such as creating releases and tags.
To create a new personal access token, go to your GitLab account Preferences and click on “Access Tokens” in the “User Settings” section. Then, click on “Add new token” and fill in the required details. You can use:
Token name: semantic_release
Check the following scopes:
api
,read_user
,read_repository
, andwrite_repository
. Once you’ve created the token, copy it to your clipboard, as you’ll need it later.
Adding the token to the GitLab CI/CD variables#
To add the token to the GitLab CI/CD variables, go to the settings of the repository and then to the CI/CD section. Browse until you find the “Variables” section and click on “Expand” to reveal the form for adding a new variable. Now click on “Add variable” and add a new variable with:
Type: Variable (default)
Environment: All (default)
Visibility: Masked
Flags: Protect Variable and Expand variable reference
Key:
GITLAB_TOKEN
Value:
<your token>
Setup Your Python Project with Poetry#
To ensure that our project is set up with Poetry and has a pyproject.toml
file at its root, we need to initialize the project using Poetry.
If the pyproject.toml
file is not there, we can create it by running the following command in the terminal:
poetry init
Change the Python Versions Supported by the Project#
Since python-semantic-release
requires Python >=3.8
, before installing python-semantic-release, it is important that you check and change, if needed, the Python version supported by the project.
In the pyproject.toml
file, look for requires-python
and change the Python version to ^3.8
if a lower version is specified.
For example, if you find:
requires-python = ">=3.7"
Change it to:
requires-python = ">=3.8"
Add Python Semantic Release as a dependency of your project#
Add python-semantic-release
to your development dependencies using Poetry.
poetry add --group dev python-semantic-release
The currently activated Python version 3.7.4 is not supported by the project (>=3.10).
Trying to find and use a compatible version.
Using python3.12 (3.12.4)
Creating virtualenv my-package in /home/callaram/tds/home/ch5/my-package/.venv
Using version ^10.3.1 for python-semantic-release
Updating dependencies
Resolving dependencies... (6.5s)
Package operations: 40 installs, 0 updates, 0 removals
- Installing certifi (2025.8.3): Pending...
- Installing charset-normalizer (3.4.3): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing charset-normalizer (3.4.3): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing certifi (2025.8.3): Installing...
- Installing charset-normalizer (3.4.3): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing charset-normalizer (3.4.3): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing certifi (2025.8.3)
- Installing charset-normalizer (3.4.3): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing charset-normalizer (3.4.3): Downloading... 0%
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing charset-normalizer (3.4.3): Downloading... 100%
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing charset-normalizer (3.4.3): Installing...
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing charset-normalizer (3.4.3)
- Installing idna (3.10): Pending...
- Installing urllib3 (2.5.0): Downloading... 0%
- Installing urllib3 (2.5.0): Downloading... 100%
- Installing urllib3 (2.5.0): Installing...
- Installing urllib3 (2.5.0): Installing...
- Installing idna (3.10): Installing...
- Installing urllib3 (2.5.0): Installing...
- Installing urllib3 (2.5.0)
- Installing urllib3 (2.5.0)
- Installing idna (3.10)
- Installing urllib3 (2.5.0)
- Installing mdurl (0.1.2): Pending...
- Installing requests (2.32.4): Pending...
- Installing smmap (5.0.2): Pending...
- Installing typing-extensions (4.14.1): Pending...
- Installing typing-extensions (4.14.1): Pending...
- Installing smmap (5.0.2): Installing...
- Installing typing-extensions (4.14.1): Pending...
- Installing smmap (5.0.2): Installing...
- Installing typing-extensions (4.14.1): Pending...
- Installing requests (2.32.4): Installing...
- Installing smmap (5.0.2): Installing...
- Installing typing-extensions (4.14.1): Pending...
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing requests (2.32.4): Installing...
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing mdurl (0.1.2): Installing...
- Installing requests (2.32.4): Installing...
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing requests (2.32.4): Installing...
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing mdurl (0.1.2)
- Installing requests (2.32.4): Installing...
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing requests (2.32.4)
- Installing smmap (5.0.2)
- Installing typing-extensions (4.14.1): Downloading... 0%
- Installing typing-extensions (4.14.1): Downloading... 100%
- Installing typing-extensions (4.14.1): Installing...
- Installing typing-extensions (4.14.1)
- Installing annotated-types (0.7.0): Pending...
- Installing click (8.1.8): Pending...
- Installing gitdb (4.0.12): Pending...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Pending...
- Installing pygments (2.19.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing gitdb (4.0.12): Pending...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Pending...
- Installing pygments (2.19.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing click (8.1.8): Installing...
- Installing gitdb (4.0.12): Pending...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Pending...
- Installing pygments (2.19.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Pending...
- Installing pygments (2.19.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing gitdb (4.0.12): Installing...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Pending...
- Installing pygments (2.19.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing six (1.17.0): Installing...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing gitdb (4.0.12): Installing...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing click (8.1.8)
- Installing gitdb (4.0.12): Installing...
- Installing markdown-it-py (3.0.0): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing markdown-it-py (3.0.0): Installing...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Pending...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Pending...
- Installing wrapt (1.17.2): Installing...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Installing...
- Installing requests-toolbelt (1.0.0): Installing...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Installing...
- Installing markdown-it-py (3.0.0): Installing...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Installing...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Installing...
- Installing gitdb (4.0.12)
- Installing markdown-it-py (3.0.0): Installing...
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0): Installing...
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2): Installing...
- Installing wrapt (1.17.2)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2)
- Installing markdown-it-py (3.0.0)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Pending...
- Installing wrapt (1.17.2)
- Installing wrapt (1.17.2)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing click (8.1.8)
- Installing gitdb (4.0.12)
- Installing markdown-it-py (3.0.0)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing annotated-types (0.7.0): Installing...
- Installing click (8.1.8)
- Installing gitdb (4.0.12)
- Installing markdown-it-py (3.0.0)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing click (8.1.8)
- Installing gitdb (4.0.12)
- Installing markdown-it-py (3.0.0)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing annotated-types (0.7.0)
- Installing click (8.1.8)
- Installing gitdb (4.0.12)
- Installing markdown-it-py (3.0.0)
- Installing markupsafe (3.0.2): Pending...
- Installing pydantic-core (2.33.2): Downloading... 0%
- Installing pygments (2.19.2): Installing...
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Downloading... 0%
- Installing wrapt (1.17.2)
- Installing wrapt (1.17.2)
- Installing typing-inspection (0.4.1): Downloading... 100%
- Installing wrapt (1.17.2)
- Installing wrapt (1.17.2)
- Installing typing-inspection (0.4.1): Installing...
- Installing wrapt (1.17.2)
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Installing...
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Downloading... 100%
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1): Installing...
- Installing wrapt (1.17.2)
- Installing wrapt (1.17.2)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing markupsafe (3.0.2): Downloading... 0%
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing markupsafe (3.0.2): Downloading... 100%
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing markupsafe (3.0.2): Installing...
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing markupsafe (3.0.2)
- Installing pydantic-core (2.33.2): Installing...
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing pydantic-core (2.33.2)
- Installing pygments (2.19.2)
- Installing requests-toolbelt (1.0.0)
- Installing six (1.17.0)
- Installing typing-inspection (0.4.1)
- Installing wrapt (1.17.2)
- Installing click-option-group (0.5.7): Pending...
- Installing deprecated (1.2.18): Pending...
- Installing dotty-dict (1.3.1): Pending...
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Pending...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Pending...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Pending...
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Pending...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing dotty-dict (1.3.1): Installing...
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Pending...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing iniconfig (2.1.0): Installing...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Installing...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Installing...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Installing...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0): Installing...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0): Installing...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing deprecated (1.2.18): Pending...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing click-option-group (0.5.7): Installing...
- Installing deprecated (1.2.18): Pending...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing deprecated (1.2.18): Installing...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Pending...
- Installing tzdata (2025.2): Installing...
- Installing deprecated (1.2.18): Installing...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing click-option-group (0.5.7)
- Installing deprecated (1.2.18): Installing...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 0%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing pydantic (2.11.7): Downloading... 100%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 100%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing deprecated (1.2.18)
- Installing dotty-dict (1.3.1)
- Installing gitpython (3.1.45): Pending...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Pending...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0): Installing...
- Installing pydantic (2.11.7): Downloading... 100%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing pydantic (2.11.7): Downloading... 100%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Downloading... 100%
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing jinja2 (3.1.6): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Pending...
- Installing tzdata (2025.2): Installing...
- Installing tzdata (2025.2): Installing...
- Installing tomlkit (0.13.3): Installing...
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Installing...
- Installing tzdata (2025.2): Installing...
- Installing gitpython (3.1.45): Installing...
- Installing importlib-resources (6.5.2): Pending...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Pending...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3): Installing...
- Installing tzdata (2025.2): Installing...
- Installing tzdata (2025.2): Installing...
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2): Downloading... 0%
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0): Installing...
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2): Downloading... 0%
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing gitpython (3.1.45)
- Installing importlib-resources (6.5.2): Downloading... 0%
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Pending...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2): Downloading... 100%
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2): Installing...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing importlib-resources (6.5.2)
- Installing pytz (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0): Downloading... 0%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-gitlab (6.2.0): Downloading... 100%
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-gitlab (6.2.0): Installing...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing python-gitlab (6.2.0)
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0)
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing pytz (2025.2)
- Installing jinja2 (3.1.6)
- Installing numpy (2.3.2): Installing...
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0)
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2): Installing...
- Installing tzdata (2025.2)
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0)
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2)
- Installing numpy (2.3.2)
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pydantic (2.11.7)
- Installing python-dateutil (2.9.0.post0)
- Installing python-gitlab (6.2.0)
- Installing iniconfig (2.1.0)
- Installing rich (14.1.0)
- Installing shellingham (1.5.4)
- Installing tomlkit (0.13.3)
- Installing tzdata (2025.2)
- Installing pandas (2.3.1): Pending...
- Installing pytest (8.4.1): Pending...
- Installing python-semantic-release (10.3.1): Pending...
- Installing python-semantic-release (10.3.1): Pending...
- Installing pytest (8.4.1): Installing...
- Installing python-semantic-release (10.3.1): Pending...
- Installing python-semantic-release (10.3.1): Pending...
- Installing pytest (8.4.1)
- Installing python-semantic-release (10.3.1): Pending...
- Installing python-semantic-release (10.3.1): Installing...
- Installing pytest (8.4.1)
- Installing python-semantic-release (10.3.1): Installing...
- Installing pandas (2.3.1): Installing...
- Installing pytest (8.4.1)
- Installing python-semantic-release (10.3.1): Installing...
- Installing python-semantic-release (10.3.1)
- Installing pytest (8.4.1)
- Installing python-semantic-release (10.3.1)
- Installing pandas (2.3.1)
- Installing pytest (8.4.1)
- Installing python-semantic-release (10.3.1)
Writing lock file
Configure Python Semantic Release#
To configure python-semantic-release
, we will use the pyproject.toml
. We will add two sections to the file: [tool.semantic_release]
and [tool.semantic_release.remote]
. The first section will define the version variable, whether to commit the version number, and whether to upload to PyPI. The second section will define the remote repository’s name and type.
[tool.semantic_release]
version_variable = "pyproject.toml:version"
commit_version_number = true
upload_to_pypi = "false"
[tool.semantic_release.remote]
name = "origin"
type = "gitlab"
Setup Gitlab for Continuous Deployment#
Now we will add a semantic-release step to our .gitlab-ci.yml
file to automate the versioning and release process. This step will run in the deploy
stage and will be triggered when a commit is made to the default branch that follows semantic versioning in its commit message.
Let’s replace the content of the .gitlab-ci.yml
file with the following configuration:
image: python:latest
before_script:
- git checkout "$CI_COMMIT_REF_NAME"
- pip install poetry
- poetry install --only dev --no-root
semantic-release:
stage: deploy
rules:
- if: '$CI_COMMIT_MESSAGE =~ /^(\d+\.)?(\d+\.)?(\d+).*/ && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
when: never
- when: always
script:
- poetry run semantic-release -vvv version
- poetry run semantic-release -vvv publish
Let’s break down this GitLab CI/CD configuration to understand how it automates semantic versioning:
Docker Image Configuration#
image: python:latest
We use the python:latest
Docker image as our CI/CD environment. This provides a clean Python environment with pip and other Python tools pre-installed, ensuring consistent execution across different runners.
Global Setup (before_script)#
before_script:
- git checkout "$CI_COMMIT_REF_NAME"
- pip install poetry
- poetry install --only dev --no-root
The before_script
section runs before every job and performs essential setup:
git checkout "$CI_COMMIT_REF_NAME"
- Switches to the specific branch or tag that triggered the pipeline. The$CI_COMMIT_REF_NAME
variable contains the branch/tag name, ensuring we’re working with the correct commit.pip install poetry
- Installs Poetry package manager, which is required to manage our Python project dependencies.poetry install --only dev --no-root
- Installs only development dependencies (includingpython-semantic-release
) without installing the package itself. The--no-root
flag prevents Poetry from installing the current project as a package, which is suitable for CI environments.
Semantic Release Job Configuration#
semantic-release:
stage: deploy
This job runs in the deploy
stage, typically after build and test stages have completed successfully.
Job Execution Rules#
rules:
- if: '$CI_COMMIT_MESSAGE =~ /^(\d+\.)?(\d+\.)?(\d+).*/ && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
when: never
- when: always
The rules section implements smart logic to prevent infinite CI/CD loops:
First rule (
when: never
) - Prevents the job from running when:The commit message starts with a version number pattern (regex
^(\d+\.)?(\d+\.)?(\d+).*
matches patterns like1.2.3
,0.1.0
, etc.)AND the commit is on the default branch (
$CI_DEFAULT_BRANCH
is typicallymain
ormaster
)
This prevents semantic-release from triggering another pipeline when it creates its own version bump commits.
Second rule (
when: always
) - Runs the job in all other cases, ensuring semantic-release processes regular feature and bug fix commits.
Release Automation Scripts#
script:
- poetry run semantic-release -vvv version
- poetry run semantic-release -vvv publish
The script section executes two critical commands:
poetry run semantic-release -vvv version
- This command:Analyzes commit messages since the last release using conventional commit standards
Determines the next version number based on semantic commit types (
feat:
= minor,fix:
= patch,BREAKING CHANGE:
= major)Updates version numbers in
pyproject.toml
and other configured filesThe
-vvv
flag provides verbose logging for debugging
poetry run semantic-release -vvv publish
- This command:Creates a Git tag for the new version
Generates or updates the
CHANGELOG.md
file based on commit historyCreates a GitLab release with release notes
Pushes the changes and tags back to the repository
How the Automation Works#
Developer commits with semantic messages (e.g.,
feat: add user authentication
,fix: resolve login bug
)Pipeline triggers and the semantic-release job analyzes the commit history
Version calculation happens automatically based on commit types since the last release
Release artifacts are generated (tags, changelog, GitLab releases) without manual intervention
Loop prevention ensures semantic-release’s own version commits don’t trigger new releases
This automation ensures consistent versioning following semantic versioning principles, eliminates manual release management tasks, and provides clear release documentation through automatically generated changelogs.
Commit all changes#
Commit all the changes to the repository, using the message “feat(semantic-release): add semantic release to the repository”.
Make Semantic Commits#
To ensure python-semantic-release
correctly increments version numbers, use semantic commit messages (e.g., fix:
, feat:
, BREAKING CHANGE:
) for your commits. This practice helps the tool to automatically determine the next version number based on the changes made.
You can find more information about semantic commits messages supported by python-semantic-release
here.
What to notice
After pushing our first commit and successfully running
python-semantic-release
, the tool will automatically generate both a release and a tag for your project, as well as aCHANGELOG.md
file. You can find the generated release in the Releases section of themy-package
repository. This section provides detailed information about what’s new, improved, or fixed in each release, along with any associated assets.
Similarly, the automatically created tag, marking the specific point in the repository’s history for the release, can be found in the Tags section. Tags serve as important reference points, indicating version releases and facilitating easy navigation through the project’s version history.
See it in action#
You can create a new commit with a semantic commit message and push it to the repository to see python-semantic-release
in action. For example, you can create a new file in the repository and push it to the default branch.
cd tests
touch test.py
git add test.py
git commit -m "feat(test): add new test module"
git push --set-upstream origin master