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 .csproj file.
  • 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

  1. Find all matching tags.
  2. Extract the final number.
  3. Determine the highest value.
  4. Increment it by one.
  5. 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:

  1. Creates a Git tag.
  2. Pushes the tag to GitHub.
  3. Creates a GitHub Release.
  4. 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.


 TopicSubtopic
<  Prev:   System Recovering
   
 This Category Links 
Category:Web Sites Index:Web Sites