Skip to content

Commit cfbb295

Browse files
committed
Add --versionIncrement option to prepare-release command that overrides the increment setting from version.json
1 parent d69d232 commit cfbb295

File tree

4 files changed

+91
-44
lines changed

4 files changed

+91
-44
lines changed

doc/nbgv-cli.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,28 @@ nbgv prepare-release rc
7777
no new branch will be created. Instead the tool will just update the version
7878
in the current branch by replacing or removing the prerelease tag.
7979

80-
### Explicitly setting the next version
80+
### Customizing the next version
8181

82-
If you want to explicitly set the next version of the main branch instead of
83-
automatically determining it by incrementing the current version, you
84-
can set the version as commandline parameter:
82+
By default, the next version of the main branch is determined from the current
83+
version and the `versionIncrement` setting in `version.json`.
84+
To customize this behaviour, you can either explicitly set the next version
85+
or override the version increment setting.
86+
87+
To explicitly set the next version, run
8588

8689
```ps1
8790
nbgv prepare-release --nextVersion 2.0-beta
8891
```
8992

93+
To override the `versionIncrement` setting from `version.json`, run
94+
95+
```ps1
96+
nbgv prepare-release --versionIncrement Major
97+
```
98+
99+
**Note:** The parameters `nextVersion` and `versionIncrement` cannot
100+
be combined.
101+
90102
### Customizing the behaviour of `prepare-release`
91103

92104
The behaviour of the `prepare-release` command can be customized in

src/NerdBank.GitVersioning.Tests/ReleaseManagerTests.cs

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -200,42 +200,45 @@ public void PrepeareRelease_ReleaseBranchWithVersionDecrement(string initialVers
200200

201201
[Theory]
202202
// base test cases
203-
[InlineData("1.2-beta", null, null, null, null, null, "v1.2", "1.2", "1.3-alpha")]
204-
[InlineData("1.2-beta", null, null, null, "rc", null, "v1.2", "1.2-rc", "1.3-alpha")]
205-
[InlineData("1.2-beta.{height}", null, null, null, null, null, "v1.2", "1.2", "1.3-alpha.{height}")]
206-
[InlineData("1.2-beta.{height}", null, null, null, "rc", null, "v1.2", "1.2-rc.{height}", "1.3-alpha.{height}")]
203+
[InlineData("1.2-beta", null, null, null, null, null, null, "v1.2", "1.2", "1.3-alpha")]
204+
[InlineData("1.2-beta", null, null, null, "rc", null, null, "v1.2", "1.2-rc", "1.3-alpha")]
205+
[InlineData("1.2-beta.{height}", null, null, null, null, null, null, "v1.2", "1.2", "1.3-alpha.{height}")]
206+
[InlineData("1.2-beta.{height}", null, null, null, "rc", null, null, "v1.2", "1.2-rc.{height}", "1.3-alpha.{height}")]
207207
// modify release.branchName
208-
[InlineData("1.2-beta", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", null, null, "v1.2release", "1.2", "1.3-alpha")]
209-
[InlineData("1.2-beta", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", "rc", null, "v1.2release", "1.2-rc", "1.3-alpha")]
210-
[InlineData("1.2-beta.{height}", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", null, null, "v1.2release", "1.2", "1.3-alpha.{height}")]
211-
[InlineData("1.2-beta.{height}", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", "rc", null, "v1.2release", "1.2-rc.{height}", "1.3-alpha.{height}")]
208+
[InlineData("1.2-beta", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", null, null, null, "v1.2release", "1.2", "1.3-alpha")]
209+
[InlineData("1.2-beta", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", "rc", null, null, "v1.2release", "1.2-rc", "1.3-alpha")]
210+
[InlineData("1.2-beta.{height}", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", null, null, null, "v1.2release", "1.2", "1.3-alpha.{height}")]
211+
[InlineData("1.2-beta.{height}", "v{version}release", ReleaseVersionIncrement.Minor, "alpha", "rc", null, null, "v1.2release", "1.2-rc.{height}", "1.3-alpha.{height}")]
212212
// modify release.versionIncrement: "Major"
213-
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Major, "alpha", null, null, "v1.2", "1.2", "2.0-alpha")]
214-
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Major, "alpha", "rc", null, "v1.2", "1.2-rc", "2.0-alpha")]
215-
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Major, "alpha", null, null, "v1.2", "1.2", "2.0-alpha.{height}")]
216-
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Major, "alpha", "rc", null, "v1.2", "1.2-rc.{height}", "2.0-alpha.{height}")]
213+
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Major, "alpha", null, null, null, "v1.2", "1.2", "2.0-alpha")]
214+
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Major, "alpha", "rc", null, null, "v1.2", "1.2-rc", "2.0-alpha")]
215+
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Major, "alpha", null, null, null, "v1.2", "1.2", "2.0-alpha.{height}")]
216+
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Major, "alpha", "rc", null, null, "v1.2", "1.2-rc.{height}", "2.0-alpha.{height}")]
217217
// modify release.versionIncrement: "Build"
218-
[InlineData("1.2.3-beta", null, ReleaseVersionIncrement.Build, "alpha", null, null, "v1.2.3", "1.2.3", "1.2.4-alpha")]
219-
[InlineData("1.2.3-beta", null, ReleaseVersionIncrement.Build, "alpha", "rc", null, "v1.2.3", "1.2.3-rc", "1.2.4-alpha")]
220-
[InlineData("1.2.3-beta.{height}", null, ReleaseVersionIncrement.Build, "alpha", null, null, "v1.2.3", "1.2.3", "1.2.4-alpha.{height}")]
221-
[InlineData("1.2.3-beta.{height}", null, ReleaseVersionIncrement.Build, "alpha", "rc", null, "v1.2.3", "1.2.3-rc.{height}", "1.2.4-alpha.{height}")]
218+
[InlineData("1.2.3-beta", null, ReleaseVersionIncrement.Build, "alpha", null, null, null, "v1.2.3", "1.2.3", "1.2.4-alpha")]
219+
[InlineData("1.2.3-beta", null, ReleaseVersionIncrement.Build, "alpha", "rc", null, null, "v1.2.3", "1.2.3-rc", "1.2.4-alpha")]
220+
[InlineData("1.2.3-beta.{height}", null, ReleaseVersionIncrement.Build, "alpha", null, null, null, "v1.2.3", "1.2.3", "1.2.4-alpha.{height}")]
221+
[InlineData("1.2.3-beta.{height}", null, ReleaseVersionIncrement.Build, "alpha", "rc", null, null, "v1.2.3", "1.2.3-rc.{height}", "1.2.4-alpha.{height}")]
222222
// modify release.firstUnstableTag
223-
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Minor, "preview", null, null, "v1.2", "1.2", "1.3-preview")]
224-
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Minor, "preview", "rc", null, "v1.2", "1.2-rc", "1.3-preview")]
225-
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Minor, "preview", null, null, "v1.2", "1.2", "1.3-preview.{height}")]
226-
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Minor, "preview", "rc", null, "v1.2", "1.2-rc.{height}", "1.3-preview.{height}")]
223+
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Minor, "preview", null, null, null, "v1.2", "1.2", "1.3-preview")]
224+
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Minor, "preview", "rc", null, null, "v1.2", "1.2-rc", "1.3-preview")]
225+
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Minor, "preview", null, null, null, "v1.2", "1.2", "1.3-preview.{height}")]
226+
[InlineData("1.2-beta.{height}", null, ReleaseVersionIncrement.Minor, "preview", "rc", null, null, "v1.2", "1.2-rc.{height}", "1.3-preview.{height}")]
227227
// include build metadata in version
228-
[InlineData("1.2-beta+metadata", null, ReleaseVersionIncrement.Minor, "alpha", null, null, "v1.2", "1.2+metadata", "1.3-alpha+metadata")]
229-
[InlineData("1.2-beta+metadata", null, ReleaseVersionIncrement.Minor, "alpha", "rc", null, "v1.2", "1.2-rc+metadata", "1.3-alpha+metadata")]
230-
[InlineData("1.2-beta.{height}+metadata", null, ReleaseVersionIncrement.Minor, "alpha", null, null, "v1.2", "1.2+metadata", "1.3-alpha.{height}+metadata")]
231-
[InlineData("1.2-beta.{height}+metadata", null, ReleaseVersionIncrement.Minor, "alpha", "rc", null, "v1.2", "1.2-rc.{height}+metadata", "1.3-alpha.{height}+metadata")]
228+
[InlineData("1.2-beta+metadata", null, ReleaseVersionIncrement.Minor, "alpha", null, null, null, "v1.2", "1.2+metadata", "1.3-alpha+metadata")]
229+
[InlineData("1.2-beta+metadata", null, ReleaseVersionIncrement.Minor, "alpha", "rc", null, null, "v1.2", "1.2-rc+metadata", "1.3-alpha+metadata")]
230+
[InlineData("1.2-beta.{height}+metadata", null, ReleaseVersionIncrement.Minor, "alpha", null, null, null, "v1.2", "1.2+metadata", "1.3-alpha.{height}+metadata")]
231+
[InlineData("1.2-beta.{height}+metadata", null, ReleaseVersionIncrement.Minor, "alpha", "rc", null, null, "v1.2", "1.2-rc.{height}+metadata", "1.3-alpha.{height}+metadata")]
232232
// versions without prerelease tags
233-
[InlineData("1.2", null, ReleaseVersionIncrement.Minor, "alpha", null, null, "v1.2", "1.2", "1.3-alpha")]
234-
[InlineData("1.2", null, ReleaseVersionIncrement.Major, "alpha", null, null, "v1.2", "1.2", "2.0-alpha")]
233+
[InlineData("1.2", null, ReleaseVersionIncrement.Minor, "alpha", null, null, null, "v1.2", "1.2", "1.3-alpha")]
234+
[InlineData("1.2", null, ReleaseVersionIncrement.Major, "alpha", null, null, null, "v1.2", "1.2", "2.0-alpha")]
235235
// explicitly set next version (firstUnstableTag setting will be ignored)
236-
[InlineData("1.2-beta", null, null, null, null, "4.5", "v1.2", "1.2", "4.5")]
237-
[InlineData("1.2-beta", null, null, null, null, "4.5-pre", "v1.2", "1.2", "4.5-pre")]
238-
[InlineData("1.2-beta.{height}", null, null, null, null, "4.5-pre.{height}", "v1.2", "1.2", "4.5-pre.{height}")]
236+
[InlineData("1.2-beta", null, null, null, null, "4.5", null, "v1.2", "1.2", "4.5")]
237+
[InlineData("1.2-beta", null, null, null, null, "4.5-pre", null, "v1.2", "1.2", "4.5-pre")]
238+
[InlineData("1.2-beta.{height}", null, null, null, null, "4.5-pre.{height}", null, "v1.2", "1.2", "4.5-pre.{height}")]
239+
// explicitly set version increment overriding the setting from version.json
240+
[InlineData("1.2-beta", null, ReleaseVersionIncrement.Minor, null, null, null, ReleaseVersionIncrement.Major, "v1.2", "1.2", "2.0-alpha")]
241+
[InlineData("1.2.3-beta", null, ReleaseVersionIncrement.Minor, null, null, null, ReleaseVersionIncrement.Build, "v1.2.3", "1.2.3", "1.2.4-alpha")]
239242
public void PrepareRelease_Master(
240243
// data for initial setup (version and release options configured in version.json)
241244
string initialVersion,
@@ -245,6 +248,7 @@ public void PrepareRelease_Master(
245248
// arguments passed to PrepareRelease()
246249
string releaseUnstableTag,
247250
string nextVersion,
251+
ReleaseVersionIncrement? parameterVersionIncrement,
248252
// expected versions and branch name after running PrepareRelease()
249253
string expectedBranchName,
250254
string resultingReleaseVersion,
@@ -295,7 +299,7 @@ public void PrepareRelease_Master(
295299

296300
// prepare release
297301
var releaseManager = new ReleaseManager();
298-
releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag, (nextVersion == null ? null : SemanticVersion.Parse(nextVersion)));
302+
releaseManager.PrepareRelease(this.RepoPath, releaseUnstableTag, (nextVersion == null ? null : SemanticVersion.Parse(nextVersion)), parameterVersionIncrement);
299303

300304
// check if a branch was created
301305
Assert.Contains(this.Repo.Branches, branch => branch.FriendlyName == expectedBranchName);

src/NerdBank.GitVersioning/ReleaseManager.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using LibGit2Sharp;
88
using Validation;
9+
using static Nerdbank.GitVersioning.VersionOptions;
910

1011
/// <summary>
1112
/// Methods for creating releases
@@ -110,9 +111,14 @@ public ReleaseManager(TextWriter outputWriter = null, TextWriter errorWriter = n
110111
/// version based on the current version and the <c>versionIncrement</c> setting in <c>version.json</c>.
111112
/// Parameter will be ignored if the current branch is a release branch.
112113
/// </param>
113-
public void PrepareRelease(string projectDirectory, string releaseUnstableTag = null, SemanticVersion nextVersion = null)
114+
/// <param name="versionIncrement">
115+
/// The increment to apply in order to determine the next version on the current branch.
116+
/// If specified, value will be used instead of the increment specified in <c>version.json</c>.
117+
/// Parameter will be ignored if the current branch is a release branch.
118+
/// </param>
119+
public void PrepareRelease(string projectDirectory, string releaseUnstableTag = null, SemanticVersion nextVersion = null, ReleaseVersionIncrement? versionIncrement = null)
114120
{
115-
Requires.NotNull(projectDirectory, nameof(projectDirectory));
121+
Requires.NotNull(projectDirectory, nameof(projectDirectory));
116122

117123
// open the git repository
118124
var repository = this.GetRepository(projectDirectory);
@@ -136,7 +142,7 @@ public void PrepareRelease(string projectDirectory, string releaseUnstableTag =
136142
var releaseVersion = string.IsNullOrEmpty(releaseUnstableTag)
137143
? versionOptions.Version.WithoutPrepreleaseTags()
138144
: versionOptions.Version.SetFirstPrereleaseTag(releaseUnstableTag);
139-
var nextDevVersion = this.GetNextDevVersion(versionOptions, nextVersion);
145+
var nextDevVersion = this.GetNextDevVersion(versionOptions, nextVersion, versionIncrement);
140146

141147
// check if the current branch is the release branch
142148
if (string.Equals(originalBranchName, releaseBranchName, StringComparison.OrdinalIgnoreCase))
@@ -273,17 +279,19 @@ private static bool IsVersionDecrement(SemanticVersion oldVersion, SemanticVersi
273279
}
274280
}
275281

276-
private SemanticVersion GetNextDevVersion(VersionOptions versionOptions, SemanticVersion nextVersion)
282+
private SemanticVersion GetNextDevVersion(VersionOptions versionOptions, SemanticVersion nextVersion, ReleaseVersionIncrement? versionIncrementOverride)
277283
{
278284
if (nextVersion != null)
279285
return nextVersion;
280286

281-
var releaseOptions = versionOptions.ReleaseOrDefault;
287+
// determine the increment to use.
288+
// Use parameter if it has a value, otherwise use setting from version.json
289+
var versionIncrement = versionIncrementOverride ?? versionOptions.ReleaseOrDefault.VersionIncrementOrDefault;
282290

283291
// the increment is only valid if the current version has the required precision
284292
// increment settings "Major" and "Minor" are always valid
285293
// increment setting "Build" is only valid if the version has at lease three segments
286-
var isValidIncrement = releaseOptions.VersionIncrementOrDefault != VersionOptions.ReleaseVersionIncrement.Build ||
294+
var isValidIncrement = versionIncrement != ReleaseVersionIncrement.Build ||
287295
versionOptions.Version.Version.Build >= 0;
288296

289297
// increment is ignored when the next version was specified explicitly
@@ -294,8 +302,8 @@ private SemanticVersion GetNextDevVersion(VersionOptions versionOptions, Semanti
294302
}
295303

296304
return versionOptions.Version
297-
.Increment(releaseOptions.VersionIncrementOrDefault)
298-
.SetFirstPrereleaseTag(releaseOptions.FirstUnstableTagOrDefault);
305+
.Increment(versionIncrement)
306+
.SetFirstPrereleaseTag(versionOptions.ReleaseOrDefault.FirstUnstableTagOrDefault);
299307
}
300308
}
301309
}

src/nbgv/Program.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ private enum ExitCodes
4646
UserNotConfigured,
4747
DetachedHead,
4848
InvalidVersionIncrementSetting,
49+
InvalidParameters,
50+
InvalidVersionIncrement,
4951
}
5052

5153
private static ExitCodes exitCode;
@@ -65,6 +67,7 @@ public static int Main(string[] args)
6567
bool cloudBuildAllVars = false;
6668
string releasePreReleaseTag = null;
6769
string releaseNextVersion = null;
70+
string releaseVersionIncrement = null;
6871

6972
ArgumentCommand<string> install = null;
7073
ArgumentCommand<string> getVersion = null;
@@ -110,6 +113,7 @@ public static int Main(string[] args)
110113
prepareRelease = syntax.DefineCommand("prepare-release", ref commandText, "Prepares a release by creating a release branch for the current version and adjusting the version on the current branch.");
111114
syntax.DefineOption("p|project", ref projectPath, "The path to the project or project directory. The default is the current directory.");
112115
syntax.DefineOption("nextVersion", ref releaseNextVersion, "The version to set for the current branch. If omitted, the next version is determined automatically by incrementing the current version.");
116+
syntax.DefineOption("versionIncrement", ref releaseVersionIncrement, "Specifies how the next version for the current branch is determined overriding the 'versionIncrement' setting in version.json");
113117
syntax.DefineParameter("tag", ref releasePreReleaseTag, "The prerelease tag to apply on the release branch (if any). If not specified, any existing prerelease tag will be removed. The preceding hyphen may be omitted.");
114118

115119
if (syntax.ActiveCommand == null)
@@ -144,7 +148,7 @@ public static int Main(string[] args)
144148
}
145149
else if (prepareRelease.IsActive)
146150
{
147-
exitCode = OnPrepareReleaseCommand(projectPath, releasePreReleaseTag, releaseNextVersion);
151+
exitCode = OnPrepareReleaseCommand(projectPath, releasePreReleaseTag, releaseNextVersion, releaseVersionIncrement);
148152
}
149153

150154
return (int)exitCode;
@@ -558,7 +562,7 @@ private static ExitCodes OnCloudCommand(string projectPath, string version, stri
558562
}
559563
}
560564

561-
private static ExitCodes OnPrepareReleaseCommand(string projectPath, string prereleaseTag, string nextVersion)
565+
private static ExitCodes OnPrepareReleaseCommand(string projectPath, string prereleaseTag, string nextVersion, string versionIncrement)
562566
{
563567
// validate project path property
564568
string searchPath = GetSpecifiedOrCurrentDirectoryPath(projectPath);
@@ -568,6 +572,25 @@ private static ExitCodes OnPrepareReleaseCommand(string projectPath, string prer
568572
return ExitCodes.NoGitRepo;
569573
}
570574

575+
// nextVersion and versionIncrement parameters cannot be combined
576+
if(!string.IsNullOrEmpty(nextVersion) && !string.IsNullOrEmpty(versionIncrement))
577+
{
578+
Console.Error.WriteLine("Options 'nextVersion' and 'versionIncrement' cannot be used at the same time.");
579+
return ExitCodes.InvalidParameters;
580+
}
581+
582+
// parse versionIncrement is parameter was specified
583+
VersionOptions.ReleaseVersionIncrement? versionIncrementParsed = default;
584+
if (!string.IsNullOrEmpty(versionIncrement))
585+
{
586+
if(!Enum.TryParse< VersionOptions.ReleaseVersionIncrement>(versionIncrement, true, out var parsed))
587+
{
588+
Console.Error.WriteLine($"\"{versionIncrement}\" is not a valid version increment");
589+
return ExitCodes.InvalidVersionIncrement;
590+
}
591+
versionIncrementParsed = parsed;
592+
}
593+
571594
// parse nextVersion if parameter was specified
572595
SemanticVersion nextVersionParsed = default;
573596
if (!string.IsNullOrEmpty(nextVersion))

0 commit comments

Comments
 (0)