Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Root configuration should propagate to branches #2388

Closed
Tognolo opened this issue Aug 19, 2020 · 20 comments
Closed

[Feature] Root configuration should propagate to branches #2388

Tognolo opened this issue Aug 19, 2020 · 20 comments

Comments

@Tognolo
Copy link

Tognolo commented Aug 19, 2020

Hello, I'd like to use the GitVersionTask package to version my code, but I can't get information about it's configuration. I see a lot of configuration about the usage of the MsBuild setup, but it's not clear if the GitVersionTask package is enough or I've to install other packages. Any demo configuration is blessed.

@asbjornu
Copy link
Member

You just install the NuGet package. Nothing else should be required.

@Tognolo
Copy link
Author

Tognolo commented Aug 19, 2020

I did it. But I can't get the right version in my libraries. E.g., I'm getting a version 2.4.0 for my DLLs, even if I didn't wrote that tag in any of my projects, neither in the code. Also, it's not clear which branch is using to work.

How can I run it in debug mode?

Edit: I just added the tag "2.3.8-alpha.1" to the develop (the previous one is "2.3.6") but I get the message "Failed to inherit Increment branch configuration, no branches found".

Edit 2: I'm renaming my tags to v2.x.x, but originally my tags are version/2.x.x, where I can setup the tag prefix using GitVersionTask package?

@asbjornu
Copy link
Member

If you want more insight into why and how GitVersion calculates a given version number, I recommend you install the command line version and run it in the solution root. Its logs should give you an idea into what it bases the version number on. The command line is packaged in many different ways, so which one you should install is up to you. You can find the different variants detailed in #2326.

@Tognolo
Copy link
Author

Tognolo commented Aug 19, 2020

Running the command line gave me a better comprehension of how it works. Now I can ask a more specific question. I have the current tags sequences (and relative incremented versions):

  • 2.3.9 (current tag) >> 2.3.9
  • 2.3.8 >> 2.4.0
  • 2.3.3 (the oldest, the previous ones are gone...) >> 2.4.0

In BaseVersionCalculator.GetBaseVersion it gets all the base versions and for each one calculates the incremented version, so for every commit it will be 2.4.0, except the current one. At this point there is:

var maxVersion = baseVersions
    .Aggregate((v1, v2) => v1.IncrementedVersion > v2.IncrementedVersion ? v1 : v2); // it is 2.3.8
var matchingVersionsOnceIncremented = baseVersions
    .Where(b => b.Version.BaseVersionSource != null && b.IncrementedVersion == maxVersion.IncrementedVersion)
    .ToList();

matchingVersionsOnceIncremented has every commit except the current one, because 2.3.9 < 2.4.0. At this point I need to understand how to:

  • bump patch instead of minor value;
  • set versioning mode to MainLIne.

Update

I was able to create the GitVersion.yml file in the right place with the right values. One question, as documentation says:

The part of the SemVer to increment when GitVersion detects it needs to be increased, such as for commits after a tag: Major, Minor, Patch, None.

The special value Inherit means that GitVersion should find the parent branch (i.e. the branch where the current branch was branched from), and use its values for increment, prevent-increment-of-merged-branch-version and tracks-release-branches.

But in ConfigExtensions.CalculateEffectiveConfiguration method the increment strategy is:

var incrementStrategy = currentBranchConfig.Increment.Value;

So the base setup is always overridden by branch configuration.

@asbjornu
Copy link
Member

I'm happy you've figured out so much by yourself, @Tognolo. Can you please paste your GitVersion.yml file and explain which branches you have and version(s) you expect?

@Tognolo
Copy link
Author

Tognolo commented Sep 1, 2020

This is my GitVersion.yml:

tag-prefix: 'version\/|rc\/'
increment: None
branches: 
  develop:
    increment: None
  master:
    increment: None

I had to add the branches section to have the increment behaviour to None in develop and master branches. For the other branches the increment works as default, even if i set increment: None ad default setup. I expected that this configuration would be enough for my scenario:

tag-prefix: 'version\/|rc\/'
increment: None

@asbjornu
Copy link
Member

asbjornu commented Sep 1, 2020

I agree, this is something we should consider changing in v6.

@asbjornu asbjornu changed the title [Docs] Use of GitVersionTask package [Feature] Root configuration should propagate to branches Sep 1, 2020
@asbjornu asbjornu added this to the 6.0.0 milestone Sep 1, 2020
@HHobeck
Copy link
Contributor

HHobeck commented Oct 2, 2022

I have thought about the concept. In my opinion we need to introduce a fallback and a unknown branch configuration. The fallback branch configuration might be (like in your example) be defined on the root configuration layer. But what I don't like with this solution is you do not see if it is related to the fallback setting or is it related to the overall setting of GitVersion.

Another solution might be to explicit separate the fallback-branch and unknown-branch configuration in a dedicated section with the same property like the normal branch configuration. This makes it quite clear what are branch configuration and what are overall configurations. At this moment there are also overlapping configurations (used for fallback and overall e.g. Increment or VersioningMode settings) which is error prone. If this is not complex enough the overall settings are leaking in the effected branch configuration as well.

Another problem I see is that you want to override an existing template (at this moment the default is the gitflow workflow template right?) or even want to define your workflow from scratch. How would you do this? If I'm right @asbjornu has already expressed an idea for templating.

@asbjornu
Copy link
Member

asbjornu commented Oct 3, 2022

@HHobeck, I'm not sure I understand what you mean with "templating". Can you please elaborate?

@HHobeck
Copy link
Contributor

HHobeck commented Oct 3, 2022

Of course. Actually it was in this discussion.

The point here is we have one pre-defined workflow as a default template with the name gitflow workflow. But if we want to support more workflows then we need to introduce a templating mechanism like maybe in kubernetes. I thought this is what you meant.

Example 1: from GitFlow workflow

workflow: GitFlow/v1
assembly-versioning-scheme: MajorMinorPatchTag
assembly-file-versioning-scheme: MajorMinorPatchTag
assembly-informational-format: '{MajorMinorPatch}+{Sha}'
mode: ContinuousDeployment
branches: {
    "release": {
      "tracks-release-branches": true
    }
}

Example 2: from GitHub

workflow: GitHub/v1
assembly-versioning-scheme: MajorMinorPatchTag
assembly-file-versioning-scheme: MajorMinorPatchTag
assembly-informational-format: '{MajorMinorPatch}+{Sha}'
mode: ContinuousDeployment
branches: {
    "main": {
      "tracks-release-branches": true
    }
}

Example 3: from scratch

workflow: null
...

@asbjornu
Copy link
Member

asbjornu commented Oct 3, 2022

Ah, I see. I think that's sort of the idea I have for how mode should work. mode selects the Strategy, which populates a default configuration (template) that can be overridden by GitVersion.yml. It feels like mode and workflow would be competing with each other if we introduced the workflow property.

@HHobeck
Copy link
Contributor

HHobeck commented Oct 4, 2022

So that means you would like to change the structure of VersioningMode. Which values you have in mind?

public enum VersioningMode
{
    ContinuousDelivery,
    ContinuousDeployment,
    Mainline
}

@HHobeck
Copy link
Contributor

HHobeck commented Oct 5, 2022

I have taken a look into the usage of the VersioningMode and I totally agree with you that we need to change the current usage of it. But I'm not sure if it is a good idea to use this property for templating because we need to refactoring a lot of code before we are able to even start the actual implementation of this feature.

If you ask me we should introduce a new field like base-template or whatever name you like and implementing this new templating mechanism on top of it. Parallel to this we are going to refactor the usage of versioning-mode and define it as deprecated. We can remove the logic step by step and delete this property when it is not used anymore. ;)

@HHobeck
Copy link
Contributor

HHobeck commented Oct 5, 2022

Concrete I would propose following refactoring steps:

  1. Separate/document the properties which are related to the overall and branch configuration (conceptional).
  2. Create a new section fallback and unknown branch configuration (both properties are of type BranchConfig).
  3. Move the default branch configuration from the root layer to the fallback-branch-configuration section.
  4. Rename Config to Configuration and BranchConfig to BranchConfiguration.
  5. Introduce a new field for templating
  6. Define the templates for GitHub and GitFlow
  7. Write logic to use the pre-defined templates when the given base-template is defined

I know the fallback and unknown branch configuration is not necessary for the templating feature. But we need to do this as well in v6.

@HHobeck
Copy link
Contributor

HHobeck commented Oct 10, 2022

I have taken a look into the usage of the VersioningMode and I totally agree with you that we need to change the current usage of it. But I'm not sure if it is a good idea to use this property for templating because we need to refactoring a lot of code before we are able to even start the actual implementation of this feature.

If you ask me we should introduce a new field like base-template or whatever name you like and implementing this new templating mechanism on top of it. Parallel to this we are going to refactor the usage of versioning-mode and define it as deprecated. We can remove the logic step by step and delete this property when it is not used anymore. ;)

Actually I think we need the VersioningMode to control the behavior of how the BaseVersionSource should be determined on the branch layer and how the semantic version should be calculated. This is essential if you take the following examples:

    [Test]
    public void __Just_A_Test_A__()
    {
        var mainlineConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.Mainline).Build();

        var continuousDeploymentConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.ContinuousDeployment).Build();

        var continuousDeliveryConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.ContinuousDelivery).Build();

        using var fixture = new EmptyRepositoryFixture("main");

        fixture.MakeACommit("one");
        fixture.BranchTo("release/1.0.0");
        fixture.MakeACommit("two");
        fixture.MakeACommit("three");
        fixture.ApplyTag("1.0.0-beta.1");

        // {major}.{minor}.{patch}-{PreReleaseLabel}
        fixture.AssertFullSemver("1.0.0-beta", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.0-beta.1", continuousDeploymentConfiguration);
        // {major}.{minor}.{patch}-{PreReleaseLabel}.{PreReleaseNumber}
        fixture.AssertFullSemver("1.0.0-beta.1", continuousDeliveryConfiguration);

        fixture.BranchTo("feature/just-a-test"); // Inheriting VersioningMode from release branch

        // {major}.{minor}.{patch}-{PreReleaseLabel}
        fixture.AssertFullSemver("1.0.0-beta", mainlineConfiguration);
        // {major}.{minor}.{patch}-{PreReleaseLabel}.{PreReleaseNumber}
        fixture.AssertFullSemver("1.0.0-beta.1", continuousDeploymentConfiguration);
        fixture.AssertFullSemver("1.0.0-beta.1", continuousDeliveryConfiguration);
    }

and

    [Test]
    public void __Just_A_Test_B__()
    {
        var mainlineConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.Mainline).Build();

        var continuousDeploymentConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.ContinuousDeployment).Build();

        var continuousDeliveryConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithoutTag("feature")
            .WithVersioningMode("release", VersioningMode.ContinuousDelivery).Build();

        using var fixture = new EmptyRepositoryFixture("main");

        fixture.MakeACommit("one");
        fixture.BranchTo("release/1.0.0");
        fixture.MakeACommit("two");
        fixture.MakeACommit("three");
        fixture.ApplyTag("1.0.0-beta.1");
        fixture.MakeACommit("four");

        // {major}.{minor}.{patch}-{PreReleaseLabel}.{CommitsSinceVersionSource}
        fixture.AssertFullSemver("1.0.0-beta", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.0-beta.3", continuousDeploymentConfiguration);
        // {major}.{minor}.{patch}-{PreReleaseLabel}.{PreReleaseNumber}+{CommitsSinceVersionSource}
        fixture.AssertFullSemver("1.0.0-beta.2+3", continuousDeliveryConfiguration);

        fixture.BranchTo("feature/just-a-test"); // Inheriting VersioningMode from release branch

        // {major}.{minor}.{patch}-{PreReleaseLabel}.{CommitsSinceVersionSource}
        fixture.AssertFullSemver("1.0.0-beta", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.0-beta.3", continuousDeploymentConfiguration);
        // {major}.{minor}.{patch}-{PreReleaseLabel}.{PreReleaseNumber}+{CommitsSinceVersionSource}
        fixture.AssertFullSemver("1.0.0-beta.2+3", continuousDeliveryConfiguration);
    }

@HHobeck
Copy link
Contributor

HHobeck commented Oct 10, 2022

    [Test]
    public void __Just_A_Test_C__()
    {
        var mainlineConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithTag("main", "ci")
            .WithVersioningMode("release", VersioningMode.Mainline)
            .WithVersioningMode("main", VersioningMode.Mainline).Build();

        var continuousDeploymentConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithTag("main", "ci")
            .WithVersioningMode("release", VersioningMode.ContinuousDeployment)
            .WithVersioningMode("main", VersioningMode.ContinuousDeployment).Build();

        var continuousDeliveryConfiguration = TestConfigurationBuilder.New
            .WithoutVersioningMode().WithTag("release", "beta").WithTag("main", "ci")
            .WithVersioningMode("release", VersioningMode.ContinuousDelivery)
            .WithVersioningMode("main", VersioningMode.ContinuousDelivery).Build();

        using var fixture = new EmptyRepositoryFixture("main");

        fixture.MakeACommit("one");
        fixture.BranchTo("release/1.0.0");
        fixture.MakeACommit("two");
        fixture.MakeACommit("three");

        fixture.Checkout("main");
        fixture.MergeNoFF("release/1.0.0");

        fixture.AssertFullSemver("1.0.0-ci", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.0-ci.4", continuousDeploymentConfiguration);
        fixture.AssertFullSemver("1.0.0-ci.1+4", continuousDeliveryConfiguration);

        fixture.Repository.Branches.Remove("release/1.0.0");

        fixture.AssertFullSemver("1.0.0-ci", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.0-ci.4", continuousDeploymentConfiguration);
        fixture.AssertFullSemver("1.0.0-ci.1+4", continuousDeliveryConfiguration);

        fixture.MakeACommit("four");

        fixture.AssertFullSemver("1.0.1-ci", mainlineConfiguration);
        fixture.AssertFullSemver("1.0.1-ci.1", continuousDeploymentConfiguration); // <<---- this is important
        fixture.AssertFullSemver("1.0.0-ci.1+5", continuousDeliveryConfiguration); // <<---- this is important
    }

@HHobeck
Copy link
Contributor

HHobeck commented Oct 10, 2022

The business rules are the following to increment the next version number (ShouldIncrement is true) in MergeMessageVersionStrategy:

  • the PreventIncrementOfMergedBranchVersion of the effective branch configuration is false or
  • CurrentCommit is not equals to MergeCommit and VersioningMode of the effective branch configuration is not equals to ContinuousDelivery

@HHobeck
Copy link
Contributor

HHobeck commented Oct 26, 2022

I realized that the author of this ticket want a functionality to just define one configuration for all branches for convenience purpose. Keep in mind we have a branch specific, a fallback and a unknown branch section. Makes it sense to introduce a overwrite all section?

The fallback section only applies when e.g. the value on the branch specific section is null.

@HHobeck
Copy link
Contributor

HHobeck commented Feb 28, 2023

I realized that the author of this ticket want a functionality to just define one configuration for all branches for convenience purpose. Keep in mind we have a branch specific, a fallback and a unknown branch section. Makes it sense to introduce a overwrite all section?

The fallback section only applies when e.g. the value on the branch specific section is null.

Hi there. I would like to highlight the problem I see here. This feature makes no sense in my opinion. I would suggest to close it.

@arturcic
Copy link
Member

Closing this one as suggested. If there are additional details the author can add, he is welcome

@arturcic arturcic removed this from the 6.x milestone Feb 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants