|
1 | 1 | # Versioning |
2 | 2 |
|
3 | | -## Auto Generated Version Examples |
4 | | -These are examples of how our configuration of [poetry-dynamic-versioning](https://github.com/mtkennerly/poetry-dynamic-versioning) will generate the version number. |
5 | | - |
6 | | -If branch is not main and there are commits since last tag: |
7 | | -``` |
8 | | -tux 0.0.0.dev2106+b731156.dynamicversioning |
9 | | -^ ^ ^ ^ ^ |
10 | | -name^ commits commit branch (escaped), is empty if its main |
11 | | - ver since hash |
12 | | - last |
13 | | - tag |
14 | | -``` |
15 | | -If branch is main and there are commits since last tag: |
16 | | -``` |
17 | | -tux 0.0.0.dev2106+b731156 |
18 | | -^ ^ ^ ^ |
19 | | -name^ commits commit |
20 | | - ver since hash |
21 | | - last |
22 | | - tag |
23 | | -``` |
24 | | -If branch is main and there are no commits since last tag: |
25 | | -``` |
26 | | -tux 0.0.0 |
27 | | -^ ^ |
28 | | -name^ |
29 | | - ver |
30 | | -``` |
31 | | - |
32 | | -## Scheme |
33 | | -We use PEP 440 for formatting our version numbers, however we use SemVer for the versioning scheme. |
34 | | -> Keep in mind you cannot use .dev(NUMBER) as it clashes with the auto generated versioning. (e.g 0.1.0rc1.dev1 is invalid and won't show up properly) |
35 | | -
|
36 | | -## SemVer Summary |
37 | | -A example in tux would be: |
38 | | -Given a version number MAJOR.MINOR.PATCH, increment the: |
39 | | - |
40 | | -MAJOR version when you make changes that may need significant manual setup from the last version (example would be a web panel, config overhaul, major db changes) |
41 | | -MINOR version when you make changes that needs little to no manual interference (at most maybe tweaking a config value or updating the db) |
42 | | -PATCH version when you make changes that need no manual interference |
43 | | - |
44 | | -You can add stuff like "0.1.0**rc1**" to mark small changes leading up to a release. (release candidates) |
45 | | - |
46 | | -You do not need to stick to this absolutely all the time, this is a guideline on how to make your versioning. |
| 3 | +This document outlines the versioning scheme, detection logic, and release process for the Tux project. Our system is designed to provide consistent and reliable versioning across development, testing, and production environments. |
| 4 | + |
| 5 | +## Versioning Scheme |
| 6 | + |
| 7 | +We follow the [Semantic Versioning (SemVer)](https://semver.org/) specification for our release cycle. Version numbers are formatted as `MAJOR.MINOR.PATCH`. |
| 8 | + |
| 9 | +- **MAJOR**: Incremented for incompatible API changes or significant architectural shifts that may require manual intervention during an upgrade (e.g., major config or database schema changes). |
| 10 | +- **MINOR**: Incremented for new, backward-compatible functionality. |
| 11 | +- **PATCH**: Incremented for backward-compatible bug fixes. |
| 12 | + |
| 13 | +Release candidates can be denoted with suffixes (e.g., `1.0.0-rc1`). |
| 14 | + |
| 15 | +## Version Detection |
| 16 | + |
| 17 | +The application version is determined dynamically at runtime. The `tux/__init__.py` module contains a robust detection mechanism that checks multiple sources in a specific order of priority. This ensures that the version is always available, regardless of the environment. |
| 18 | + |
| 19 | +The `version` field in `pyproject.toml` is intentionally set to a static placeholder (`0.0.0`) because the true version is resolved dynamically. |
| 20 | + |
| 21 | +### Priority Order |
| 22 | + |
| 23 | +The version is sourced by trying the following methods in order, stopping at the first success: |
| 24 | + |
| 25 | +1. **`TUX_VERSION` Environment Variable**: |
| 26 | + - **Usage**: A runtime override. |
| 27 | + - **Example**: `TUX_VERSION=1.2.3-custom tux --dev start` |
| 28 | + - **Priority**: Highest. If set, this value is always used. |
| 29 | + |
| 30 | +2. **`VERSION` File**: |
| 31 | + - **Usage**: The primary versioning method for Docker images. This file is generated during the Docker build process. |
| 32 | + - **Location**: Project root (`/app/VERSION` inside the container). |
| 33 | + |
| 34 | +3. **Git Tags (`git describe`)**: |
| 35 | + - **Usage**: The standard for development environments where the Git history is available. |
| 36 | + - **Format**: It produces version strings like: |
| 37 | + - `1.2.3`: For a commit that is tagged directly. |
| 38 | + - `1.2.3-10-gabc1234`: For a commit that is 10 commits ahead of the `v1.2.3` tag. |
| 39 | + - `1.2.3-10-gabc1234-dirty`: If there are uncommitted changes. |
| 40 | + - **Note**: The leading `v` from tags (e.g., `v1.2.3`) is automatically removed. |
| 41 | + |
| 42 | +4. **Package Metadata (`importlib.metadata`)**: |
| 43 | + - **Usage**: For when Tux is installed as a package from PyPI or a wheel file. |
| 44 | + - **Mechanism**: Reads the version from the installed package's metadata. |
| 45 | + |
| 46 | +5. **Fallback to `"dev"`**: |
| 47 | + - **Usage**: A final fallback if all other methods fail, ensuring the application can always start. |
| 48 | + |
| 49 | +## Release Cycle and Git Tagging |
| 50 | + |
| 51 | +The release process is centered around Git tags. |
| 52 | + |
| 53 | +1. **Create a Release**: To create a new version, create and push an annotated Git tag: |
| 54 | + |
| 55 | + ```sh |
| 56 | + # Example for a patch release |
| 57 | + git tag -a v1.2.3 -m "Release v1.2.3" |
| 58 | + git push origin v1.2.3 |
| 59 | + ``` |
| 60 | + |
| 61 | +2. **Development Version**: Between releases, any new commits will result in a development version string (e.g., `1.2.3-5-g567def8`), indicating progress since the last tag. |
| 62 | + |
| 63 | +## Docker Image Tagging |
| 64 | + |
| 65 | +Our Docker build process is designed to bake the version directly into the image, ensuring traceability. |
| 66 | + |
| 67 | +- **Build Process**: The `Dockerfile` uses a build argument (`VERSION`) to create a `VERSION` file inside the image. This file becomes the source of truth for the version within the container. |
| 68 | + |
| 69 | +- **Building an Image**: To build a versioned image, pass the `VERSION` argument, preferably derived from `git describe`: |
| 70 | + |
| 71 | + ```sh |
| 72 | + # Recommended command to build a production image |
| 73 | + docker build \ |
| 74 | + --build-arg VERSION=$(git describe --tags --always --dirty | sed 's/^v//') \ |
| 75 | + --target production \ |
| 76 | + -t your-registry/tux:latest . |
| 77 | + ``` |
| 78 | + |
| 79 | + You can also tag the image with the specific version: |
| 80 | + |
| 81 | + ```sh |
| 82 | + # Tag with the specific version for better tracking |
| 83 | + VERSION_TAG=$(git describe --tags --always --dirty | sed 's/^v//') |
| 84 | + docker build \ |
| 85 | + --build-arg VERSION=$VERSION_TAG \ |
| 86 | + --target production \ |
| 87 | + -t your-registry/tux:$VERSION_TAG \ |
| 88 | + -t your-registry/tux:latest . |
| 89 | + ``` |
| 90 | + |
| 91 | +This ensures that even in a detached production environment without Git, the application reports the correct version it was built from. |
0 commit comments