[!NOTE] All commands should be executed from the root of the repository unless otherwise stated.
Perform a one-time install of the nbgv tool using the following dotnet CLI command:
[!NOTE] The version should match the one used in Directory.Packages.props.
dotnet tool install -g nbgv --version <theActualVersion>
To synchronize the AnalyzerReleases.Shipped.md release version with the latest commit, there is a Git commit hook that ensures that the version in the HEAD commit is the same version that is committed to the file.
Check whether the Git core.hooksPath is correctly set:
git config core.hooksPath
If the command outputs a path, confirm that the path is ./eng/git-hooks. In all other cases, run the following command to set it appropriately.
git config core.hooksPath ./eng/git-hooks
Repeat the first command to confirm that it is set.
This project uses Nerdbank.GitVersioning to assist with creating version numbers based on the current branch and commit. This tool handles making pre-release and production releases on release branches.
At any point before or during the release the version of the HEAD commit of the current Git branch can be checked using the following command.
nbgv get-version
The reply will show a table of version information.
Version: 2.0.0 AssemblyVersion: 2.0.0.0 AssemblyInformationalVersion: 2.0.0-beta.5+a54c015802 NuGetPackageVersion: 2.0.0-beta.5 NpmPackageVersion: 2.0.0-beta.5
The NuGetPackageVersion is the one we will be referring to in the rest of this document. Although, be aware that in some steps it should be prefixed with v, such as when tagging the release.
[!NOTE] This version number will change for each Git commit and applies only to the current branch.
main branch.AnalyzerReleases.Unshipped.md and AnalyzerReleases.Shipped.md are set up consistently and align with the features that have been merged since the prior release. Do not yet move any rules from AnalyzerReleases.Unshipped.md to AnalyzerReleases.Shipped.md. That task will be performed in a later step.README, LICENSE, NOTICE and other documentation files are up to date.If any changes are required, it is recommended to use feature branch(es) and pull request(s) to update the main branch as appropriate before creating a release branch.
The version that will be released next is controlled by the version.json file. We must choose the release version and commit it to the main branch prior to creating a release branch.
[!NOTE] If you are not familiar with these terms, these are covered in the Semantic Versioning 2.0 document.
For the purposes of this project:
[!NOTE] This project doesn't have any public API that users consume, so the type of release is strictly informational in nature, not functional.
Now is the time to decide which of these strategies to use for the current version. For the next version (a future release version), we should always assume a patch. This is primarily so we never have to downgrade a version even if a patch is rarely done in practice.
With that in mind, open version.json and look at the “version” property, which will determine next version that will be released.
"version": "2.0.0-alpha.{height}"
The above example shows that the next version that will be released from a release branch is 2.0.0 or 2.0.0-beta.x (where x is an auto-incrementing number). The actual version in the file (alpha) will be used only if the main branch is released directly (something that is rare and not covered here).
If we are releasing new features and want the next Minor version (2.1.0), we need to update the version.json file to reflect that version.
"version": "2.1.0-alpha.{height}"
Or, if the next version will be a patch, then leave the file unchanged. Commit any changes to the main branch and push them upstream before proceeding.
Prereleases should rarely need to change the version.json file and will later choose the Requires Stabilization option when creating a release branch.
[!IMPORTANT] Release version numbers must always use all 3 version components when specified in
version.json.
There are 2 supported scenarios for the release workflow:
[!NOTE] In both cases,
mainis advanced to the specified--nextVersion. This number should always be a patch bump and it should always use all 3 version components (major.minor.patch).The release branch name is always based on the version being released (e.g.,
release/v2.0.0).
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.
For example, assume the version.json file on the main branch is currently set up 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}.
nbgv prepare-release --nextVersion 2.0.1
The command should respond with:
release/v2.0.0 branch now tracks v2.0.0 stabilization and release. main branch now tracks v2.0.1-alpha.{height} development.
The tool created a release branch named release/v2.0.0. Every build from this branch will be versioned 2.0.0, regardless of how many commits are added.
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). Starting from the same point as the Ready to Release scenario, run the following command.
nbgv prepare-release beta --nextVersion 2.0.1
The command should respond with:
release/v2.0.0 branch now tracks v2.0.0-beta.{height} stabilization and release. main branch now tracks v2.0.1-alpha.{height} development.
The tool created a release branch named release/v2.0.0. Every commit to 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 (i.e. 2.0.0-beta.123).
After the release branch is created, the rest of the commits will be added to the release branch, so use the git checkout command to switch to that branch.
git checkout <release-branch>
[!IMPORTANT] This command depends on Powershell and Java.
The Release Audit Tool will ensure that all source code files and most other non-generated text files contain a license header.
pwsh ./rat.ps1
The tool will apply the updates directly to the local working directory. Review and commit the changes to your local Git clone, adding exclusions to .rat-excludes and re-running as necessary.
[!NOTE] These extra commits will automatically bump the version number from what was specified when Creating a Release Branch. It is normal and expected that we may have extra gaps between release version numbers.
Roslyn analyzers use two release tracking files to manage analyzer rule metadata:
AnalyzerReleases.Unshipped.md Tracks analyzer rules that have been added or modified since the last release but are not yet published in a shipped package.
AnalyzerReleases.Shipped.md Tracks analyzer rules that have been released in one or more shipped packages. This is the authoritative record of rules shipped at specific versions.
Before tagging the release, you must ensure that these files are up to date. This ensures that the release metadata exactly matches the rules shipped in the NuGet package.
[!NOTE] If the release doesn't contain new or changed analyzer rules, this step can be skipped. For example, if the release only contains new code fixes and/or backward compatible patches to existing analyzers.
Since Nerdbank.GitVersioning calculates the release version, the AnalyzerReleases.Shipped.md file is expected to include a version token when it is committed. A version token must be included in the header of the new section being added to AnalyzerReleases.Shipped.md.
## Release {{vnext}}
[!IMPORTANT] This change is expected to be the final commit prior to release. If there are any other changes you anticipate that need to be included in the release, they should be committed to the release branch prior to this step.
[!IMPORTANT] This step depends on the NBGV tool, Bash, and the setup of the Git commit hook as described in Prerequisites.
Locate pending unshipped rules
Open AnalyzerReleases.Unshipped.md. This contains all rules added or modified since the last release.
Move unshipped rules into AnalyzerReleases.Shipped.md
AnalyzerReleases.Shipped.md with a heading for the release version, containing the version token.AnalyzerReleases.Unshipped.md into this section.Clear AnalyzerReleases.Unshipped.md
After the rules are copied over, AnalyzerReleases.Unshipped.md should either be empty or contain only rules that are not part of this release.
Commit the changes
Commit the modifications before tagging the release.
git add -A git commit -m "Updated AnalyzerReleases with the latest changes"
[!NOTE] To ensure the Git commit hook works correctly, run these commands on the command line. Some GUI tools may interfere with it.
AnalyzerReleases.Shipped.md evolves by appending each release as a new section. Each release is marked with a ## Release <version> header.
[!NOTE] Due to a limitation/bug in the Roslyn meta-analyzers, the Release header cannot contain semver pre-release labels (e.g.,
-beta,-rc, etc.). Therefore, the version token{{vnext}}is used to indicate the next minor release version, which will be replaced with the actual version during the git post-commit hook.
## Release 2.0 ### New Rules Rule ID | Category | Severity | Notes ---------------|----------|----------|----------------------------------------- LuceneDev1000 | Design | Warning | Floating point types should not be compared for exact equality LuceneDev1001 | Design | Warning | Floating point types should be formatted with J2N methods ## Release {{vnext}} ### New Rules Rule ID | Category | Severity | Notes ---------------|----------|----------|----------------------------------------- LuceneDev1002 | Design | Warning | Floating point type arithmetic needs to be checked ### Removed Rules Rule ID | Notes ---------------|------------------------------------------------- LuceneDev1001 | Replaced with LuceneDev1002 (better precision)
The release process is mostly automated. However, a manual review is required on the GitHub releases page. This allows you to:
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. Select the run corresponding to the version tag that is pushed upstream to view the progress.
Run the following command to tag the HEAD commit of the release branch.
nbgv tag
This command will reply with the tag name and release commit hash.
v1.0.0-alpha.155 tag created at bd65d5e12b6ed44ba478b8f564dd3f19799dfbf4.
[!NOTE] The release build workflow always builds from the tag, not the HEAD commit. To ensure all commits on the branch make it into the release, ensure that the tag is pointing to the HEAD commit.
The final step to begin the release build is to push the tag and any new commits to the upstream repository.
git push <remote-name> <release-branch> <tag-name>
[!IMPORTANT] If there are any local commits that have not yet been pushed, the above command will include them in the release. The command provided as a hint from
nbgv tagdoes not include the branch name, but we should always push the branch as well as the tags to put the upstream repository in a consistent state.
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 corresponding to the version you tagged.
[!NOTE] If the release doesn't appear, check the GitHub Actions UI. Select the run corresponding to the version tag that is pushed upstream to view the progress.
There are 2 possible outcomes for the release workflow:
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.
The following labels are recognized by the release notes generator.
| GitHub Label | Action |
|---|---|
| notes:ignore | Removes the PR from the release notes |
| notes:breaking-change | Categorizes the PR under “Breaking Changes” |
| notes:new-feature | Categorizes the PR under “New Features” |
| notes:bug-fix | Categorizes the PR under “Bug Fixes” |
| notes:performance-improvement | Categorizes the PR under “Performance Improvements” |
| notes:improvement | Categorizes the PR under “Improvements” |
| notes:website-or-documentation | Categorizes the PR under “Website and API Documentation” |
| <none of the above> | Categorizes the PR under “Other Changes” |
[!NOTE] 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.
The release will also attach the NuGet packages that will be released to NuGet. Download the packages and run some basic checks:
.nupkg files into a local directory, and add a reference to the directory from Visual Studio. See this answer for the steps. Verify that the NuGet packages can be referenced by a new project and that the project compiles.version.json..nupkg files in NuGet Package Explorer and check that files in the packages are present and that the XML config is up to date.Once everything is in order, the release can be published, which will deploy the packages to NuGet.org automatically.
[!NOTE] 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_KEYin GitHub Secrets with the new key.
At the bottom of the draft release page, click on Publish release.
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 and correct any problems that were reported. Make any necessary commits to the release branch before starting the release.
Since the tag did not result in a release, it is important to delete it to avoid a confusing release history.
git tag -d v<package-version> git push --delete <remote-name> v<package-version>
AnalyzerReleases.Shipped.mdIf you previously added a new section to AnalyzerReleases.Shipped.md, it may contain a version number that no longer corresponds to the release. Change the release header to include the replacement token, once again.
## Release {{vnext}}
Then commit the change to the release branch.
Next, follow the same procedure starting at Tag the HEAD Commit to restart the draft release.
Finally, merge the release branch back into the main branch and push the changes to the upstream repository.
[!IMPORTANT] Release branches start with
release/v.
git checkout main git merge <release-branch> git push <remote-name> main
From this point, the release will be tracked historically using the Git tag, so there is no reason to keep the release branch once it has been merged. You may wish to delay the deletion for a few days in case it is needed for some reason, but when you are ready, the commands to delete the local and remote branches are:
[!IMPORTANT] Release branches start with
release/v. Take care not to delete the tag, which starts with av.
git branch -d <release-branch> git push --delete <remote-name> <release-branch>
The Lucene.NET project is the only consumer of this package. If the release was intended for general use (not just a one-off scan), update the version in .build/dependencies.props to reflect the new release and submit a pull request to the Lucene.NET repository.