From ed94e69e8f9f952c900119c667555dfb89547326 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 12:59:45 +0000 Subject: [PATCH 01/12] ci: Do release tagging in CI and add --draft support --- .github/workflows/release.yaml | 42 +++++++- scripts/release.sh | 83 +++++++++------ scripts/release/generate_release_notes.sh | 6 +- scripts/release/increment_version_tag.sh | 117 ++++++++++++++++++++++ scripts/release/publish.sh | 40 ++++---- 5 files changed, 233 insertions(+), 55 deletions(-) create mode 100755 scripts/release/increment_version_tag.sh diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3b5c1638d..4880d5dc0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,11 +1,21 @@ # GitHub release workflow. -name: release +name: New Release on: - push: - tags: - - "v*" workflow_dispatch: inputs: + increment: + description: Preferred version increment (release script may promote e.g. patch to minor depending on changes). + type: choice + required: true + default: patch + options: + - patch + - minor + - major + draft: + description: Create a draft release (for manually editing release notes before publishing). + type: boolean + required: true snapshot: description: Force a dev version to be generated, implies dry_run. type: boolean @@ -100,6 +110,27 @@ jobs: AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }} AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }} + - name: Create release tag and release notes + run: | + ref=HEAD + old_version="$(git describe --abbrev=0 "$ref^1")" + + # Cache commit metadata. + . ./scripts/release/check_commit_metadata.sh "$old_version" "$ref" + + # Create new release tag. + version="$( + ./scripts/release/increment_version_tag.sh \ + ${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \ + --ref "$ref" \ + ${{ github.event.inputs.increment }} + )" + + # Generate notes. + echo 'CODER_RELEASE_NOTES<> $GITHUB_ENV + ./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref" + echo 'RN_EOF' >> $GITHUB_ENV + - name: Build binaries run: | set -euo pipefail @@ -158,7 +189,9 @@ jobs: - name: Publish release run: | ./scripts/release/publish.sh \ + ${{ github.event.inputs.draft && '--draft' }} \ ${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \ + --release-notes "$CODER_RELEASE_NOTES" \ ./build/*_installer.exe \ ./build/*.zip \ ./build/*.tar.gz \ @@ -195,6 +228,7 @@ jobs: with: name: release-artifacts path: | + ./build/*_installer.exe ./build/*.zip ./build/*.tar.gz ./build/*.tgz diff --git a/scripts/release.sh b/scripts/release.sh index 83c1ea01f..68e2c7822 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -12,33 +12,49 @@ # be tagged at, otherwise the latest commit will be used. # # Set --minor to force a minor version bump, even when there are no breaking -# changes. +# changes. Likewise for --major. By default a patch version will be created. +# +# Set --dry-run to run the release workflow in CI as a dry-run (no release will +# be created). # # To mark a release as containing breaking changes, the commit title should # either contain a known prefix with an exclamation mark ("feat!:", # "feat(api)!:") or the PR that was merged can be tagged with the # "release/breaking" label. # -# Usage: ./release.sh [--ref ] [--minor] +# Usage: ./release.sh [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" cdroot +draft=0 +dry_run=0 ref= -minor=0 +increment= -args="$(getopt -o n -l ref:,minor -- "$@")" +args="$(getopt -o n -l draft,dry-run,ref:,major,minor,patch -- "$@")" eval set -- "$args" while true; do case "$1" in + --draft) + draft=1 + shift + ;; + --dry-run) + dry_run=1 + shift + ;; --ref) ref="$2" shift 2 ;; - --minor) - minor=1 + --major | --minor | --patch) + if [[ -n $increment ]]; then + error "Cannot specify multiple version increments." + fi + increment=${1#--} shift ;; --) @@ -54,6 +70,11 @@ done # Check dependencies. dependencies gh sort +if [[ -z $increment ]]; then + # Default to patch versions. + increment="patch" +fi + # Make sure the repository is up-to-date before generating release notes. log "Fetching main and tags from origin..." git fetch --quiet --tags origin main @@ -75,24 +96,7 @@ log "Checking commit metadata for changes since $old_version..." # shellcheck source=scripts/release/check_commit_metadata.sh source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref" -mapfile -d . -t version_parts <<<"$old_version" -if [[ $minor == 1 ]] || [[ $COMMIT_METADATA_BREAKING == 1 ]]; then - if [[ $COMMIT_METADATA_BREAKING == 1 ]]; then - log "Breaking change detected, incrementing minor version..." - else - log "Forcing minor version bump..." - fi - version_parts[1]=$((version_parts[1] + 1)) - version_parts[2]=0 -else - log "No breaking changes detected, incrementing patch version..." - version_parts[2]=$((version_parts[2] + 1)) -fi -new_version="${version_parts[0]}.${version_parts[1]}.${version_parts[2]}" - -log "Old version: ${old_version}" -log "New version: ${new_version}" - +new_version="$(execrelative ./release/increment_version_tag.sh --dry-run --ref "$ref" --"$increment")" release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_version" --new-version "$new_version" --ref "$ref")" echo @@ -102,11 +106,30 @@ if [[ $show_reply =~ ^[Yy]$ ]]; then echo -e "$release_notes\n" fi -read -p "Create release? (y/n) " -n 1 -r create +create_message="Create release" +if ((draft)); then + create_message="Create draft release" +fi +if ((dry_run)); then + create_message+=" (DRYRUN)" +fi +read -p "$create_message? (y/n) " -n 1 -r create echo -if [[ $create =~ ^[Yy]$ ]]; then - log "Tagging commit $ref as $new_version..." - git tag -a "$new_version" -m "$new_version" "$ref" - log "Pushing tag to origin..." - git push -u origin "$new_version" +if ! [[ $create =~ ^[Yy]$ ]]; then + exit 0 +fi + +args=() +if ((draft)); then + args+=(-F draft=true) +fi +if ((dry_run)); then + args+=(-F dry_run=true) fi + +gh workflow run release.yaml \ + --ref main \ + -F increment="$increment" \ + "${args[@]}" + +log "Release process started, you can watch the release via: gh run watch --exit-status " diff --git a/scripts/release/generate_release_notes.sh b/scripts/release/generate_release_notes.sh index df6cfd98b..56e1508ac 100755 --- a/scripts/release/generate_release_notes.sh +++ b/scripts/release/generate_release_notes.sh @@ -59,10 +59,10 @@ if [[ -z $ref ]]; then fi # shellcheck source=scripts/release/check_commit_metadata.sh -source "$SCRIPT_DIR/release/check_commit_metadata.sh" "${old_version}" "${ref}" +source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref" # Sort commits by title prefix, then by date, only return sha at the end. -mapfile -t commits < <(git log --no-merges --pretty=format:"%ct %h %s" "${old_version}..${ref}" | sort -k3,3 -k1,1n | cut -d' ' -f2) +mapfile -t commits < <(git log --no-merges --pretty=format:"%ct %h %s" "$old_version..$ref" | sort -k3,3 -k1,1n | cut -d' ' -f2) # From: https://github.com/commitizen/conventional-commit-types # NOTE(mafredri): These need to be supported in check_commit_metadata.sh as well. @@ -140,7 +140,7 @@ image_tag="$(execrelative ./image_tag.sh --version "$new_version")" echo -e "## Changelog $changelog -Compare: [\`${old_version}...${new_version}\`](https://github.com/coder/coder/compare/${old_version}...${new_version}) +Compare: [\`$old_version...$new_version\`](https://github.com/coder/coder/compare/$old_version...$new_version) ## Container Image diff --git a/scripts/release/increment_version_tag.sh b/scripts/release/increment_version_tag.sh new file mode 100755 index 000000000..81cdec909 --- /dev/null +++ b/scripts/release/increment_version_tag.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +# This script should be called to tag a new release. It will take the suggested +# increment (major, minor, patch) and optionally promote e.g. patch -> minor if +# there are breaking changes between the previous version and the given --ref +# (or HEAD). +# +# Usage: ./increment_version_tag.sh [--dry-run] [--ref ] <--major | --minor | --patch> +# +# This script will create a git tag, so it should only be run in CI (or via +# --dry-run). + +set -euo pipefail +# shellcheck source=scripts/lib.sh +source "$(dirname "$(dirname "${BASH_SOURCE[0]}")")/lib.sh" +cdroot + +dry_run=0 +ref=HEAD +increment= + +args="$(getopt -o n -l dry-run,ref:,major,minor,patch -- "$@")" +eval set -- "$args" +while true; do + case "$1" in + --dry-run) + dry_run=1 + shift + ;; + --ref) + ref="$2" + shift 2 + ;; + --major | --minor | --patch) + if [[ -n $increment ]]; then + error "Cannot specify multiple version increments." + fi + increment=${1#--} + shift + ;; + --) + shift + break + ;; + *) + error "Unrecognized option: $1" + ;; + esac +done + +# Check dependencies. +dependencies git + +if [[ -z $increment ]]; then + error "No version increment provided." +fi + +if [[ $dry_run != 1 ]] && [[ ${CI:-} == "" ]]; then + error "This script must be run in CI or with --dry-run." +fi + +old_version="$(git describe --abbrev=0 "$ref^1")" +cur_tag="$(git describe --abbrev=0 "$ref")" +if [[ $old_version != "$cur_tag" ]]; then + if ! ((dry_run)); then + error "Ref \"$ref\" is already tagged with a release ($cur_tag)." + fi + echo "$new_version" + +fi +ref=$(git rev-parse --short "$ref") + +log "Checking commit metadata for changes since $old_version..." +# shellcheck source=scripts/release/check_commit_metadata.sh +source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref" + +if ((COMMIT_METADATA_BREAKING == 1)); then + prev_increment=$increment + if [[ $increment == patch ]]; then + increment=minor + fi + if [[ $prev_increment != "$increment" ]]; then + log "Breaking change detected, changing version increment from \"$prev_increment\" to \"$increment\"." + else + log "Breaking change detected, provided increment is sufficient, using \"$increment\" increment." + fi +else + log "No breaking changes detected, using \"$increment\" increment." +fi + +mapfile -d . -t version_parts <<<"${old_version#v}" +case "$increment" in +patch) + version_parts[2]=$((version_parts[2] + 1)) + ;; +minor) + version_parts[1]=$((version_parts[1] + 1)) + version_parts[2]=0 + ;; +major) + version_parts[0]=$((version_parts[0] + 1)) + version_parts[1]=0 + version_parts[2]=0 + ;; +*) + error "Unrecognized version increment." + ;; +esac + +new_version="v${version_parts[0]}.${version_parts[1]}.${version_parts[2]}" + +log "Old version: $old_version" +log "New version: $new_version" +maybedryrun "$dry_run" git tag -a "$new_version" -m "Release $new_version" "$ref" +maybedryrun "$dry_run" git push --quiet origin "$new_version" + +echo "$new_version" diff --git a/scripts/release/publish.sh b/scripts/release/publish.sh index 8b592212b..863dc07e3 100755 --- a/scripts/release/publish.sh +++ b/scripts/release/publish.sh @@ -34,9 +34,11 @@ if [[ "${CI:-}" == "" ]]; then fi version="" +release_notes="" +draft=0 dry_run=0 -args="$(getopt -o "" -l version:,dry-run -- "$@")" +args="$(getopt -o "" -l version:,release-notes:,draft,dry-run -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -44,6 +46,14 @@ while true; do version="$2" shift 2 ;; + --release-notes) + release_notes="$2" + shift 2 + ;; + --draft) + draft=1 + shift + ;; --dry-run) dry_run=1 shift @@ -67,6 +77,10 @@ if [[ "$version" == "" ]]; then version="$(execrelative ./version.sh)" fi +if [[ -z $release_notes ]]; then + error "No release notes specified, use --release-notes." +fi + # realpath-ify all input files so we can cdroot below. files=() for f in "$@"; do @@ -96,22 +110,6 @@ if [[ "$(git describe --always)" != "$new_tag" ]]; then log "The provided version does not match the current git tag, but --dry-run was supplied so continuing..." fi -# This returns the tag before the current tag. -old_tag="$(git describe --abbrev=0 HEAD^1)" - -# For dry-run builds we want to use the SHA instead of the tag, because the new -# tag probably doesn't exist. -new_ref="$new_tag" -if [[ "$dry_run" == 1 ]]; then - new_ref="$(git rev-parse --short HEAD)" -fi - -# shellcheck source=scripts/release/check_commit_metadata.sh -source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_tag" "$new_ref" - -# Craft the release notes. -release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_tag" --new-version "$new_tag" --ref "$new_ref")" - release_notes_file="$(mktemp)" echo "$release_notes" >"$release_notes_file" @@ -127,7 +125,7 @@ pushd "$temp_dir" sha256sum ./* | sed -e 's/\.\///' - >"coder_${version}_checksums.txt" popd -log "--- Creating release $new_tag" +log "--- Publishing release $new_tag on GitHub" log log "Description:" echo "$release_notes" | sed -e 's/^/\t/' - 1>&2 @@ -139,11 +137,17 @@ popd log log +args=() +if ((draft)); then + args+=(--draft) +fi + # We pipe `true` into `gh` so that it never tries to be interactive. true | maybedryrun "$dry_run" gh release create \ --title "$new_tag" \ --notes-file "$release_notes_file" \ + "${args[@]}" \ "$new_tag" \ "$temp_dir"/* From d52c6393e8104ae69c9cf8b8306d2752a15c1548 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 13:33:51 +0000 Subject: [PATCH 02/12] Ignore metadata to test workflow --- .github/workflows/release.yaml | 6 ++++++ scripts/release/check_commit_metadata.sh | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4880d5dc0..b75ba5545 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -35,6 +35,7 @@ permissions: env: CODER_RELEASE: ${{ github.event.inputs.snapshot && 'false' || 'true' }} + DRY_RUN: ${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && 'true' || 'false' }} jobs: release: @@ -115,6 +116,11 @@ jobs: ref=HEAD old_version="$(git describe --abbrev=0 "$ref^1")" + if [[ $DRY_RUN == true ]]; then + # Allow dry-run of branches to pass. + export CODER_IGNORE_MISSING_COMMIT_METADATA=1 + fi + # Cache commit metadata. . ./scripts/release/check_commit_metadata.sh "$old_version" "$ref" diff --git a/scripts/release/check_commit_metadata.sh b/scripts/release/check_commit_metadata.sh index 76e781dd2..44fc4b6dd 100755 --- a/scripts/release/check_commit_metadata.sh +++ b/scripts/release/check_commit_metadata.sh @@ -26,6 +26,11 @@ if [[ -z $to_ref ]]; then error "No to_ref specified" fi +ignore_missing_metadata=${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} +if [[ $ignore_missing_metadata == 1 ]]; then + log "WARNING: Ignoring missing commit metadata, breaking changes may be missed." +fi + range="$from_ref..$to_ref" # Check dependencies. @@ -87,9 +92,11 @@ main() { commit_sha_long=${parts[1]} commit_prefix=${parts[2]} - # Safety-check, guarantee all commits had their metadata fetched. - if [[ ! -v labels[$commit_sha_long] ]]; then - error "Metadata missing for commit $commit_sha_short" + if [[ $ignore_missing_metadata != 1 ]]; then + # Safety-check, guarantee all commits had their metadata fetched. + if [[ ! -v labels[$commit_sha_long] ]]; then + error "Metadata missing for commit $commit_sha_short" + fi fi # Store the commit title for later use. @@ -99,11 +106,11 @@ main() { # First, check the title for breaking changes. This avoids doing a # GH API request if there's a match. - if [[ $commit_prefix =~ $breaking_title ]] || [[ ${labels[$commit_sha_long]} = *"label:$breaking_label"* ]]; then + if [[ $commit_prefix =~ $breaking_title ]] || [[ ${labels[$commit_sha_long]:-} = *"label:$breaking_label"* ]]; then COMMIT_METADATA_CATEGORY[$commit_sha_short]=$breaking_category COMMIT_METADATA_BREAKING=1 continue - elif [[ ${labels[$commit_sha_long]} = *"label:$security_label"* ]]; then + elif [[ ${labels[$commit_sha_long]:-} = *"label:$security_label"* ]]; then COMMIT_METADATA_CATEGORY[$commit_sha_short]=$security_label continue fi From 42b612a7c19d2cdf9fb1826a21d60e294149d54c Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 14:49:09 +0000 Subject: [PATCH 03/12] fixup! ci: Do release tagging in CI and add --draft support --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b75ba5545..42811a0a6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -129,7 +129,7 @@ jobs: ./scripts/release/increment_version_tag.sh \ ${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \ --ref "$ref" \ - ${{ github.event.inputs.increment }} + --${{ github.event.inputs.increment }} )" # Generate notes. From 76d792746ecf5b50c0372a58e8f5d4586cd7d16f Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 15:07:38 +0000 Subject: [PATCH 04/12] fixup! ci: Do release tagging in CI and add --draft support --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 42811a0a6..d594feade 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -134,7 +134,7 @@ jobs: # Generate notes. echo 'CODER_RELEASE_NOTES<> $GITHUB_ENV - ./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref" + ./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref" | tee -a $GITHUB_ENV echo 'RN_EOF' >> $GITHUB_ENV - name: Build binaries From 2048a815f69c5b49b2bac12b781388729e587891 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 15:23:01 +0000 Subject: [PATCH 05/12] fixup! ci: Do release tagging in CI and add --draft support --- .github/workflows/release.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d594feade..9cae92750 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -133,10 +133,14 @@ jobs: )" # Generate notes. + release_notes="$(./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref")" echo 'CODER_RELEASE_NOTES<> $GITHUB_ENV - ./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref" | tee -a $GITHUB_ENV + echo "$release_notes" >> $GITHUB_ENV echo 'RN_EOF' >> $GITHUB_ENV + - name: Echo release notes + run: echo "$CODER_RELEASE_NOTES" + - name: Build binaries run: | set -euo pipefail From 277dc0c6e838476b8c06a7ee8897bc5bffb852e0 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 15:38:44 +0000 Subject: [PATCH 06/12] fixup! ci: Do release tagging in CI and add --draft support --- scripts/release.sh | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 68e2c7822..2cef87ab9 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -22,22 +22,34 @@ # "feat(api)!:") or the PR that was merged can be tagged with the # "release/breaking" label. # -# Usage: ./release.sh [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] +# To test changes to this script, you can set `--branch `, which will +# run the release workflow in CI as a dry-run and use the latest commit on the +# specified branch as the release commit. This will also set --dry-run. +# +# Usage: ./release.sh [--branch ] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" cdroot +branch=main draft=0 dry_run=0 ref= increment= -args="$(getopt -o n -l draft,dry-run,ref:,major,minor,patch -- "$@")" +args="$(getopt -o n -l branch:,draft,dry-run,ref:,major,minor,patch -- "$@")" eval set -- "$args" while true; do case "$1" in + --branch) + branch="$2" + log "Using branch $branch, implies DRYRUN and CODER_IGNORE_MISSING_COMMIT_METADATA." + dry_run=1 + export CODER_IGNORE_MISSING_COMMIT_METADATA=1 + shift 2 + ;; --draft) draft=1 shift @@ -77,13 +89,13 @@ fi # Make sure the repository is up-to-date before generating release notes. log "Fetching main and tags from origin..." -git fetch --quiet --tags origin main +git fetch --quiet --tags origin "$branch" # Resolve to the latest ref on origin/main unless otherwise specified. -ref=$(git rev-parse --short "${ref:-origin/main}") +ref=$(git rev-parse --short "${ref:-origin/$branch}") # Make sure that we're running the latest release script. -if [[ -n $(git diff --name-status origin/main -- ./scripts/release.sh) ]]; then +if [[ -n $(git diff --name-status origin/"$branch" -- ./scripts/release.sh) ]]; then error "Release script is out-of-date. Please check out the latest version and try again." fi @@ -128,8 +140,9 @@ if ((dry_run)); then fi gh workflow run release.yaml \ - --ref main \ + --ref "$branch" \ -F increment="$increment" \ + -F snapshot=false \ "${args[@]}" log "Release process started, you can watch the release via: gh run watch --exit-status " From ff61eb209f6fd6b762cb07bb8bab3ed51582c656 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 15:40:30 +0000 Subject: [PATCH 07/12] fixup! ci: Do release tagging in CI and add --draft support --- scripts/release.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 2cef87ab9..e82c2c814 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -88,7 +88,7 @@ if [[ -z $increment ]]; then fi # Make sure the repository is up-to-date before generating release notes. -log "Fetching main and tags from origin..." +log "Fetching $branch and tags from origin..." git fetch --quiet --tags origin "$branch" # Resolve to the latest ref on origin/main unless otherwise specified. @@ -104,7 +104,6 @@ fi mapfile -t versions < <(gh api -H "Accept: application/vnd.github+json" /repos/coder/coder/git/refs/tags -q '.[].ref | split("/") | .[2]' | grep '^v' | sort -r -V) old_version=${versions[0]} -log "Checking commit metadata for changes since $old_version..." # shellcheck source=scripts/release/check_commit_metadata.sh source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref" From ce869dd67a134d054a9879e54a3be82563bf5c12 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 15:46:34 +0000 Subject: [PATCH 08/12] fixup! ci: Do release tagging in CI and add --draft support --- scripts/release/check_commit_metadata.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/release/check_commit_metadata.sh b/scripts/release/check_commit_metadata.sh index 44fc4b6dd..bfdd3b33b 100755 --- a/scripts/release/check_commit_metadata.sh +++ b/scripts/release/check_commit_metadata.sh @@ -26,11 +26,6 @@ if [[ -z $to_ref ]]; then error "No to_ref specified" fi -ignore_missing_metadata=${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} -if [[ $ignore_missing_metadata == 1 ]]; then - log "WARNING: Ignoring missing commit metadata, breaking changes may be missed." -fi - range="$from_ref..$to_ref" # Check dependencies. @@ -39,6 +34,10 @@ dependencies gh COMMIT_METADATA_BREAKING=0 declare -A COMMIT_METADATA_TITLE COMMIT_METADATA_CATEGORY +# This environment variable can be set to 1 to ignore missing commit metadata, +# useful for dry-runs. +ignore_missing_metadata=${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} + main() { # Match a commit prefix pattern, e.g. feat: or feat(site):. prefix_pattern="^([a-z]+)(\([a-z]*\))?:" @@ -144,6 +143,9 @@ export_commit_metadata() { if [[ ${_COMMIT_METADATA_CACHE:-} == "${range}:"* ]]; then eval "${_COMMIT_METADATA_CACHE#*:}" else + if [[ $ignore_missing_metadata == 1 ]]; then + log "WARNING: Ignoring missing commit metadata, breaking changes may be missed." + fi main fi From 132c70e59dcb1a6d186e71aef1a0ebcce5b6f9be Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 16:01:11 +0000 Subject: [PATCH 09/12] Add -h, --help to release.sh --- scripts/release.sh | 66 +++++++++++++----------- scripts/release/increment_version_tag.sh | 2 +- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index e82c2c814..7ad3be095 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,45 +1,49 @@ #!/usr/bin/env bash -# This script should be called to create a new release. -# -# When run, this script will display the new version number and optionally a -# preview of the release notes. The new version will be selected automatically -# based on if the release contains breaking changes or not. If the release -# contains breaking changes, a new minor version will be created. Otherwise, a -# new patch version will be created. -# -# Set --ref if you need to specify a specific commit that the new version will -# be tagged at, otherwise the latest commit will be used. -# -# Set --minor to force a minor version bump, even when there are no breaking -# changes. Likewise for --major. By default a patch version will be created. -# -# Set --dry-run to run the release workflow in CI as a dry-run (no release will -# be created). -# -# To mark a release as containing breaking changes, the commit title should -# either contain a known prefix with an exclamation mark ("feat!:", -# "feat(api)!:") or the PR that was merged can be tagged with the -# "release/breaking" label. -# -# To test changes to this script, you can set `--branch `, which will -# run the release workflow in CI as a dry-run and use the latest commit on the -# specified branch as the release commit. This will also set --dry-run. -# -# Usage: ./release.sh [--branch ] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] - set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" cdroot +help() { + cat <<-EOH + Usage: ./release.sh [--branch ] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] + + This script should be called to create a new release. + + When run, this script will display the new version number and optionally a + preview of the release notes. The new version will be selected automatically + based on if the release contains breaking changes or not. If the release + contains breaking changes, a new minor version will be created. Otherwise, a + new patch version will be created. + + Set --ref if you need to specify a specific commit that the new version will + be tagged at, otherwise the latest commit will be used. + + Set --minor to force a minor version bump, even when there are no breaking + changes. Likewise for --major. By default a patch version will be created. + + Set --dry-run to run the release workflow in CI as a dry-run (no release will + be created). + + To mark a release as containing breaking changes, the commit title should + either contain a known prefix with an exclamation mark ("feat!:", + "feat(api)!:") or the PR that was merged can be tagged with the + "release/breaking" label. + + To test changes to this script, you can set --branch , which will + run the release workflow in CI as a dry-run and use the latest commit on the + specified branch as the release commit. This will also set --dry-run. + EOH +} + branch=main draft=0 dry_run=0 ref= increment= -args="$(getopt -o n -l branch:,draft,dry-run,ref:,major,minor,patch -- "$@")" +args="$(getopt -o h -l branch:,draft,dry-run,help,ref:,major,minor,patch -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -58,6 +62,10 @@ while true; do dry_run=1 shift ;; + -h | --help) + help + exit 0 + ;; --ref) ref="$2" shift 2 diff --git a/scripts/release/increment_version_tag.sh b/scripts/release/increment_version_tag.sh index 81cdec909..c29f38617 100755 --- a/scripts/release/increment_version_tag.sh +++ b/scripts/release/increment_version_tag.sh @@ -19,7 +19,7 @@ dry_run=0 ref=HEAD increment= -args="$(getopt -o n -l dry-run,ref:,major,minor,patch -- "$@")" +args="$(getopt -o '' -l dry-run,ref:,major,minor,patch -- "$@")" eval set -- "$args" while true; do case "$1" in From aa6526155c2c923aebab723cd5f8c87ce7241b47 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 16:03:22 +0000 Subject: [PATCH 10/12] fixup! Add -h, --help to release.sh --- scripts/release.sh | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 7ad3be095..6f35c3dfa 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -6,35 +6,35 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" cdroot help() { - cat <<-EOH - Usage: ./release.sh [--branch ] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] + cat <] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] - This script should be called to create a new release. +This script should be called to create a new release. - When run, this script will display the new version number and optionally a - preview of the release notes. The new version will be selected automatically - based on if the release contains breaking changes or not. If the release - contains breaking changes, a new minor version will be created. Otherwise, a - new patch version will be created. +When run, this script will display the new version number and optionally a +preview of the release notes. The new version will be selected automatically +based on if the release contains breaking changes or not. If the release +contains breaking changes, a new minor version will be created. Otherwise, a +new patch version will be created. - Set --ref if you need to specify a specific commit that the new version will - be tagged at, otherwise the latest commit will be used. +Set --ref if you need to specify a specific commit that the new version will +be tagged at, otherwise the latest commit will be used. - Set --minor to force a minor version bump, even when there are no breaking - changes. Likewise for --major. By default a patch version will be created. +Set --minor to force a minor version bump, even when there are no breaking +changes. Likewise for --major. By default a patch version will be created. - Set --dry-run to run the release workflow in CI as a dry-run (no release will - be created). +Set --dry-run to run the release workflow in CI as a dry-run (no release will +be created). - To mark a release as containing breaking changes, the commit title should - either contain a known prefix with an exclamation mark ("feat!:", - "feat(api)!:") or the PR that was merged can be tagged with the - "release/breaking" label. +To mark a release as containing breaking changes, the commit title should +either contain a known prefix with an exclamation mark ("feat!:", +"feat(api)!:") or the PR that was merged can be tagged with the +"release/breaking" label. - To test changes to this script, you can set --branch , which will - run the release workflow in CI as a dry-run and use the latest commit on the - specified branch as the release commit. This will also set --dry-run. - EOH +To test changes to this script, you can set --branch , which will +run the release workflow in CI as a dry-run and use the latest commit on the +specified branch as the release commit. This will also set --dry-run. +EOH } branch=main From b8187324f512250f28fd7356b9c6110a2174cb8f Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 16:03:55 +0000 Subject: [PATCH 11/12] fixup! Add -h, --help to release.sh --- scripts/release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 6f35c3dfa..4df75d238 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -5,7 +5,7 @@ set -euo pipefail source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" cdroot -help() { +usage() { cat <] [--draft] [--dry-run] [--ref ] [--major | --minor | --patch] @@ -63,7 +63,7 @@ while true; do shift ;; -h | --help) - help + usage exit 0 ;; --ref) From e110beb582fb702db26273af51a5628a3979bb64 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jan 2023 16:10:01 +0000 Subject: [PATCH 12/12] Add -h, --help to increment_version_tag.sh --- scripts/release/increment_version_tag.sh | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/scripts/release/increment_version_tag.sh b/scripts/release/increment_version_tag.sh index c29f38617..85ac1d14e 100755 --- a/scripts/release/increment_version_tag.sh +++ b/scripts/release/increment_version_tag.sh @@ -1,25 +1,29 @@ #!/usr/bin/env bash -# This script should be called to tag a new release. It will take the suggested -# increment (major, minor, patch) and optionally promote e.g. patch -> minor if -# there are breaking changes between the previous version and the given --ref -# (or HEAD). -# -# Usage: ./increment_version_tag.sh [--dry-run] [--ref ] <--major | --minor | --patch> -# -# This script will create a git tag, so it should only be run in CI (or via -# --dry-run). - set -euo pipefail # shellcheck source=scripts/lib.sh source "$(dirname "$(dirname "${BASH_SOURCE[0]}")")/lib.sh" cdroot +usage() { + cat <] <--major | --minor | --patch> + +This script should be called to tag a new release. It will take the suggested +increment (major, minor, patch) and optionally promote e.g. patch -> minor if +there are breaking changes between the previous version and the given --ref +(or HEAD). + +This script will create a git tag, so it should only be run in CI (or via +--dry-run). +EOH +} + dry_run=0 ref=HEAD increment= -args="$(getopt -o '' -l dry-run,ref:,major,minor,patch -- "$@")" +args="$(getopt -o h -l dry-run,help,ref:,major,minor,patch -- "$@")" eval set -- "$args" while true; do case "$1" in @@ -31,6 +35,10 @@ while true; do ref="$2" shift 2 ;; + -h | --help) + usage + exit 0 + ;; --major | --minor | --patch) if [[ -n $increment ]]; then error "Cannot specify multiple version increments."