Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions doc/nbgv-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,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