GitHub: GitHub Actions Release Versioning Guide
web csharp apps ai
A previous post covered creating a publishing a built version of a WPF app every time the repository is updated. This covers tying the major and minor release number to the project’s major and minor version numbers.
Preamble
This document explains how to implement automatic GitHub Release numbering where:
- The major.minor version comes from your project’s
.csprojfile. - The patch/release sequence is automatically incremented by GitHub Actions.
- When the project version changes, the release sequence automatically resets to
1.
There is a release.yml file in the project folder: .github/workflow/release.yml that orchestrates a new release build when the repsoitory is updated.
Releases are then accessed via ‘repsitory url on GitHub’/’releases’
Previous post GitHub: Creating Releases
Example
If your project version is:
<Version>4.0</Version>
GitHub releases will be created as:
v4.0.1
v4.0.2
v4.0.3
When the project version changes to:
<Version>4.1</Version>
The next release becomes:
v4.1.1
and continues:
v4.1.2
v4.1.3
Step 1 - Read the Project Version
The workflow reads the version from the project’s .csproj file.
Example:
<PropertyGroup>
<Version>4.0</Version>
</PropertyGroup>
GitHub Actions reads this value and stores it for later use.
- name: Read project version
id: version
shell: pwsh
run: |
[xml]$proj = Get-Content "SwissTimingDisplay/SwissTimingDisplay.csproj"
$version = $proj.Project.PropertyGroup.Version
if (-not $version) {
$version = $proj.Project.PropertyGroup.VersionPrefix
}
if (-not $version) {
throw "No Version or VersionPrefix found in csproj"
}
"VERSION=$version" >> $env:GITHUB_OUTPUT
Result
VERSION = 4.0
Step 2 - Fetch Existing Tags
GitHub only downloads a shallow copy of the repository by default.
To determine the next release number, all tags must be available locally.
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch tags
run: git fetch --tags
Example Existing Tags
v3.0.4
v3.0.5
v4.0.1
v4.0.2
v4.0.3
These tags are now available to the workflow.
Step 3 - Determine the Next Release Number
The workflow searches all tags matching the current project version.
For a project version of:
4.0
it searches for:
v4.0.*
Logic
- Find all matching tags.
- Extract the final number.
- Determine the highest value.
- Increment it by one.
- Build the next tag.
- name: Determine next release tag
id: tag
shell: pwsh
run: |
$baseVersion = "$"
$tags = git tag -l "v$baseVersion.*"
if (-not $tags) {
$nextPatch = 1
}
else {
$highest = $tags |
ForEach-Object {
($_ -split '\.')[-1]
} |
Measure-Object -Maximum |
Select-Object -ExpandProperty Maximum
$nextPatch = $highest + 1
}
$releaseTag = "v$baseVersion.$nextPatch"
"RELEASE_TAG=$releaseTag" >> $env:GITHUB_OUTPUT
Example A
Existing tags:
v4.0.1
v4.0.2
v4.0.3
Result:
v4.0.4
Example B
Project version:
4.1
No matching tags exist:
v4.1.*
Result:
v4.1.1
Step 4 - Create the Release
Once the next version number has been calculated, GitHub Actions:
- Creates a Git tag.
- Pushes the tag to GitHub.
- Creates a GitHub Release.
- Uploads the application ZIP file.
Create the Tag
- name: Create git tag
shell: pwsh
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag "$"
git push origin "$"
Create the GitHub Release
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: $
generate_release_notes: true
files: $-$.zip
env:
GITHUB_TOKEN: $
Example Output
If the project version is:
4.0
and the latest release is:
v4.0.3
the workflow automatically creates:
Tag: v4.0.4
Release: v4.0.4
Asset: SwissTimingDisplay-v4.0.4.zip
Summary
The workflow now follows a simple versioning strategy:
| Project Version | Releases Generated |
|---|---|
| 4.0 | v4.0.1, v4.0.2, v4.0.3… |
| 4.1 | v4.1.1, v4.1.2, v4.1.3… |
| 5.0 | v5.0.1, v5.0.2, v5.0.3… |
Benefits:
- Project version remains under developer control.
- Release numbering is automatic.
- No dependency on GitHub workflow run numbers.
- Release sequence automatically resets when the major/minor version changes.
- Git tags, GitHub releases, and published artifacts stay aligned.
Footnote
This was generated with some help from Copilot after working through teh mechanism.
| Topic | Subtopic | |
| < Prev: | System Recovering | 🔐 Recovering Data From a BitLocker‑Encrypted Windows Drive Using WinPE |
| This Category Links | ||
| Category: | Web Sites Index: | Web Sites |