Skip to content

Add CustomVersion output variable - #5098

Merged
mergify[bot] merged 7 commits into
GitTools:mainfrom
arturcic:feature/custom-version
Jul 30, 2026
Merged

Add CustomVersion output variable#5098
mergify[bot] merged 7 commits into
GitTools:mainfrom
arturcic:feature/custom-version

Conversation

@arturcic

@arturcic arturcic commented Jul 24, 2026

Copy link
Copy Markdown
Member

Description

Adds a configurable CustomVersion output variable controlled by custom-version-format. The format supports the existing version-variable and environment-variable formatters and defaults to {SemVer} without changing the semantics of existing outputs.

The value is available in JSON output, generated version files, WiX output, and the MSBuild GetVersion task. Configuration, CLI override, output approvals, documentation, and generated schemas are updated as well.

Related Issue

Closes #1674
Closes #2065
Closes #3340
Closes #4659

Supersedes the implementation attempted in #4659 and follows the design described in discussion #4272.

Motivation and Context

Consumers sometimes need a version format with semantics different from GitVersion's standard outputs. Examples covered by this change include:

  • PEP 440-compatible pre-release versions such as 0.6.3beta10.
  • Fixed-width monotonically increasing integer versions for Android, such as 0001000.
  • CI-owned build numbers supplied through environment variables.
  • RPM/YUM-safe versions without dashes in the release value.

For #1674, separators in a branch-derived label can be removed with the PascalCase formatter:

custom-version-format: '{MajorMinorPatch}.{PreReleaseLabel:c}.{PreReleaseNumber}'

When the exact replacement must be controlled—for example, preserving JIRA.123 instead of reducing JIRA-123 to Jira123—replace {PreReleaseLabel:c} with an environment variable containing the desired RPM-safe label:

custom-version-format: '{MajorMinorPatch}.{env:RPM_PRERELEASE_LABEL}.{PreReleaseNumber}'

How Has This Been Tested?

  • dotnet build ./src/GitVersion.slnx --no-restore
  • dotnet test --project ./src/GitVersion.Configuration.Tests/GitVersion.Configuration.Tests.csproj --no-restore — 97 passed
  • App parser override tests — 40 passed
  • Relevant Core variable, JSON, and executor tests — 37 passed
  • dotnet test --project ./src/GitVersion.Output.Tests/GitVersion.Output.Tests.csproj --no-restore — 123 passed
  • dotnet test --project ./src/GitVersion.MsBuild.Tests/GitVersion.MsBuild.Tests.csproj --no-restore — 151 passed
  • dotnet format ./src/GitVersion.slnx --verify-no-changes --no-restore
  • Configuration and output schemas regenerated successfully

A broader Core test run reached an unrelated timing-sensitive failure in PerformanceScenarios.RepositoryWithALotOfTags (3518 ms versus the 2500 ms threshold); all CustomVersion-related tests pass.

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed. See the performance-test note above.

@HHobeck

HHobeck commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Nice catch. I haven't found any issues with the implementation. The only point I'd like to raise is that, from a conceptual point of view, I think this property should be configurable on a per-branch basis if we want to properly support e.g. PEP 440.

See:

@arturcic
arturcic force-pushed the feature/custom-version branch from d07f576 to 13ac2ff Compare July 29, 2026 21:49
@arturcic
arturcic force-pushed the feature/custom-version branch from 13ac2ff to 5723c9e Compare July 29, 2026 21:56
@arturcic

Copy link
Copy Markdown
Member Author

@HHobeck move the property to BranchConfiguration instead, please review

@HHobeck

HHobeck commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
internal record BranchConfiguration : IBranchConfiguration
{
    [JsonPropertyName("custom-version-format")]
    [JsonPropertyDescription($"Specifies the format of CustomVersion. Defaults to '{DefaultCustomVersionFormat}'.")]
    [JsonPropertyDefault($"'{DefaultCustomVersionFormat}'")]
    public string? CustomVersionFormat { get; set; }
    ...
}

I would prefer not to define fallback configuration values in code. We usually rely on predefined workflows to provide default values, which makes those defaults transparent to the end user.

Also, I'm not sure a default value of SemVer for custom-version-format is necessary. As the name suggests, it's intended for custom formatting. Why would we output the semantic version twice?

Edit:
That means for GitHubFlow, GitFow and TrunkBased workflow I would leave it empty.

@arturcic

Copy link
Copy Markdown
Member Author

We usually rely on predefined workflows to provide default values, which makes those defaults transparent to the end user.

Good catch

@HHobeck

HHobeck commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

I was also thinking about removing DeploymentMode and using the new formatting scheme to generate the different version formats instead. That would require a more generic property name than custom-version-format. The DeploymentMode effects only how the semver will be formatted.

What do you think? @asbjornu

@HHobeck

HHobeck commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Maybe I'm wrong and it is more then just formatting:

image

@arturcic

Copy link
Copy Markdown
Member Author

I will focus only on adding the possibility to specify a custom version format so it can be used to generate custom version and later we can decide on how to extend or make it more generci

Comment thread src/GitVersion.Core.Tests/VersionCalculation/VariableProviderTests.cs Outdated
@arturcic
arturcic force-pushed the feature/custom-version branch from 06ee9eb to 51f7a58 Compare July 30, 2026 15:02
@sonarqubecloud

Copy link
Copy Markdown

@arturcic
arturcic enabled auto-merge July 30, 2026 15:05
@mergify

mergify Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Queued — the merge queue status continues in this comment ↓.

@mergify

mergify Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-07-30 15:20 UTC · Rule: default · triggered by @arturcic with the merge queue checkbox
  • Checks skipped · PR is already up-to-date
  • Merged2026-07-30 15:21 UTC · at 51f7a58efedfae47014692f6cad139543bc6fae5 · merge

This pull request spent 14 seconds in the queue, including 2 seconds running CI.

Required conditions to merge
  • github-review-approved [🛡 GitHub repository ruleset rule main branch rule]
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/DotNet Format
    • check-neutral = @github-actions/DotNet Format
    • check-skipped = @github-actions/DotNet Format
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Release
    • check-neutral = @github-actions/Release
    • check-skipped = @github-actions/Release
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Build & Test (new-cli)
    • check-neutral = @github-actions/Build & Test (new-cli)
    • check-skipped = @github-actions/Build & Test (new-cli)
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Build & Package / macos-26
    • check-neutral = @github-actions/Build & Package / macos-26
    • check-skipped = @github-actions/Build & Package / macos-26
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Build & Package / ubuntu-24.04
    • check-neutral = @github-actions/Build & Package / ubuntu-24.04
    • check-skipped = @github-actions/Build & Package / ubuntu-24.04
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Build & Package / windows-2025-vs2026
    • check-neutral = @github-actions/Build & Package / windows-2025-vs2026
    • check-skipped = @github-actions/Build & Package / windows-2025-vs2026
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Test / macos-26 - net10.0
    • check-neutral = @github-actions/Test / macos-26 - net10.0
    • check-skipped = @github-actions/Test / macos-26 - net10.0
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Test / ubuntu-24.04 - net10.0
    • check-neutral = @github-actions/Test / ubuntu-24.04 - net10.0
    • check-skipped = @github-actions/Test / ubuntu-24.04 - net10.0
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @github-actions/Test / windows-2025-vs2026 - net10.0
    • check-neutral = @github-actions/Test / windows-2025-vs2026 - net10.0
    • check-skipped = @github-actions/Test / windows-2025-vs2026 - net10.0
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-neutral = Mergify Merge Protections
    • check-skipped = Mergify Merge Protections
    • check-success = Mergify Merge Protections
  • any of [🛡 GitHub repository ruleset rule main branch rule]:
    • check-success = @sonarqubecloud/SonarCloud Code Analysis
    • check-neutral = @sonarqubecloud/SonarCloud Code Analysis
    • check-skipped = @sonarqubecloud/SonarCloud Code Analysis

@mergify mergify Bot added the queued label Jul 30, 2026
@mergify
mergify Bot merged commit 329cbe9 into GitTools:main Jul 30, 2026
59 checks passed
@mergify

mergify Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Thank you @arturcic for your contribution!

@mergify mergify Bot removed the queued label Jul 30, 2026
@arturcic
arturcic deleted the feature/custom-version branch July 30, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants