consul/build-support/functions/30-release.sh

537 lines
14 KiB
Bash
Raw Normal View History

# Copyright (c) HashiCorp, Inc.
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
# SPDX-License-Identifier: BUSL-1.1
function tag_release {
# Arguments:
# $1 - Path to top level consul source
# $2 - Version string to use for tagging the release
# $3 - Alternative GPG key id used for signing the release commit (optional)
#
# Returns:
# 0 - success
# * - error
#
# Notes:
# If the RELEASE_UNSIGNED environment variable is set then no gpg signing will occur
if ! test -d "$1"
then
err "ERROR: '$1' is not a directory. tag_release must be called with the path to the top level source as the first argument'"
return 1
fi
if test -z "$2"
then
err "ERROR: tag_release must be called with a version number as the second argument"
return 1
fi
# determine whether the gpg key to use is being overridden
local gpg_key=${HASHICORP_GPG_KEY}
if test -n "$3"
then
gpg_key=$3
fi
pushd "$1" > /dev/null
local ret=0
local branch_to_tag=$(git_branch) || ret=1
# perform an usngined release if requested (mainly for testing locally)
if test ${ret} -ne 0
then
err "ERROR: Failed to determine git branch to tag"
elif is_set "$RELEASE_UNSIGNED"
then
(
git commit --allow-empty -a -m "Release v${2}" &&
git tag -a -m "Version ${2}" "v${2}" "${branch_to_tag}"
)
ret=$?
# perform a signed release (official releases should do this)
elif have_gpg_key ${gpg_key}
then
(
git commit --allow-empty -a --gpg-sign=${gpg_key} -m "Release v${2}" &&
git tag -a -m "Version ${2}" -s -u ${gpg_key} "v${2}" "${branch_to_tag}"
)
ret=$?
# unsigned release not requested and gpg key isn't useable
else
err "ERROR: GPG key ${gpg_key} is not in the local keychain - to continue set RELEASE_UNSIGNED=1 in the env"
ret=1
fi
popd > /dev/null
return $ret
}
function package_binaries {
# Arguments:
# $1 - Path to the directory containing the built binaries
# $2 - Destination path of the packaged binaries
# $3 - Version
#
# Returns:
# 0 - success
# * - error
local sdir="$1"
local ddir="$2"
local vers="$3"
local ret=0
if ! test -d "${sdir}"
then
err "ERROR: '$1' is not a directory. package_binaries must be called with the path to the directory containing the binaries"
return 1
fi
rm -rf "${ddir}" > /dev/null 2>&1
mkdir -p "${ddir}" >/dev/null 2>&1
2018-06-19 16:41:24 +00:00
for platform in $(find "${sdir}" -mindepth 1 -maxdepth 1 -type d )
do
local os_arch=$(basename $platform)
local dest="${ddir}/${CONSUL_PKG_NAME}_${vers}_${os_arch}.zip"
status "Compressing ${os_arch} directory into ${dest}"
pushd "${platform}" > /dev/null
zip "${ddir}/${CONSUL_PKG_NAME}_${vers}_${os_arch}.zip" ./*
ret=$?
popd > /dev/null
if test "$ret" -ne 0
then
break
fi
done
return ${ret}
}
function package_release_one {
# Arguments:
# $1 - Path to the top level Consul source
# $2 - Version to use in the names of the zip files (optional)
# $3 - Subdirectory under pkg/dist to use (optional)
#
# Returns:
# 0 - success
# * - error
if ! test -d "$1"
then
err "ERROR: '$1' is not a directory. package_release must be called with the path to the top level source as the first argument'"
return 1
fi
local sdir="$1"
local ret=0
local vers="$2"
local extra_dir_name="$3"
local extra_dir=""
if test -n "${extra_dir_name}"
then
extra_dir="${extra_dir_name}/"
fi
if test -z "${vers}"
then
vers=$(get_version "${sdir}" true false)
ret=$?
if test "$ret" -ne 0
then
err "ERROR: failed to determine the version."
return $ret
fi
fi
package_binaries "${sdir}/pkg/bin/${extra_dir}" "${sdir}/pkg/dist/${extra_dir}" "${vers}"
return $?
}
function package_release {
# Arguments:
# $1 - Path to the top level Consul source
# $2 - Version to use in the names of the zip files (optional)
#
# Returns:
# 0 - success
# * - error
package_release_one "$1" "$2" ""
return $?
}
function shasum_release {
# Arguments:
# $1 - Path to the dist directory
# $2 - Version of the release
#
# Returns:
# 0 - success
# * - failure
local sdir="$1"
local vers="$2"
if ! test -d "$1"
then
err "ERROR: sign_release requires a path to the dist dir as the first argument"
return 1
fi
if test -z "${vers}"
then
err "ERROR: sign_release requires a version to be specified as the second argument"
return 1
fi
local hfile="${CONSUL_PKG_NAME}_${vers}_SHA256SUMS"
shasum_directory "${sdir}" "${sdir}/${hfile}"
return $?
}
function sign_release {
# Arguments:
# $1 - Path to distribution directory
# $2 - Version
# $2 - Alternative GPG key to use for signing
#
# Returns:
# 0 - success
# * - failure
local sdir="$1"
local vers="$2"
if ! test -d "${sdir}"
then
err "ERROR: sign_release requires a path to the dist dir as the first argument"
return 1
fi
if test -z "${vers}"
then
err "ERROR: sign_release requires a version to be specified as the second argument"
return 1
fi
local hfile="${CONSUL_PKG_NAME}_${vers}_SHA256SUMS"
status_stage "==> Signing ${hfile}"
gpg_detach_sign "${1}/${hfile}" "$3" || return 1
return 0
}
function check_release_one {
# Arguments:
# $1 - Path to the release files
# $2 - Version to expect
# $3 - boolean whether to expect the signature file
# $4 - Release Name (optional)
#
# Returns:
# 0 - success
# * - failure
declare -i ret=0
declare -a expected_files
declare log_extra=""
if test -n "$4"
then
log_extra="for $4 "
fi
expected_files+=("${CONSUL_PKG_NAME}_${2}_SHA256SUMS")
echo "check sig: $3"
if is_set "$3"
then
expected_files+=("${CONSUL_PKG_NAME}_${2}_SHA256SUMS.sig")
fi
expected_files+=("${CONSUL_PKG_NAME}_${2}_darwin_386.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_darwin_amd64.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_freebsd_386.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_freebsd_amd64.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_386.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_amd64.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_arm.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_arm64.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_solaris_amd64.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_windows_386.zip")
expected_files+=("${CONSUL_PKG_NAME}_${2}_windows_amd64.zip")
declare -a found_files
status_stage "==> Verifying release contents ${log_extra}- ${2}"
debug "Expecting Files:"
for fname in "${expected_files[@]}"
do
debug " $fname"
done
pushd "$1" > /dev/null
for actual_fname in $(ls)
do
local found=0
for i in "${!expected_files[@]}"
do
local expected_fname="${expected_files[i]}"
if test "${expected_fname}" == "${actual_fname}"
then
# remove from the expected_files array
unset 'expected_files[i]'
# append to the list of found files
found_files+=("${expected_fname}")
# mark it as found so we dont error
found=1
break
fi
done
if test $found -ne 1
then
err "ERROR: Release build has an extra file: ${actual_fname}"
ret=1
fi
done
for fname in "${expected_files[@]}"
do
err "ERROR: Release build is missing a file: $fname"
ret=1
done
if test $ret -eq 0
then
if ! shasum -c -s "${CONSUL_PKG_NAME}_${2}_SHA256SUMS"
then
err "ERROR: Failed SHA-256 hash verification"
shasum -c "${CONSUL_PKG_NAME}_${2}_SHA256SUMS"
ret=1
fi
fi
if test $ret -eq 0 && is_set "${3}"
then
if ! gpg --verify "${CONSUL_PKG_NAME}_${2}_SHA256SUMS.sig" "${CONSUL_PKG_NAME}_${2}_SHA256SUMS" > /dev/null 2>&1
then
err "ERROR: Failed GPG verification of SHA256SUMS signature"
ret=1
fi
fi
if test $ret -eq 0
then
status "Release build contents:"
for fname in "${found_files[@]}"
do
echo " $fname"
done
fi
popd > /dev/null
return $ret
}
function check_release {
# Arguments:
# $1 - Path to the release files
# $2 - Version to expect
# $3 - boolean whether to expect the signature file
#
# Returns:
# 0 - success
# * - failure
check_release_one "$1" "$2" "$3"
return ${ret}
}
function build_consul_release {
build_consul "$1" "" "$2"
}
function build_release {
# Arguments: (yeah there are lots)
# $1 - Path to the top level Consul source
# $2 - boolean whether to tag the release yet
# $3 - boolean whether to build the binaries
# $4 - boolean whether to generate the sha256 sums
# $5 - version to set within version.go and the changelog
# $6 - release date to set within the changelog
# $7 - release version to set
# $8 - alternative gpg key to use for signing operations (optional)
#
# Returns:
# 0 - success
# * - error
debug "Source Dir: $1"
debug "Tag Release: $2"
debug "Build Release: $3"
debug "Sign Release: $4"
debug "Version: $5"
debug "Release Date: $6"
debug "Release Vers: $7"
debug "GPG Key: $8"
if ! test -d "$1"
then
err "ERROR: '$1' is not a directory. build_release must be called with the path to the top level source as the first argument'"
return 1
fi
if test -z "$2" -o -z "$3" -o -z "$4"
then
err "ERROR: build_release requires 4 arguments to be specified: <path to consul source> <tag release bool?> <build binaries bool?> <shasum 256 bool?>"
return 1
fi
local sdir="$1"
local do_tag="$2"
local do_build="$3"
local do_sha256="$4"
local gpg_key="$8"
if test -z "${gpg_key}"
then
gpg_key=${HASHICORP_GPG_KEY}
fi
if ! is_set "${RELEASE_UNSIGNED}"
then
if ! have_gpg_key "${gpg_key}"
then
err "ERROR: Aborting build because no useable GPG key is present. Set RELEASE_UNSIGNED=1 to bypass this check"
return 1
fi
fi
if ! is_git_clean "${sdir}" true && ! is_set "${ALLOW_DIRTY_GIT}"
then
err "ERROR: Refusing to build because Git is dirty. Set ALLOW_DIRTY_GIT=1 in the environment to proceed anyways"
return 1
fi
local set_vers="$5"
local set_date="$6"
local set_release="$7"
if test -z "${set_vers}"
then
set_vers=$(get_version "${sdir}" false false)
set_release=$(parse_version "${sdir}" true false true)
fi
if is_set "${do_tag}" && ! set_release_mode "${sdir}" "${set_vers}" "${set_date}" "${set_release}"
then
err "ERROR: Failed to put source into release mode"
return 1
fi
local vers="$(get_version ${sdir} true false)"
if test $? -ne 0
then
err "Please specify a version (couldn't find one based on build tags)."
return 1
fi
# Make sure we arent in dev mode
unset CONSUL_DEV
if is_set "${do_build}"
then
status_stage "==> Refreshing Docker Build Images"
refresh_docker_images "${sdir}"
if test $? -ne 0
then
err "ERROR: Failed to refresh docker images"
return 1
fi
status_stage "==> Building UI for version ${vers}"
# passing the version to override the version determined via tags
build_ui "${sdir}" "${UI_BUILD_TAG}" "${vers}"
if test $? -ne 0
then
err "ERROR: Failed to build the ui"
return 1
fi
if is_set "${do_tag}"
then
git add "${sdir}/agent/uiserver/dist"
if test $? -ne 0
then
err "ERROR: Failed to git add /agent/uiserver/dist directory"
return 1
fi
fi
status "UI Built with Version: $(ui_version "${sdir}/agent/uiserver/dist/index.html")"
fi
if is_set "${do_tag}"
then
status_stage "==> Tagging version ${vers}"
tag_release "${sdir}" "${vers}" "${gpg_key}"
if test $? -ne 0
then
err "ERROR: Failed to tag the release"
return 1
fi
update_git_env "${sdir}"
fi
if is_set "${do_build}"
then
status_stage "==> Building Consul for version ${vers}"
build_consul_release "${sdir}" "${GO_BUILD_TAG}"
if test $? -ne 0
then
err "ERROR: Failed to build the Consul binaries"
return 1
fi
status_stage "==> Packaging up release binaries"
package_release "${sdir}" "${vers}"
if test $? -ne 0
then
err "ERROR: Failed to package the release binaries"
return 1
fi
fi
status_stage "==> Generating SHA 256 Hashes for Binaries"
shasum_release "${sdir}/pkg/dist" "${vers}"
if test $? -ne 0
then
err "ERROR: Failed to generate SHA 256 hashes for the release"
return 1
fi
if is_set "${do_sha256}"
then
sign_release "${sdir}/pkg/dist" "${vers}" "${gpg_key}"
if test $? -ne 0
then
err "ERROR: Failed to sign the SHA 256 hashes file"
return 1
fi
fi
check_release "${sdir}/pkg/dist" "${vers}" "${do_sha256}"
return $?
}