Skip to content

feat: add support for environment variables in branch labels#4944

Merged
arturcic merged 8 commits into
GitTools:mainfrom
robertcoltheart:feature/enhance-branch-label-with-env-vars
Jun 10, 2026
Merged

feat: add support for environment variables in branch labels#4944
arturcic merged 8 commits into
GitTools:mainfrom
robertcoltheart:feature/enhance-branch-label-with-env-vars

Conversation

@robertcoltheart

Copy link
Copy Markdown
Contributor

Description

Supports environment variable substitution in the label configuration for a branch using the established format used elsewhere. Fallbacks are also supported if the environment variable is not found. The changes are backwards compatible and should not fail for existing configuration.

Documentation detailing the changes has been added to configuration.md.

Related Issue

Resolves #4745

Motivation and Context

Allow labels to include environment variables as well as regex-captured variables. This is useful for CICD environments like GitHub where the pull request head_ref can be provided instead of the merge commit target.

How Has This Been Tested?

Unit tests covering the new functionality have been added.

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.

Comment thread docs/input/docs/reference/configuration.md
@robertcoltheart

Copy link
Copy Markdown
Contributor Author

1 check is failing because the Nuke website is down.

@arturcic arturcic requested a review from HHobeck May 22, 2026 16:16
@robertcoltheart robertcoltheart requested a review from arturcic May 26, 2026 22:53
Comment thread docs/input/docs/learn/who.md
return label;
var labelPlaceholders = BuildLabelPlaceholders(configuration.RegularExpression, effectiveBranchName);

return label.FormatWith(labelPlaceholders, environment);

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.

Throws if environment variable is not found and has no fallback. This is deliberate to stay consistent with other usages of environment variables, for example in assembly file version.

@robertcoltheart

Copy link
Copy Markdown
Contributor Author

@HHobeck @arturcic Fixed a couple of issues that I missed. This is ready for review and merge now, thanks!

Comment thread src/GitVersion.Configuration.Tests/Configuration/ConfigurationExtensionsTests.cs Outdated

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.

Here are a few suggestions regarding this implementation:

  1. Use object instead of generics: Change the generic type T to object. It makes more sense here since a generic type parameter provides no extra benefit for this use case.

  2. Clarify supported types: The method currently supports instances of type object and IDictionary<string, object>, but this intent is not clearly expressed in the method body. I suggest splitting this into explicit overloads for better readability, like this:

internal static class StringFormatWithExtension
{
    extension(string template)
    {
        public string FormatWith(object? source, IEnvironment environment)
        {
            object? GetFromSource(string value)
            {
                // ...
            }

            object? GetFromEnvironment(string value) => environment.GetEnvironmentVariable(value);
            
            return template.FormatWith(GetFromSource, GetFromEnvironment);
        }

        public string FormatWith(IDictionary<string, object> source, IEnvironment environment)
        {
            object? GetFromSource(string value)
            {
                source.TryGetValue(value, out var result);
                return result;
            }

            object? GetFromEnvironment(string value) => environment.GetEnvironmentVariable(value);

            return template.FormatWith(GetFromSource, GetFromEnvironment);
        }

        private string FormatWith(
            Func<string, object?> getFromSource, Func<string, object?> getFromEnvironment)
        {
            // ...
        }
    }
}
  1. Allow flexible placeholder combinations: It does not make sense to restrict how placeholders can occur. Why shouldn't all of the following combinations be valid?
  • {JustAProperty}
  • {JustAProperty ?? "JustAFallback"}
  • {JustAProperty} ?? {env:JustAVariable}
  • {JustAProperty} ?? {env:JustAVariable} ?? "JustAFallback"
  • {env:JustAVariable}
  • {env:JustAVariable} ?? "JustAFallback"
  • {env:JustAVariable} ?? {JustAProperty}
  • {env:JustAVariable} ?? {JustAProperty} ?? "JustAFallback"

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.

1 and 2, fair enough, will make these changes.

For 3, it was written this way (and I'm guessing the original implementor in #4746 did it this way for the same reason) to remain compatible/easy to understand as the existing configuration options for label and for assembly-file-versioning-format, where the {env:} syntax is derived from. The understanding I have is that {Name} syntax is reserved for regex captures, whereas {env:} is used for environment variables. I think it would be more confusing given the language that the configuration has cultivated to conflate these 2 concepts.

If the longer-term intention is to further enhance the regex/env var to support this conflation, I'd suggest doing this in a follow up change rather than here. Let me know your thoughts on this.

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.

For 3, it was written this way (and I'm guessing the original implementor in #4746 did it this way for the same reason) to remain compatible/easy to understand as the existing configuration options for label and for assembly-file-versioning-format, where the {env:} syntax is derived from. The understanding I have is that {Name} syntax is reserved for regex captures, whereas {env:} is used for environment variables. I think it would be more confusing given the language that the configuration has cultivated to conflate these 2 concepts.

Good question. @asbjornu @arturcic: What do you think?

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.

Any thoughts on this guys?

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.

I'm not sure I understand the following statement:

The understanding I have is that {Name} syntax is reserved for regex captures

From the documentation:

Expressions in curly braces reference one of the variables or a process-scoped environment variable (when prefixed with env:).

So for {Name}, Name would represent a GitVersion variable called Name. I think @HHobeck's example (in the configuration context):

assembly-file-versioning-format: '{env:JustAVariable} ?? {JustAProperty} ?? "JustAFallback"`'

Should be possible as follows:

assembly-file-versioning-format: '{env:JustAVariable ?? JustAProperty ?? "JustAFallback"}'

…the difference being the placement of the braces, which IIRC needs to embrace the entire expression. Whether one, two or multiple fallback values are possible already is not something I have tested, but I think it's something that should be supported.

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.

Should be possible as follows:

assembly-file-versioning-format: '{env:JustAVariable ?? JustAProperty ?? "JustAFallback"}'

I agree. The would be the correction:

  • {JustAProperty}
  • {JustAProperty ?? "JustAFallback"}
  • {JustAProperty ?? env:JustAVariable}
  • {JustAProperty ?? env:JustAVariable ?? "JustAFallback"}
  • {env:JustAVariable}
  • {env:JustAVariable ?? "JustAFallback"}
  • {env:JustAVariable ?? JustAProperty}
  • {env:JustAVariable ?? JustAProperty ?? "JustAFallback"}

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.

Fair enough, if that's the consensus I'll have a go at implementing it in this 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.

Awesome! But feel free to create a separate PR if you'd like.

@arturcic

arturcic commented Jun 9, 2026

Copy link
Copy Markdown
Member

@robertcoltheart please rebase onto main and fix the sonarcloud

@arturcic

Copy link
Copy Markdown
Member

@robertcoltheart could you please rebase instead of merging main into your branch? Thanks in advance. See https://github.com/GitTools/GitVersion/blob/main/CONTRIBUTING.md#git-history--pull-request-updates

@robertcoltheart robertcoltheart force-pushed the feature/enhance-branch-label-with-env-vars branch from 854bae7 to 2627649 Compare June 10, 2026 10:08
@arturcic

Copy link
Copy Markdown
Member

@robertcoltheart please fix the Sonar Cloud issue as well https://sonarcloud.io/project/issues?id=GitTools_GitVersion&pullRequest=4944&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true

@arturcic

arturcic commented Jun 10, 2026

Copy link
Copy Markdown
Member

@robertcoltheart is there anything left to be fixed/implemented based on the feedback. I'm considering to prepare a new release soon and was wondering if we can include this in the new release

@robertcoltheart

Copy link
Copy Markdown
Contributor Author

No I'm happy with this for now. I can address the updated fallback logic in a separate pull request.

@arturcic

Copy link
Copy Markdown
Member

@asbjornu @HHobeck can you have a second review and approve it if you're fine with the current state

@arturcic arturcic force-pushed the feature/enhance-branch-label-with-env-vars branch from d047baf to 8d1e896 Compare June 10, 2026 20:01
@arturcic arturcic enabled auto-merge June 10, 2026 20:01
@arturcic arturcic added this to the 6.x milestone Jun 10, 2026
@sonarqubecloud

Copy link
Copy Markdown

@arturcic

Copy link
Copy Markdown
Member

@Mergifyio refresh

@mergify

mergify Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

refresh

✅ Pull request refreshed

@arturcic arturcic disabled auto-merge June 10, 2026 20:38
@arturcic arturcic merged commit 375cb8d into GitTools:main Jun 10, 2026
218 of 219 checks passed
@mergify

mergify Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Thank you @robertcoltheart for your contribution!

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ISSUE]: Provide the ability to use environment variables in labels

4 participants