#!/usr/bin/env bash # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 set -uo pipefail CHANGIE_VERSION="${CHANGIE_VERSION:-1.21.0}" SEMVER_VERSION="${SEMVER_VERSION:-7.6.3}" function usage { cat <<-'EOF' Usage: ./changelog.sh [] Description: This script will update CHANGELOG.md with the given version and date and add the changelog entries. It will also set the version/VERSION file to the correct version. In general this script should handle most release related tasks within this repository. Commands: generate generate will create a new section in the CHANGELOG.md file for the given release type. The release type should be one of "dev", "alpha", "rc", "release", or "patch". `dev`: will update the changelog with the latest unreleased changes. `alpha`: will generate a new section with an alpha version for today. `beta`: will generate a new beta release. `rc`: will generate a new rc release. `release`: will make the initial minor release for this branch. `patch`: will generate a new patch release nextminor: Run on main branch: Updates the minor version. listIssuesInRelease: Lists all issues in the release passed as an argument. EOF } function generate { RELEASE_TYPE="${1:-}" if [[ -z "$RELEASE_TYPE" ]]; then echo "missing argument" usage exit 1 fi FOOTER_FILE='footer.md' case "$RELEASE_TYPE" in dev) FOOTER_FILE='footer-with-experiments.md' LATEST_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) # Check if we already released this version already if git tag -l "v$LATEST_VERSION" | grep -q "v$LATEST_VERSION"; then LATEST_VERSION=$(npx -y semver@$SEMVER_VERSION -i patch $LATEST_VERSION) fi COMPLETE_VERSION="$LATEST_VERSION-dev" npx -y changie@$CHANGIE_VERSION merge -u "## $LATEST_VERSION (Unreleased)" # If we have no changes yet, the changelog is empty now, so we need to add a header if ! grep -q "## $LATEST_VERSION" CHANGELOG.md; then CURRENT_CHANGELOG=$(cat CHANGELOG.md) echo "## $LATEST_VERSION (Unreleased)" > CHANGELOG.md echo "" >> CHANGELOG.md echo "$CURRENT_CHANGELOG" >> CHANGELOG.md fi ;; alpha) FOOTER_FILE='footer-with-experiments.md' PRERELEASE_VERSION=$(date +"alpha%Y%m%d") LATEST_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) HUMAN_DATE=$(date +"%B %d, %Y") # Date in Janurary 1st, 2022 format COMPLETE_VERSION="$LATEST_VERSION-$PRERELEASE_VERSION" npx -y changie@$CHANGIE_VERSION merge -u "## $COMPLETE_VERSION ($HUMAN_DATE)" # If we have no changes yet, the changelog is empty now, so we need to add a header if ! grep -q "$COMPLETE_VERSION" CHANGELOG.md; then CURRENT_CHANGELOG=$(cat CHANGELOG.md) echo "## $COMPLETE_VERSION ($HUMAN_DATE)" > CHANGELOG.md echo "" >> CHANGELOG.md echo "$CURRENT_CHANGELOG" >> CHANGELOG.md fi ;; beta) LATEST_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) # We need to check if this is the first RC of the version BETA_NUMBER=$(git tag -l "v$LATEST_VERSION-beta*" | wc -l) BETA_NUMBER=$((BETA_NUMBER + 1)) HUMAN_DATE=$(date +"%B %d, %Y") # Date in Janurary 1st, 2022 format COMPLETE_VERSION="$LATEST_VERSION-beta$BETA_NUMBER" npx -y changie@$CHANGIE_VERSION merge -u "## $COMPLETE_VERSION ($HUMAN_DATE)" ;; rc) LATEST_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) # We need to check if this is the first RC of the version RC_NUMBER=$(git tag -l "v$LATEST_VERSION-rc*" | wc -l) RC_NUMBER=$((RC_NUMBER + 1)) HUMAN_DATE=$(date +"%B %d, %Y") # Date in Janurary 1st, 2022 format COMPLETE_VERSION="$LATEST_VERSION-rc$RC_NUMBER" npx -y changie@$CHANGIE_VERSION merge -u "## $COMPLETE_VERSION ($HUMAN_DATE)" ;; patch) COMPLETE_VERSION=$(npx -y changie@$CHANGIE_VERSION next patch) npx -y changie@$CHANGIE_VERSION batch patch npx -y changie@$CHANGIE_VERSION merge ;; release) # This is the first release of the branch, releasing the new minor version COMPLETE_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) # We currently keep a file that looks like this release to ensure the alphas and dev versions are generated correctly rm ./.changes/$COMPLETE_VERSION.md npx -y changie@$CHANGIE_VERSION batch $COMPLETE_VERSION npx -y changie@$CHANGIE_VERSION merge ;; *) echo "invalid argument" usage exit 1 ;; esac # Set version/VERSION to the to be released version echo "$COMPLETE_VERSION" > version/VERSION # Add footer to the changelog cat ./.changes/$FOOTER_FILE >> CHANGELOG.md echo "" >> CHANGELOG.md cat ./.changes/previous-releases.md >> CHANGELOG.md } # This function expects the current branch to be main. Run it if you want to set main to the next # minor version. function nextminor { # Prepend the latest version to the previous releases LATEST_VERSION=$(npx -y changie@$CHANGIE_VERSION latest -r --skip-prereleases) LATEST_VERSION=${LATEST_VERSION%.*} # Remove the patch version CURRENT_FILE_CONTENT=$(cat ./.changes/previous-releases.md) echo "- [v$LATEST_VERSION](https://github.com/hashicorp/terraform/blob/v$LATEST_VERSION/CHANGELOG.md)" > ./.changes/previous-releases.md echo "$CURRENT_FILE_CONTENT" >> ./.changes/previous-releases.md NEXT_VERSION=$(npx -y changie@$CHANGIE_VERSION next minor) # Remove all existing per-release changelogs rm ./.changes/*.*.*.md # Remove all old changelog entries rm ./.changes/v*/*.yaml # Create a new empty version file for the next minor version touch ./.changes/$NEXT_VERSION.md LATEST_MAJOR_MINOR=$(echo $LATEST_VERSION | awk -F. '{print $1"."$2}') NEXT_MAJOR_MINOR=$(echo $NEXT_VERSION | awk -F. '{print $1"."$2}') # Create a new changes directory for the next minor version mkdir ./.changes/v$NEXT_MAJOR_MINOR touch ./.changes/v$NEXT_MAJOR_MINOR/.gitkeep # Set changies changes dir to the new version awk "{sub(/unreleasedDir: v$LATEST_MAJOR_MINOR/, \"unreleasedDir: v$NEXT_MAJOR_MINOR\")}1" ./.changie.yaml > temp && mv temp ./.changie.yaml generate "dev" } function listIssuesInRelease() { RELEASE_MAJOR_MINOR="${1:-}" if [ -z "$RELEASE_MAJOR_MINOR" ]; then echo "No release version specified" exit 1 fi # Check if yq is installed if ! command -v yq &> /dev/null; then echo "yq could not be found" exit 1 fi echo "Listing issues in release $RELEASE_MAJOR_MINOR" # Loop through files in .changes/v$RELEASE_MAJOR_MINOR for file in ./.changes/v$RELEASE_MAJOR_MINOR/*.yaml; do ISSUE=$(cat "$file" | yq '.custom.Issue') echo "- https://github.com/hashicorp/terraform/issues/$ISSUE" done } function main { case "$1" in generate) generate "${@:2}" ;; nextminor) nextminor "${@:2}" ;; listIssuesInRelease) listIssuesInRelease "${@:2}" ;; *) usage exit 1 ;; esac } main "$@" exit $?