2026-10-25 21:19:42 +01:00
|
|
|
# Versioning
|
|
|
|
|
|
|
|
|
|
Versions are driven by semantic commits and release tags. We do not infer a
|
|
|
|
|
release version from branch names or build history.
|
|
|
|
|
|
|
|
|
|
## Semantic commits
|
|
|
|
|
|
|
|
|
|
Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
|
|
|
for changes. The format is:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
<type>[optional scope]: <description>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Common types are:
|
|
|
|
|
|
|
|
|
|
- `feat`: a new feature
|
|
|
|
|
- `fix`: a bug fix
|
|
|
|
|
- `docs`: documentation-only changes
|
|
|
|
|
- `style`: formatting or other non-functional changes
|
|
|
|
|
- `refactor`: code changes without a feature or fix
|
|
|
|
|
- `perf`: a performance improvement
|
|
|
|
|
- `test`: tests
|
|
|
|
|
- `build`: build or dependency changes
|
|
|
|
|
- `ci`: continuous-integration changes
|
|
|
|
|
- `chore`: maintenance work
|
|
|
|
|
- `revert`: a reverted commit
|
|
|
|
|
|
|
|
|
|
Scopes are optional and identify the affected area, for example:
|
|
|
|
|
`feat(api): add health endpoint`. Use a short, consistent, project-specific
|
|
|
|
|
scope when one is useful.
|
|
|
|
|
|
|
|
|
|
Append `!` after the type or scope for a breaking change, or include a
|
|
|
|
|
`BREAKING CHANGE:` footer. For example:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
feat(api)!: replace authentication endpoint
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Version increments
|
|
|
|
|
|
|
|
|
|
The next release version is incremented from the previous release using only
|
|
|
|
|
`fix`, `feat`, and breaking-change markers:
|
|
|
|
|
|
|
|
|
|
- **Major**: any commit marked with `!` or containing a `BREAKING CHANGE:`
|
|
|
|
|
footer
|
|
|
|
|
- **Minor**: otherwise, any `feat` commit
|
|
|
|
|
- **Patch**: otherwise, any `fix` commit
|
|
|
|
|
|
|
|
|
|
Other commit types do not increment the version. If multiple applicable
|
|
|
|
|
commits exist, the highest increment wins.
|
|
|
|
|
|
|
|
|
|
## Build metadata
|
|
|
|
|
|
|
|
|
|
Builds that are not releases carry metadata identifying their source:
|
|
|
|
|
|
|
|
|
|
- **Pull requests:** `pr.<number>.sha.<sha>`
|
|
|
|
|
- **Main branch:** `sha.<sha>`
|
|
|
|
|
|
|
|
|
|
The main branch is labelled `next` for the upcoming release.
|
2026-10-25 21:36:51 +01:00
|
|
|
The resulting versions use SemVer build metadata, for example:
|
|
|
|
|
`0.0.0-next+sha.<sha>`.
|
2026-10-25 21:19:42 +01:00
|
|
|
|
|
|
|
|
## Releases
|
|
|
|
|
|
|
|
|
|
A tag is the release. The version is taken directly from the tag; it is never
|
|
|
|
|
computed by the build system. Release tags must therefore contain the complete
|
|
|
|
|
release version (for example, `1.2.3`). The tag and the version exported to
|
|
|
|
|
the .NET CLI are both `1.2.3`; no `v` prefix is used.
|
|
|
|
|
|
|
|
|
|
## Version action
|
|
|
|
|
|
|
|
|
|
Version calculation and commit validation are provided by a reusable action. It
|
|
|
|
|
is written in Bash only and runs as the first step after checkout in each
|
|
|
|
|
workflow.
|
|
|
|
|
|
|
|
|
|
The action selects commits according to the workflow ref:
|
|
|
|
|
|
|
|
|
|
- **Pull requests:** commits belonging to the pull request only; commits
|
|
|
|
|
already present on the target branch are excluded.
|
|
|
|
|
- **Main:** commits since the previous release tag.
|
|
|
|
|
- **Release tags:** no version is computed; the tag version is used directly.
|
|
|
|
|
|
|
|
|
|
The action then:
|
|
|
|
|
|
|
|
|
|
1. validates the applicable commit messages against the Conventional Commits
|
|
|
|
|
format;
|
|
|
|
|
2. calculates the version from the previous release tag and the applicable
|
|
|
|
|
commits, unless the current ref is a release tag; and
|
|
|
|
|
3. exports the calculated version and its label/build metadata as action
|
|
|
|
|
outputs for later steps. Jobs are responsible for mapping those outputs to
|
|
|
|
|
environment variables when needed.
|