Skip to content

Commit

Permalink
Merge pull request #875 from ronaldbarendse/feature/tagname
Browse files Browse the repository at this point in the history
Add `tagName` option to customize generated tag name
  • Loading branch information
AArnott authored Jan 28, 2023
2 parents 175cea8 + edb2d5f commit 7d22ed6
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 13 deletions.
38 changes: 38 additions & 0 deletions doc/nbgv-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,44 @@ For each branch, the following properties are provided:
**Note:** When the current branch is already the release branch for the current version, no new branch will be created.
In that case, the `NewBranch` property will be `null`.

## Creating a version tag

The `tag` command automates the task of tagging a commit with a version.

To create a version tag, run:

```ps1
nbgv tag
```

This will:

1. Read version.json to ascertain the version under development, and the naming convention of tag names.
1. Create a new tag for that version.

You can optionally include a version or commit id to create a new tag for an older version/commit, e.g.:

```ps1
nbgv tag 1.0.0
```

### Customizing the behaviour of `tag`

The behaviour of the `tag` command can be customized in `version.json`:

```json
{
"version": "1.0",
"release": {
"tagName" : "v{version}"
}
}
```

| Property | Default value | Description |
|----------|---------------|-------------------------------------------------------------------------------------------------|
| tagName | `v{version}` | Defines the format of tag names. Format must include a placeholder '{version}' for the version. |

## Learn more

There are several more sub-commands and switches to each to help you build and maintain your projects, find a commit that built a particular version later on, create tags, etc.
Expand Down
1 change: 1 addition & 0 deletions doc/versionJson.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ The content of the version.json file is a JSON serialized object with these prop
}
},
"release" : {
"tagName" : "v{version}",
"branchName" : "v{version}",
"versionIncrement" : "minor",
"firstUnstableTag" : "alpha"
Expand Down
31 changes: 27 additions & 4 deletions src/NerdBank.GitVersioning/VersionOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ public int GetHashCode(CloudBuildNumberCommitIdOptions? obj)
}

/// <summary>
/// Encapsulates settings for the "prepare-release" command.
/// Encapsulates settings for the "prepare-release" and "tag" commands.
/// </summary>
public class ReleaseOptions : IEquatable<ReleaseOptions>
{
Expand All @@ -1452,6 +1452,7 @@ public class ReleaseOptions : IEquatable<ReleaseOptions>
internal static readonly ReleaseOptions DefaultInstance = new ReleaseOptions()
{
isFrozen = true,
tagName = "v{version}",
branchName = "v{version}",
versionIncrement = ReleaseVersionIncrement.Minor,
firstUnstableTag = "alpha",
Expand All @@ -1460,6 +1461,9 @@ public class ReleaseOptions : IEquatable<ReleaseOptions>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool isFrozen;

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string? tagName;

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string? branchName;

Expand All @@ -1482,11 +1486,28 @@ public ReleaseOptions()
/// <param name="copyFrom">The existing instance to copy from.</param>
public ReleaseOptions(ReleaseOptions copyFrom)
{
this.tagName = copyFrom.tagName;
this.branchName = copyFrom.branchName;
this.versionIncrement = copyFrom.versionIncrement;
this.firstUnstableTag = copyFrom.firstUnstableTag;
}

/// <summary>
/// Gets or sets the tag name template for tagging.
/// </summary>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? TagName
{
get => this.tagName;
set => this.SetIfNotReadOnly(ref this.tagName, value);
}

/// <summary>
/// Gets the tag name template for tagging.
/// </summary>
[JsonIgnore]
public string TagNameOrDefault => this.TagName ?? DefaultInstance.TagName!;

/// <summary>
/// Gets or sets the branch name template for release branches.
/// </summary>
Expand All @@ -1498,7 +1519,7 @@ public string? BranchName
}

/// <summary>
/// Gets the set branch name template for release branches.
/// Gets the branch name template for release branches.
/// </summary>
[JsonIgnore]
public string BranchNameOrDefault => this.BranchName ?? DefaultInstance.BranchName!;
Expand Down Expand Up @@ -1593,7 +1614,8 @@ public bool Equals(ReleaseOptions? x, ReleaseOptions? y)
return false;
}

return StringComparer.Ordinal.Equals(x.BranchNameOrDefault, y.BranchNameOrDefault) &&
return StringComparer.Ordinal.Equals(x.TagNameOrDefault, y.TagNameOrDefault) &&
StringComparer.Ordinal.Equals(x.BranchNameOrDefault, y.BranchNameOrDefault) &&
x.VersionIncrementOrDefault == y.VersionIncrementOrDefault &&
StringComparer.Ordinal.Equals(x.FirstUnstableTagOrDefault, y.FirstUnstableTagOrDefault);
}
Expand All @@ -1608,7 +1630,8 @@ public int GetHashCode(ReleaseOptions? obj)

unchecked
{
int hash = StringComparer.Ordinal.GetHashCode(obj.BranchNameOrDefault) * 397;
int hash = StringComparer.Ordinal.GetHashCode(obj.TagNameOrDefault) * 397;
hash ^= StringComparer.Ordinal.GetHashCode(obj.BranchNameOrDefault);
hash ^= (int)obj.VersionIncrementOrDefault;
hash ^= StringComparer.Ordinal.GetHashCode(obj.FirstUnstableTagOrDefault);
return hash;
Expand Down
5 changes: 5 additions & 0 deletions src/NerdBank.GitVersioning/VersionOptionsContractResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
property.ShouldSerialize = instance => !((VersionOptions)instance).ReleaseOrDefault.IsDefault;
}

if (property.DeclaringType == typeof(VersionOptions.ReleaseOptions) && member.Name == nameof(VersionOptions.ReleaseOptions.TagName))
{
property.ShouldSerialize = instance => ((VersionOptions.ReleaseOptions)instance).TagNameOrDefault != VersionOptions.ReleaseOptions.DefaultInstance.TagName;
}

if (property.DeclaringType == typeof(VersionOptions.ReleaseOptions) && member.Name == nameof(VersionOptions.ReleaseOptions.BranchName))
{
property.ShouldSerialize = instance => ((VersionOptions.ReleaseOptions)instance).BranchNameOrDefault != VersionOptions.ReleaseOptions.DefaultInstance.BranchName;
Expand Down
20 changes: 13 additions & 7 deletions src/NerdBank.GitVersioning/version.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
},
"publicReleaseRefSpec": {
"type": "array",
"description": "An array of regular expressions that may match a ref (branch or tag) that should be built with PublicRelease=true as the default value. The ref matched against is in its canonical form (e.g. refs/heads/master)",
"description": "An array of regular expressions that may match a ref (branch or tag) that should be built with PublicRelease=true as the default value. The ref matched against is in its canonical form (e.g. refs/heads/master).",
"items": {
"type": "string",
"format": "regex"
Expand All @@ -128,12 +128,12 @@
},
"cloudBuild": {
"type": "object",
"description": "Options that are applicable specifically to cloud builds (e.g. VSTS, AppVeyor, TeamCity)",
"description": "Options that are applicable specifically to cloud builds (e.g. VSTS, AppVeyor, TeamCity).",
"properties": {
"setAllVariables": {
"type": "boolean",
"default": false,
"description": "Elevates all build properties to cloud build variables prefaced with \"NBGV_\""
"description": "Elevates all build properties to cloud build variables prefaced with \"NBGV_\"."
},
"setVersionVariables": {
"type": "boolean",
Expand Down Expand Up @@ -172,13 +172,19 @@
}
},
"release": {
"description": "Settings for the prepare-release command",
"description": "Settings for the prepare-release and tag commands.",
"type": "object",
"properties": {
"tagName": {
"description": "Defines the format of tag names. Format must include a placeholder '{version}' for the version.",
"type": "string",
"pattern": "\\{version\\}",
"default": "v{version}"
},
"branchName": {
"description": "Defines the format of release branch names. Format must include a placeholder '{version}' for the version",
"description": "Defines the format of release branch names. Format must include a placeholder '{version}' for the version.",
"type": "string",
"pattern": ".*\\{version\\}.*",
"pattern": "\\{version\\}",
"default": "v{version}"
},
"versionIncrement": {
Expand All @@ -188,7 +194,7 @@
"default": "minor"
},
"firstUnstableTag": {
"description": "Specifies the first/default prerelease tag for new versions",
"description": "Specifies the first/default prerelease tag for new versions.",
"type": "string",
"default": "alpha"
}
Expand Down
27 changes: 25 additions & 2 deletions src/nbgv/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private enum ExitCodes
PackageIdNotFound,
ShallowClone,
InternalError,
InvalidTagNameSetting,
}

private static bool AlwaysUseLibGit2 => string.Equals(Environment.GetEnvironmentVariable("NBGV_GitEngine"), "LibGit2", StringComparison.Ordinal);
Expand Down Expand Up @@ -545,6 +546,24 @@ private static Task<int> OnTagCommand(string project, string versionOrRef)
return Task.FromResult((int)ExitCodes.NoGitRepo);
}

// get tag name format
VersionOptions versionOptions = context.VersionFile.GetVersion();
if (versionOptions is null)
{
Console.Error.WriteLine($"Failed to load version file for directory '{searchPath}'.");
return Task.FromResult((int)ExitCodes.NoVersionJsonFound);
}

string tagNameFormat = versionOptions.ReleaseOrDefault.TagNameOrDefault;

// ensure there is a '{version}' placeholder in the tag name
if (string.IsNullOrEmpty(tagNameFormat) || !tagNameFormat.Contains("{version}"))
{
Console.Error.WriteLine($"Invalid 'tagName' setting '{tagNameFormat}'. Missing version placeholder '{{version}}'.");
return Task.FromResult((int)ExitCodes.InvalidTagNameSetting);
}

// get commit to tag
LibGit2Sharp.Repository repository = context.Repository;
if (!context.TrySelectCommit(versionOrRef))
{
Expand Down Expand Up @@ -585,8 +604,12 @@ private static Task<int> OnTagCommand(string project, string versionOrRef)
return Task.FromResult((int)ExitCodes.NoVersionJsonFound);
}

oracle.PublicRelease = true; // assume a public release so we don't get a redundant -gCOMMITID in the tag name
string tagName = $"v{oracle.SemVer2}";
// assume a public release so we don't get a redundant -gCOMMITID in the tag name
oracle.PublicRelease = true;

// replace the "{version}" placeholder with the actual version
string tagName = tagNameFormat.Replace("{version}", oracle.SemVer2);

try
{
context.ApplyTag(tagName);
Expand Down

0 comments on commit 7d22ed6

Please sign in to comment.