|
| 1 | +# Making a Release |
| 2 | + |
| 3 | +This project uses Nerdbank.GitVersioning to assist with creating version numbers based on the current branch and commit. This tool handles making pre-release builds on the main branch and production releases on release branches. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +- [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) |
| 8 | +- [nbgv tool](https://www.nuget.org/packages/nbgv/) (the version must match the one defined in [Directory.Packages.props](../Directory.Packages.props)) |
| 9 | + |
| 10 | +### Installing NBGV Tool |
| 11 | + |
| 12 | +Perform a one-time install of the nbgv tool using the following dotnet CLI command: |
| 13 | + |
| 14 | +```console |
| 15 | +dotnet tool install -g nbgv --version <theActualVersion> |
| 16 | +``` |
| 17 | + |
| 18 | +## Versioning Primer |
| 19 | + |
| 20 | +This project uses [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html) and strictly adheres to the guidelines about bumping the major, minor and build numbers of the version number. |
| 21 | + |
| 22 | +The assembly version should remain the same in all cases, except when the major version changes, so that it can be used as a drop-in replacement. |
| 23 | + |
| 24 | +## Creating a Release Branch |
| 25 | + |
| 26 | +### Release Workflow Overview |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +### Ready to Release |
| 31 | + |
| 32 | +When the changes in the main branch are ready to release, create a release branch using the following nbgv tool command as specified in the [documentation](https://github.com/dotnet/Nerdbank.GitVersioning/blob/master/doc/nbgv-cli.md). |
| 33 | + |
| 34 | +For example, assume the `version.json` file on the main branch is currently setup as `2.0.0-alpha.{height}`. We want to go from this version to a release of `2.0.0` and set the next version on the main branch as `2.0.1-alpha.{height}`. |
| 35 | + |
| 36 | +```console |
| 37 | +nbgv prepare-release --nextVersion 2.0.1 |
| 38 | +``` |
| 39 | + |
| 40 | +The command should respond with: |
| 41 | + |
| 42 | +```console |
| 43 | +release/v2.0 branch now tracks v2.0.0 stabilization and release. |
| 44 | +main branch now tracks v2.0.1-alpha.{height} development. |
| 45 | +``` |
| 46 | + |
| 47 | +The tool created a release branch named `release/v2.0`. Every build from this branch (regardless of how many commits are added) will be versioned 2.0.0. |
| 48 | + |
| 49 | +### Requires Stabilization |
| 50 | + |
| 51 | +When creating a release that may require a few iterations to become stable, it is better to create a beta branch (more about that decision can be found [here](https://github.com/dotnet/Nerdbank.GitVersioning/blob/master/doc/nbgv-cli.md#preparing-a-release)). Starting from the same point as the [Ready to Release](#ready-to-release) scenario, we use the following command. |
| 52 | + |
| 53 | +```console |
| 54 | +nbgv prepare-release beta --nextVersion 2.0.1 |
| 55 | +``` |
| 56 | + |
| 57 | +The command should respond with: |
| 58 | + |
| 59 | +```console |
| 60 | +release/v2.0 branch now tracks v2.0.0-beta.{height} stabilization and release. |
| 61 | +main branch now tracks v2.0.0-alpha.{height} development. |
| 62 | +``` |
| 63 | + |
| 64 | +The tool created a release branch named `release/v2.0`. Every build from this branch will be given a unique pre-release version starting with 2.0.0-beta and ending in a dot followed by one or more digits. |
| 65 | + |
| 66 | +### Bumping the Version Manually |
| 67 | + |
| 68 | +When releasing a version that does not directly follow the current release version, manually update the `version` (and `assemblyVersion` if this is a major version bump) in `version.json` before creating the release branch. See the [version.json schema](https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json) to determine valid options. |
| 69 | + |
| 70 | +## Correcting the Release Version Height |
| 71 | + |
| 72 | +Nerdbank.GitVersioning is designed in a way that it doesn't produce the same version number twice. This is done by using a "git height", which counts the number of commits since the last version update. This works great for CI, but is less than ideal when we don't want to skip over versions for the release. |
| 73 | + |
| 74 | +Since Nerdbank.GitVersioning considers each commit a new "version," the `versionHeightOffset` can be adjusted on the release branch to ensure the release uses the correct version number. This can be done by using the following command to see what version we are currently on, and then adjusting the value accordingly. |
| 75 | + |
| 76 | +```console |
| 77 | +nbgv get-version |
| 78 | +``` |
| 79 | + |
| 80 | +> [!NOTE] |
| 81 | +> Officially, it is not recommended to use `versionHeightOffset` and in general that is true. However, using it in a narrow scope, such as on a release branch should be okay. In practice, users will not build from these branches, they will build from a release tag. |
| 82 | +
|
| 83 | +Then open the `version.json` file at the repository root, and set the `versionHeightOffset` using the formula `versionHeightOffset - ((versionHeight - desiredHeight) + 1)`. For example, if the current version is 2.0.1-beta.14 and we want to release 2.0.1-beta.5 (because the last version released was 2.0.1-beta.4), and the `versionHeightOffset` is set to -21: |
| 84 | + |
| 85 | +###### Calculating versionHeightOffset |
| 86 | +``` |
| 87 | +-21 - ((14 - 5) + 1) = -31 |
| 88 | +``` |
| 89 | + |
| 90 | +So, we must set `versionHeightOffset` to -31 and commit the change. |
| 91 | + |
| 92 | +Note that the + 1 is because we are creating a new commit that will increment the number by 1. The change must be committed to see the change to the version number. Run the command again to check that the version will be correct. |
| 93 | + |
| 94 | +```console |
| 95 | +nbgv get-version |
| 96 | +``` |
| 97 | + |
| 98 | +## Creating a Release Build |
| 99 | + |
| 100 | +The release process is mostly automated. However, a manual review is required on the GitHub releases page. This allows you to: |
| 101 | + |
| 102 | +1. Manually review and edit the release notes |
| 103 | +2. Re-generate the release notes after editing PR tags and titles |
| 104 | +3. Manually check the release packages |
| 105 | +4. Abort the release to try again |
| 106 | +5. Publish the release to deploy the packages to NuGet.org |
| 107 | + |
| 108 | +## Create a Draft Release |
| 109 | + |
| 110 | +Tagging the commit and pushing it to the GitHub repository will start the automated draft release. The progress of the release can be viewed in the [GitHub Actions UI](https://github.com/apache/lucenenet-codeanalysis-dev/actions). Select the run corresponding to the version tag that is pushed upstream to view the progress. |
| 111 | + |
| 112 | +### Tagging the Commit |
| 113 | + |
| 114 | +If you don't already know the version that corresponds to the HEAD commit, check it now. |
| 115 | + |
| 116 | +```console |
| 117 | +nbgv get-version |
| 118 | +``` |
| 119 | + |
| 120 | +The reply will show a table of version information. |
| 121 | + |
| 122 | +```console |
| 123 | +Version: 2.0.0 |
| 124 | +AssemblyVersion: 2.0.0.0 |
| 125 | +AssemblyInformationalVersion: 2.0.0-beta.5+a54c015802 |
| 126 | +NuGetPackageVersion: 2.0.0-beta.5 |
| 127 | +NpmPackageVersion: 2.0.0-beta.5 |
| 128 | +``` |
| 129 | + |
| 130 | +Tag the commit with `v` followed by the NuGetPackageVersion. |
| 131 | + |
| 132 | +```console |
| 133 | +git tag -a v<package-version> <commit-hash> -m "v<package-version>" |
| 134 | +git push <remote-name> <release-branch> --follow-tags |
| 135 | +``` |
| 136 | + |
| 137 | +> [!NOTE] |
| 138 | +> If there are any local commits that have not yet been pushed, the above command will include them in the release. |
| 139 | +
|
| 140 | +The push will start the automated draft release which will take a few minutes. When completed, there will be a new draft release in the [GitHub Releases](https://github.com/apache/lucenenet-codeanalysis-dev/releases) corresponding to the version you tagged. |
| 141 | + |
| 142 | +> [!NOTE] |
| 143 | +> If the release doesn't appear, check the [GitHub Actions UI](https://github.com/apache/lucenenet-codeanalysis-dev/actions). Select the run corresponding to the version tag that is pushed upstream to view the progress. |
| 144 | +
|
| 145 | +### Successful Draft Release |
| 146 | + |
| 147 | +#### Release Notes |
| 148 | + |
| 149 | +Review the draft release notes and edit or regenerate them if necessary. release notes are generated based on PR titles and categorized by their labels. If something is amiss, they can be corrected by editing the PR titles and labels, deleting the previously generated release notes, and clicking the Generate Release Notes button. |
| 150 | + |
| 151 | +##### Labels that Apply to the Release Notes |
| 152 | + |
| 153 | +| GitHub Label | Action | |
| 154 | +|--------------------------------|----------------------------------------------------------| |
| 155 | +| notes:ignore | Removes the PR from the release notes | |
| 156 | +| notes:breaking-change | Categorizes the PR under "Breaking Changes" | |
| 157 | +| notes:new-feature | Categorizes the PR under "New Features" | |
| 158 | +| notes:bug-fix | Categorizes the PR under "Bug Fixes" | |
| 159 | +| notes:performance-improvement | Categorizes the PR under "Performance Improvements" | |
| 160 | +| notes:improvement | Categorizes the PR under "Improvements" | |
| 161 | +| notes:website-or-documentation | Categorizes the PR under "Website and API Documentation" | |
| 162 | +| \<none of the above\> | Categorizes the PR under "Other Changes" | |
| 163 | + |
| 164 | +> [!NOTE] |
| 165 | +> Using multiple labels from the above list is not supported and the first category in the above list will be used if more than one is applied to a GitHub pull request. |
| 166 | +
|
| 167 | +#### Release Artifacts |
| 168 | + |
| 169 | +The release will also attach the NuGet packages that will be released to NuGet. Download the packages and run some basic checks: |
| 170 | + |
| 171 | +1. Put the `.nupkg` files into a local directory, and add a reference to the directory from Visual Studio. See [this answer](https://stackoverflow.com/a/10240180) for the steps. Check to ensure the NuGet packages can be referenced by a new project and the project will compile. |
| 172 | +2. Check the version information in [JetBrains dotPeek](https://www.jetbrains.com/decompiler/) to ensure the assembly version, file version, and informational version are consistent with what was specified in `version.json`. |
| 173 | +3. Open the `.nupkg` files in [NuGet Package Explorer](https://www.microsoft.com/en-us/p/nuget-package-explorer/9wzdncrdmdm3#activetab=pivot:overviewtab) and check that files in the packages are present and that the XML config is up to date. |
| 174 | + |
| 175 | +#### Publish the Release |
| 176 | + |
| 177 | +Once everything is in order, the release can be published, which will deploy the packages to NuGet.org automatically. |
| 178 | + |
| 179 | +> [!NOTE] |
| 180 | +> While the deployment will probably succeed, note that there is currently no automation if it fails to deploy on the first try. The GitHub API key must be regenerated once per year. If you are uncertain that it is still valid, check the expiry date in the NuGet.org portal now and regenerate, if needed. Update the `NUGET_API_KEY` in [GitHub Secrets](https://github.com/apache/lucenenet-codeanalysis-dev/settings/secrets/actions) with the new key. |
| 181 | +
|
| 182 | +At the bottom of the draft release page, click on **Publish release**. |
| 183 | + |
| 184 | +### Failed Draft Release |
| 185 | + |
| 186 | +If the build failed in any way, the release can be restarted by deleting the tag and trying again. First check to see the reason why the build failed in the [GitHub Actions UI](https://github.com/apache/lucenenet-codeanalysis-dev/actions) and correct any problems that were reported. |
| 187 | + |
| 188 | +#### Restarting the Draft Release |
| 189 | + |
| 190 | +##### Delete the Failed Tag |
| 191 | + |
| 192 | +Since the tag didn't make it to release, it is important to delete it to avoid a confusing release history. It is required to be removed if the next attempt will be for the same version number. |
| 193 | + |
| 194 | +```console |
| 195 | +git tag -d v<package-version> |
| 196 | +git push --delete <remote-name> v<package-version> |
| 197 | +``` |
| 198 | + |
| 199 | +##### Push a New Version Tag |
| 200 | + |
| 201 | +> [!NOTE] |
| 202 | +> The same version number can be reused if there weren't any commits required to correct the release problem or if the `versionHeightOffset` is changed as described above. |
| 203 | +
|
| 204 | +Once the issues have been addressed to fix the build and reset the version (if necessary), follow the same procedure starting at [Tagging the Commit](#tagging-the-commit) to restart the draft release. |
| 205 | + |
| 206 | +## Post Release Steps |
| 207 | + |
| 208 | +### Merge the Release Branch |
| 209 | + |
| 210 | +Finally, merge the release branch back into the main branch and push the changes to GitHub. |
| 211 | + |
| 212 | +```console |
| 213 | +git checkout <main-branch> |
| 214 | +git merge <release-branch> |
| 215 | +git push <remote-name> <main-branch> |
| 216 | +``` |
0 commit comments