Skip to content

feat: add improved parsing for labels and support for multiple fallbacks#4977

Open
robertcoltheart wants to merge 13 commits into
GitTools:mainfrom
robertcoltheart:feature/improved-regex-labelling
Open

feat: add improved parsing for labels and support for multiple fallbacks#4977
robertcoltheart wants to merge 13 commits into
GitTools:mainfrom
robertcoltheart:feature/improved-regex-labelling

Conversation

@robertcoltheart

@robertcoltheart robertcoltheart commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Description

Adds advanced label parsing to support multiple fallbacks.

Related Issue

Resolves #4976

Motivation and Context

This supports multiple fallbacks eg {env:ENV_VAR ?? Prop ?? "fallback"} which wasn't possible with the existing regex parsing. Any combination or number of properties, environment variables or literal values are supported. Property values can be considered as literals if they appear last in the chain.

There are some changes in behavior as below:

  1. Missing properties no longer throw if not found. This is because we can fallback from a property to another property, which may also be a literal value instead of a property. eg. {Prop1 ?? Prop2} will yield Prop2 if neither property is found.
  2. Incorrectly formatted syntax will throw (eg using ??? as a separator) whereas previously it would have just shown the unparsed syntax in the output. This is because we can't reliably determine which output to use, and using a manual parser means we can be stricter on the format than when using regex.

How Has This Been Tested?

Additional unit tests added for refactored parsing, and testing manually.

Screenshots (if appropriate):

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.

@robertcoltheart robertcoltheart force-pushed the feature/improved-regex-labelling branch from cf6ffb9 to 56ec6f8 Compare June 22, 2026 11:23
@arturcic

Copy link
Copy Markdown
Member

hey @robertcoltheart, do you think you can get this finalized and ready for review in soon? I'd want to prepare a new release, and I could wait to get this in.

@robertcoltheart

Copy link
Copy Markdown
Contributor Author

Yes this is basically done now. Just running final tests and will mark it ready hopefully today.

@arturcic

Copy link
Copy Markdown
Member

@robertcoltheart make sure to rebase onto main

@robertcoltheart robertcoltheart changed the title feat: add improved regex parsing for labels feat: add improved parsing for labels and support for multiple fallbacks Jun 23, 2026
@robertcoltheart robertcoltheart force-pushed the feature/improved-regex-labelling branch from 9cfca75 to 8663be0 Compare June 23, 2026 23:22
@robertcoltheart robertcoltheart marked this pull request as ready for review June 23, 2026 23:24
@robertcoltheart

Copy link
Copy Markdown
Contributor Author

@arturcic Waiting on tests to pass now, but this is ready for a review

@arturcic arturcic requested a review from HHobeck June 24, 2026 06:21
@arturcic

Copy link
Copy Markdown
Member

@HHobeck could would have a look on this one?

@asbjornu asbjornu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really great stuff! I especially like the increased test coverage as well as the clarity this brings to the parsing algorithm (moving logic from the Regex and into the LabelTokenizer). Good job!

Should.Throw<ArgumentException>(() =>
effectiveConfiguration.GetBranchSpecificLabel(ReferenceName.FromBranchName(BranchName), null, environment));
var actual = effectiveConfiguration.GetBranchSpecificLabel(ReferenceName.FromBranchName(BranchName), null, environment);
actual.ShouldBe("pr-");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change in behavior can be considered to be a breaking change. Perhaps not enough to warrant a major version bump, but worth mentioning in BREAKING_CHANGES.md? Otherwise we should consider supporting the previous behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment to breaking changes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. But when you want to have a fallback why do you not specify {env:MISSING_VAR ?? ""}? Don't understand the reason why this behavior change.

Comment thread src/GitVersion.Core/Formatting/LabelToken.cs Outdated
@arturcic arturcic added this to the 6.x milestone Jun 24, 2026
@arturcic arturcic modified the milestone: 6.x Jun 24, 2026
@gittools-bot gittools-bot requested a review from Copilot June 24, 2026 18:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates GitVersion’s custom string/label formatting to support multi-step fallback chains (e.g. {env:ENV_VAR ?? Prop ?? "fallback"}) by replacing the previous strict regex-based token parsing with a dedicated tokenizer/parser. This is aimed at fixing label formatting scenarios like {BranchName:c} (Issue #4976) and enabling more expressive fallback behavior across environment variables, properties, and literals.

Changes:

  • Replace the previous ExpandTokensRegex-driven parsing with a LabelTokenizer-based parser that supports chained ?? fallbacks and quoted literals.
  • Adjust placeholder resolution to avoid throwing on missing properties (and update tests to reflect new behavior).
  • Update docs/tests to cover the new fallback syntax and stricter malformed-token handling.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/GitVersion.Core/Formatting/StringFormatWithExtension.cs Switches evaluation to tokenizer-driven parsing and implements chained fallback evaluation + formatting.
src/GitVersion.Core/Formatting/MemberResolver.cs Changes missing-member behavior from throwing to returning an empty path to support fallback chains.
src/GitVersion.Core/Formatting/LabelTokenType.cs Adds token-type enum for the new parser.
src/GitVersion.Core/Formatting/LabelTokenizer.cs Implements the new parser/tokenizer for label expressions and separators.
src/GitVersion.Core/Formatting/LabelToken.cs Adds a token model used by the tokenizer/evaluator.
src/GitVersion.Core/Extensions/ConfigurationExtensions.cs Updates branch regex placeholder extraction (group name handling).
src/GitVersion.Core/Core/RegexPatterns.cs Broadens the token-matching regex to hand off parsing/validation to the tokenizer.
src/GitVersion.Core.Tests/Formatting/LabelTokenizerTests.cs Adds unit tests for token parsing scenarios (literals, identifiers, malformed inputs).
src/GitVersion.Core.Tests/Extensions/StringFormatWithExtensionTests.cs Expands tests to cover chained fallbacks and updated malformed-token behavior.
src/GitVersion.Configuration.Tests/Configuration/ConfigurationExtensionsTests.cs Updates expectations for missing env-var placeholder behavior in branch labels.
docs/input/docs/reference/mdsource/configuration.source.md Documents cascading fallbacks in label/environment placeholders.

Comment thread src/GitVersion.Core/Formatting/LabelTokenizer.cs
Comment thread src/GitVersion.Core/Formatting/StringFormatWithExtension.cs
Comment thread src/GitVersion.Core/Formatting/LabelTokenizer.cs Outdated
Comment thread src/GitVersion.Core/Extensions/ConfigurationExtensions.cs Outdated
Comment thread docs/input/docs/reference/mdsource/configuration.source.md Outdated
Comment thread src/GitVersion.Core/Formatting/StringFormatWithExtension.cs
@arturcic

Copy link
Copy Markdown
Member

@robertcoltheart could you please rebase once again onto main branch (sorry about the dependabot PRs keep being merged). @asbjornu do you mind to have a second look and approve?

@robertcoltheart robertcoltheart force-pushed the feature/improved-regex-labelling branch from f885834 to 2c308a8 Compare June 25, 2026 11:23
@robertcoltheart robertcoltheart requested a review from asbjornu June 25, 2026 11:24
@arturcic arturcic mentioned this pull request Jun 26, 2026

@asbjornu asbjornu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏🏼

Comment thread src/GitVersion.Core.Tests/Formatting/LabelTokenizerTests.cs Outdated
@mergify

mergify Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@arturcic arturcic force-pushed the feature/improved-regex-labelling branch from 2c308a8 to 0aa9be8 Compare June 26, 2026 10:26
@arturcic arturcic enabled auto-merge June 26, 2026 10:27
@HHobeck

HHobeck commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Hmm. But when you want to have a fallback why do you not specify {env:MISSING_VAR ?? ""}? Don't understand the reason why this behavior change.

I had one more comment on that.

@arturcic arturcic disabled auto-merge June 26, 2026 10:34
@arturcic

Copy link
Copy Markdown
Member

Hmm. But when you want to have a fallback why do you not specify {env:MISSING_VAR ?? ""}? Don't understand the reason why this behavior change.

I had one more comment on that.

@robertcoltheart can you check this one?

@arturcic arturcic force-pushed the feature/improved-regex-labelling branch 2 times, most recently from 174ffe8 to 93b8ed5 Compare June 26, 2026 17:30
@arturcic arturcic force-pushed the feature/improved-regex-labelling branch from 93b8ed5 to 8a0f8d5 Compare June 26, 2026 17:33
@sonarqubecloud

Copy link
Copy Markdown

@arturcic

Copy link
Copy Markdown
Member

@robertcoltheart I rebased and fixed some small conflict, could you please check with @HHobeck what needs to be done to have this PR complete?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ISSUE]: {BranchName} format strings for label not working

5 participants