diff --git a/release/README.md b/release/README.md index 31b05d5c38..ea01c7d0bb 100644 --- a/release/README.md +++ b/release/README.md @@ -7,10 +7,84 @@ distinct machines, and end up with a byte-for-byte identical binary. However, this wasn't _fully_ solved in `go1.13`, as the build system still includes the directory the binary is built into the binary itself. As a result, our scripts utilize a work around needed until `go1.13.2`. +Every release should note which Go version was used to build the release, so +that version should be used for verifying the release. ## Building a New Release -### macOS/Linux/Windows (WSL) +### Tagging and pushing a new tag (for maintainers) + +Before running release scripts, a few things need to happen in order to finally +create a release and make sure there are no mistakes in the release process. + +First, make sure that before the tagged commit there are modifications to the +[CHANGES](../CHANGES) file committed. +The CHANGES file should be a changelog that roughly mirrors the release notes. +Generally, the PRs that have been merged since the last release have been +listed in the CHANGES file and categorized. +For example, these changes have had the following format in the past: +``` +Changes in X.YY.Z (Month Day Year): + - Protocol and Network-related changes: + - PR Title One (#PRNUM) + - PR Title Two (#PRNUMTWO) + ... + - RPC changes: + - Crypto changes: + ... + + - Contributors (alphabetical order): + - Contributor A + - Contributor B + - Contributor C + ... +``` + +If the previous tag is, for example, `vA.B.C`, then you can get the list of +contributors (from `vA.B.C` until the current `HEAD`) using the following command: +```bash +git log vA.B.C..HEAD --pretty="%an" | sort | uniq +``` +After committing changes to the CHANGES file, the tagged release commit +should be created. + +The tagged commit should be a commit that bumps version numbers in `version.go` +and `cmd/btcctl/version.go`. +For example (taken from [f3ec130](https://github.com/btcsuite/btcd/commit/f3ec13030e4e828869954472cbc51ac36bee5c1d)): +```diff +diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go +index 2195175c71..f65cacef7e 100644 +--- a/cmd/btcctl/version.go ++++ b/cmd/btcctl/version.go +@@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr + const ( + appMajor uint = 0 + appMinor uint = 20 +- appPatch uint = 0 ++ appPatch uint = 1 + + // appPreRelease MUST only contain characters from semanticAlphabet + // per the semantic versioning spec. +diff --git a/version.go b/version.go +index 92fd60fdd4..fba55b5a37 100644 +--- a/version.go ++++ b/version.go +@@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr + const ( + appMajor uint = 0 + appMinor uint = 20 +- appPatch uint = 0 ++ appPatch uint = 1 + + // appPreRelease MUST only contain characters from semanticAlphabet + // per the semantic versioning spec. +``` + +Next, this commit should be signed by the maintainer using `git commit -S`. +The commit should be tagged and signed with `git tag -s`, and should be +pushed using `git push origin TAG`. + +### Building a release on macOS/Linux/Windows (WSL) No prior set up is needed on Linux or macOS is required in order to build the release binaries. However, on Windows, the only way to build the release @@ -25,6 +99,46 @@ This will then create a directory of the form `btcd-` containing archives of the release binaries for each supported operating system and architecture, and a manifest file containing the hash of each archive. +### Pushing a release (for maintainers) + +Now that the directory `btcd-` is created, the manifest file needs to be +signed by a maintainer and the release files need to be published to GitHub. + +Sign the `manifest-.txt` file like so: +```sh +gpg --sign --detach-sig manifest-.txt +``` +This will create a file named `manifest-.txt.sig`, which will must +be included in the release files later. + +#### Note before publishing +Before publishing, go through the reproducible build process that is outlined +in this document with the files created from `release/release.sh`. This includes +verifying commit and tag signatures using `git verify-commit` and git `verify-tag` +respectively. + +Now that we've double-checked everything and have all of the necessary files, +it's time to publish release files on GitHub. +Follow [this documentation](https://docs.github.com/en/github/administering-a-repository/managing-releases-in-a-repository) +to create a release using the GitHub UI, and make sure to write release notes +which roughly follow the format of [previous release notes](https://github.com/btcsuite/btcd/releases/tag/v0.20.1-beta). +This is different from the [CHANGES](../CHANGES) file, which should be before the +tagged commit in the git history. +Much of the information in the release notes will be the same as the CHANGES +file. +It's important to include the Go version used to produce the release files in +the release notes, so users know the correct version of Go to use to reproduce +and verify the build. +When following the GitHub documentation, include every file in the `btcd-` +directory. + +At this point, a signed commit and tag on that commit should be pushed to the main +branch. The directory created from running `release/release.sh` should be included +as release files in the GitHub release UI, and the `manifest-.txt` file +signature, called `manifest-.txt.sig`, should also be included. +A release notes document should be created and written in the GitHub release UI. +Once all of this is done, feel free to click `Publish Release`! + ## Verifying a Release With `go1.13`, it's now possible for third parties to verify release binaries. diff --git a/release/notes.sample b/release/notes.sample deleted file mode 100644 index 86a79a61f5..0000000000 --- a/release/notes.sample +++ /dev/null @@ -1,6 +0,0 @@ -- Each release note is preceded by a dash -- Each release note must not exceed 74 characters per line -- Release notes that require a longer explanation than will fit on a - single line should be wrapped with the text indented as in this line -- No periods at the end of each release note -- Other minor cleanup and bug fixes diff --git a/release/prep_release.sh b/release/prep_release.sh deleted file mode 100644 index c64824a644..0000000000 --- a/release/prep_release.sh +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Conformal Systems LLC -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# -# Prepares for a release: -# - Bumps version according to specified level (major, minor, or patch) -# - Updates all version files and package control files with new version -# - Performs some basic validation on specified release notes -# - Updates project changes file with release notes -# - -PROJECT=btcd -PROJECT_UC=$(echo $PROJECT | tr '[:lower:]' '[:upper:]') -SCRIPT=$(basename $0) -VERFILE=../version.go -VERFILES="$VERFILE ../cmd/btcctl/version.go" -PROJ_CHANGES=../CHANGES - -# verify params -if [ $# -lt 2 ]; then - echo "usage: $SCRIPT {major | minor | patch} release-notes-file" - exit 1 -fi - -CUR_DIR=$(pwd) -cd "$(dirname $0)" - -# verify version files exist -for verfile in $VERFILES; do - if [ ! -f "$verfile" ]; then - echo "$SCRIPT: error: $verfile does not exist" 1>&2 - exit 1 - fi -done - -# verify changes file exists -if [ ! -f "$PROJ_CHANGES" ]; then - echo "$SCRIPT: error: $PROJ_CHANGES does not exist" 1>&2 - exit 1 -fi - -RTYPE="$1" -RELEASE_NOTES="$2" -if [ $(echo $RELEASE_NOTES | cut -c1) != "/" ]; then - RELEASE_NOTES="$CUR_DIR/$RELEASE_NOTES" -fi - -# verify valid release type -if [ "$RTYPE" != "major" -a "$RTYPE" != "minor" -a "$RTYPE" != "patch" ]; then - echo "$SCRIPT: error: release type must be major, minor, or patch" - exit 1 -fi - -# verify release notes -if [ ! -e "$RELEASE_NOTES" ]; then - echo "$SCRIPT: error: specified release notes file does not exist" - exit 1 -fi - -if [ ! -s "$RELEASE_NOTES" ]; then - echo "$SCRIPT: error: specified release notes file is empty" - exit 1 -fi - -# verify release notes format -while IFS='' read line; do - if [ -z "$line" ]; then - echo "$SCRIPT: error: release notes must not have blank lines" - exit 1 - fi - if [ ${#line} -gt 74 ]; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "with more than 74 characters" - exit 1 - fi - if expr "$line" : ".*\.$" >/dev/null 2>&1 ; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "that end in a period" - exit 1 - fi - if ! expr "$line" : "\-" >/dev/null 2>&1; then - if ! expr "$line" : " " >/dev/null 2>&1; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "that do not begin with a dash and are not indented" - exit 1 - fi - fi -done <"$RELEASE_NOTES" - -# verify git is available -if ! type git >/dev/null 2>&1; then - echo -n "$SCRIPT: error: Unable to find 'git' in the system path." - exit 1 -fi - -# verify the git repository is on the master branch -BRANCH=$(git branch | grep '\*' | cut -c3-) -if [ "$BRANCH" != "master" ]; then - echo "$SCRIPT: error: git repository must be on the master branch." - exit 1 -fi - -# verify there are no uncommitted modifications prior to release modifications -NUM_MODIFIED=$(git diff 2>/dev/null | wc -l | sed 's/^[ \t]*//') -NUM_STAGED=$(git diff --cached 2>/dev/null | wc -l | sed 's/^[ \t]*//') -if [ "$NUM_MODIFIED" != "0" -o "$NUM_STAGED" != "0" ]; then - echo -n "$SCRIPT: error: the working directory contains uncommitted " - echo "modifications" - exit 1 -fi - -# get version -PAT_PREFIX="(^[[:space:]]+app" -PAT_SUFFIX='[[:space:]]+uint[[:space:]]+=[[:space:]]+)[0-9]+$' -MAJOR=$(egrep "${PAT_PREFIX}Major${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -MINOR=$(egrep "${PAT_PREFIX}Minor${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -PATCH=$(egrep "${PAT_PREFIX}Patch${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -if [ -z "$MAJOR" -o -z "$MINOR" -o -z "$PATCH" ]; then - echo "$SCRIPT: error: unable to get version from $VERFILE" 1>&2 - exit 1 -fi - -# bump version according to level -if [ "$RTYPE" = "major" ]; then - MAJOR=$(expr $MAJOR + 1) - MINOR=0 - PATCH=0 -elif [ "$RTYPE" = "minor" ]; then - MINOR=$(expr $MINOR + 1) - PATCH=0 -elif [ "$RTYPE" = "patch" ]; then - PATCH=$(expr $PATCH + 1) -fi -PROJ_VER="$MAJOR.$MINOR.$PATCH" - -# update project changes with release notes -DATE=$(date "+%a %b %d %Y") -awk -v D="$DATE" -v VER="$PROJ_VER" ' -/=======/ && first_line==0 { - first_line=1 - print $0 - next -} -/=======/ && first_line==1 { - print $0 - print "" - print "Changes in "VER" ("D")" - exit -} -{ print $0 } -' <"$PROJ_CHANGES" >"${PROJ_CHANGES}.tmp" -cat "$RELEASE_NOTES" | sed 's/^/ /' >>"${PROJ_CHANGES}.tmp" -awk ' -/=======/ && first_line==0 { - first_line=1 - next -} -/=======/ && first_line==1 { - second_line=1 - next -} -second_line==1 { print $0 } -' <"$PROJ_CHANGES" >>"${PROJ_CHANGES}.tmp" - -# update version filef with new version -for verfile in $VERFILES; do - sed -E " - s/${PAT_PREFIX}Major${PAT_SUFFIX}/\1${MAJOR}/; - s/${PAT_PREFIX}Minor${PAT_SUFFIX}/\1${MINOR}/; - s/${PAT_PREFIX}Patch${PAT_SUFFIX}/\1${PATCH}/; - " <"$verfile" >"${verfile}.tmp" -done - - -# Apply changes -mv "${PROJ_CHANGES}.tmp" "$PROJ_CHANGES" -for verfile in $VERFILES; do - mv "${verfile}.tmp" "$verfile" -done - -echo "All files have been prepared for release." -echo "Use the following commands to review the changes for accuracy:" -echo " git status" -echo " git diff" -echo "" -echo "If everything is accurate, use the following commands to commit, tag," -echo "and push the changes" -echo " git commit -am \"Prepare for release ${PROJ_VER}.\"" -echo -n " git tag -a \"${PROJECT_UC}_${MAJOR}_${MINOR}_${PATCH}\" -m " -echo "\"Release ${PROJ_VER}\"" -echo " git push" -echo " git push --tags" diff --git a/release/release.sh b/release/release.sh index 7b0885dac6..cc65fb6cf1 100755 --- a/release/release.sh +++ b/release/release.sh @@ -1,11 +1,12 @@ #!/bin/bash +# Copyright (c) 2016 Company 0, LLC. +# Copyright (c) 2016-2020 The btcsuite developers +# Use of this source code is governed by an ISC +# license that can be found in the LICENSE file. + # Simple bash script to build basic btcd tools for all the platforms we support # with the golang cross-compiler. -# -# Copyright (c) 2016 Company 0, LLC. -# Use of this source code is governed by the ISC -# license. set -e