opentofu-terraform-provider.../release.sh
2025-11-04 00:41:39 +00:00

159 lines
4.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
#
# #############################################################################
#
# Interactive Release Helper
#
# This script guides you through the pre-release validation steps for
# creating a new release. It ensures that the correct commit is chosen,
# the version is valid, and the target environment is explicitly confirmed.
#
# It is designed to be run manually to provide a series of safety checks
# before a release is formally tagged and deployed.
#
# Prerequisites:
# Set the BOB_GITHUB_TOKEN environment variable.
#
# Usage:
# ./release.sh [BRANCH]
#
# Arguments:
# BRANCH (optional): The branch or Git reference to release from.
# Defaults to 'origin/main' if not specified.
#
# Workflow:
# 1. Fetches the latest state from the 'origin' remote.
# 2. Displays the target commit for final review and asks for confirmation.
# 3. Reads the version number from the 'version/VERSION' file within that commit.
# 4. Constructs a new tag (e.g., v1.2.3) based on the version file.
# 5. Verifies that this tag does not already exist locally or on the remote.
# 6. Asks for final confirmation before proceeding with the release tag.
# 7. Prompts for a target environment (Staging or Production) with an
# extra confirmation step for the production environment.
#
# #############################################################################
set -e
BOB_PRODUCT="terraform-provider-vault"
BOB_ENVIRONMENT="tf-provider-vault"
# SLACK_CHANNEL code is duplicated in ./release/ci.hcl
SLACK_CHANNEL="C09LD1XT5MX"
# BRANCH allow override of default branch with an optional argument
BRANCH="${1:-origin/main}"
# LOCAL_BRANCH bob needs this trimmed
LOCAL_BRANCH="${BRANCH#origin/}"
# VERSION_PATH path to the version file
VERSION_PATH="${BRANCH}:version/VERSION"
YLW=$(tput setaf 3) # yellow
RST=$(tput sgr0) # reset
log_info() {
printf "==> %s\n" "$@"
}
log_warn() {
printf "[!] Warning: %s\n" "$@"
}
log_error() {
printf "[X] Error: %s\n" "$@"
}
prompt() {
printf "[?] %s" "$@ "
}
# fail if this is not set
if [[ -z "$BOB_GITHUB_TOKEN" ]]; then
log_error "BOB_GITHUB_TOKEN is not set"
exit 1
fi
# show the latest commit of BRANCH to user for manual validation
log_info "Fetching default release branch '${BRANCH}'..."
git fetch origin
RELEASE_SHA=$(git rev-parse ${BRANCH})
git log -n 1 ${RELEASE_SHA}
prompt "Do you want to release commit ${YLW}${RELEASE_SHA}${RST}? (y/n): "
read input
if [[ "$input" != "y" ]]; then
echo
exit 0
fi
VERSION=$(git show ${VERSION_PATH})
TAG_NAME="v${VERSION}"
if [[ -z "$VERSION" ]]; then
log_error "No version found at path '${VERSION_PATH}'"
exit 1
fi
log_info "Got version ${YLW}${VERSION}${RST} from ${VERSION_PATH}"
# show last release tag
LATEST_TAG=$(git ls-remote --tags --sort="v:refname" origin | awk -F/ '{print $3}' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | tail -n 1)
log_info "Latest semantic version tag on remote 'origin': ${YLW}${LATEST_TAG}${RST}"
# validate new tag is available
log_info "Fetching latest tags from remote 'origin'..."
git fetch origin --tags
if git rev-parse --verify "refs/tags/${TAG_NAME}" >/dev/null 2>&1; then
log_error "Git tag ${TAG_NAME} already exists"
exit 1
fi
log_info "Git tag ${YLW}${TAG_NAME}${RST} is available"
prompt "Do you want to release tag ${YLW}${TAG_NAME}${RST}? (y/n): "
read input
if [[ "$input" != "y" ]]; then
echo
exit 0
fi
TARGET_ENV=""
while true; do
echo "Promotion environments:"
echo -e " [s] Staging"
echo -e " [p] Production"
prompt "Select release environment (s/p): "
read env_choice
case $env_choice in
s|S )
TARGET_ENV="staging"
break
;;
p|P )
prompt "You are about to deploy to PRODUCTION. Are you sure? (y/n): "
read confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
TARGET_ENV="production"
break
else
log_warn "Production deployment aborted"
# The loop will continue, re-prompting the user.
fi
;;
* )
log_error "Invalid option. Please choose 's' or 'p'. CTRL-C to exit."
# The loop will continue, re-prompting the user.
;;
esac
done
log_info "Targeting deployment to ${YLW}${TARGET_ENV}${RST}..."
set -x
bob trigger-promotion \
--product-name ${BOB_PRODUCT?} \
--org hashicorp \
--repo ${BOB_PRODUCT?} \
--branch ${LOCAL_BRANCH?} \
--product-version ${VERSION?} \
--sha "${RELEASE_SHA?}" \
--environment ${BOB_ENVIRONMENT?} \
--slack-channel ${SLACK_CHANNEL?} \
${TARGET_ENV?}
set +x