Skip to content

feat: Add release.sh script and detect breaking changes #5366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 15, 2022
Prev Previous commit
Next Next commit
Use gh pr list to reduce API requests
  • Loading branch information
mafredri committed Dec 15, 2022
commit c871cb7744212652fb0c16c3ca5b7b46546f02fe
2 changes: 1 addition & 1 deletion scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ 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"
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
Expand Down
82 changes: 58 additions & 24 deletions scripts/release/check_commit_metadata.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env bash

# Usage: source ./check_commit_tags.sh <revision range>
# Usage: ./check_commit_tags.sh <revision range>
# Usage: source ./check_commit_metadata.sh <revision range>
# Usage: ./check_commit_metadata.sh <revision range>
#
# Example: ./check_commit_tags.sh v0.13.1..971e3678
# Example: ./check_commit_metadata.sh v0.13.1..971e3678
#
# When sourced, this script will populate the COMMIT_METADATA_* variables
# with the commit metadata for each commit in the revision range.
Expand All @@ -16,11 +16,17 @@ set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/../lib.sh"

range=${1:-}
from_ref=${1:-}
to_ref=${2:-}

if [[ -z $range ]]; then
error "No revision range specified"
if [[ -z $from_ref ]]; then
error "No from_ref specified"
fi
if [[ -z $from_ref ]]; then
error "No to_ref specified"
fi

range="$from_ref..$to_ref"

# Check dependencies.
dependencies gh
Expand All @@ -39,31 +45,59 @@ main() {
breaking_label=release/breaking
breaking_category=breaking

mapfile -t commits < <(git log --no-merges --pretty=format:"%h %s" "$range")
# Get abbreviated and full commit hashes and titles for each commit.
mapfile -t commits < <(git log --no-merges --pretty=format:"%h %H %s" "$range")

# If this is a tag, use rev-list to find the commit it points to.
from_commit=$(git rev-list -n 1 "$from_ref")
# Get the committer date of the commit so that we can list PRs merged.
from_commit_date=$(git show --no-patch --date=short --format=%cd "$from_commit")

# Get the labels for all PRs merged since the last release, this is
# inexact based on date, so a few PRs part of the previous release may
# be included.
#
# Example output:
#
# 27386d49d08455b6f8fbf2c18f38244d03fda892 label:security
# d9f2aaf3b430d8b6f3d5f24032ed6357adaab1f1
# fd54512858c906e66f04b0744d8715c2e0de97e6 label:stale label:enhancement
mapfile -t pr_labels_raw < <(
gh pr list \
--base main \
--state merged \
--limit 10000 \
--search "merged:>=$from_commit_date" \
--json mergeCommit,labels \
--jq '.[] | .mergeCommit.oid + " " + (["label:" + .labels[].name] | join(" "))'
)
declare -A labels
for entry in "${pr_labels_raw[@]}"; do
commit_sha_long=${entry%% *}
all_labels=${entry#* }
labels[$commit_sha_long]=$all_labels
done

for commit in "${commits[@]}"; do
mapfile -d ' ' -t parts <<<"$commit"
commit_sha=${parts[0]}
commit_prefix=${parts[1]}
commit_sha_short=${parts[0]}
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"
fi

# Store the commit title for later use.
title=${parts[*]:1}
title=${parts[*]:2}
title=${title%$'\n'}
COMMIT_METADATA_TITLE[$commit_sha]=$title
COMMIT_METADATA_TITLE[$commit_sha_short]=$title

# First, check the title for breaking changes. This avoids doing a
# GH API request if there's a match.
if [[ $commit_prefix =~ $breaking_title ]]; then
COMMIT_METADATA_CATEGORY[$commit_sha]=$breaking_category
COMMIT_METADATA_BREAKING=1
continue
fi

# Get the labels for the PR associated with this commit.
mapfile -t labels < <(gh api -H "Accept: application/vnd.github+json" "/repos/coder/coder/commits/${commit_sha}/pulls" -q '.[].labels[].name')

if [[ " ${labels[*]} " = *" ${breaking_label} "* ]]; then
COMMIT_METADATA_CATEGORY[$commit_sha]=$breaking_category
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
fi
Expand All @@ -73,10 +107,10 @@ main() {
fi
case $commit_prefix in
feat | fix)
COMMIT_METADATA_CATEGORY[$commit_sha]=$commit_prefix
COMMIT_METADATA_CATEGORY[$commit_sha_short]=$commit_prefix
;;
*)
COMMIT_METADATA_CATEGORY[$commit_sha]=other
COMMIT_METADATA_CATEGORY[$commit_sha_short]=other
;;
esac
done
Expand Down
2 changes: 1 addition & 1 deletion scripts/release/generate_release_notes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ 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)
Expand Down
2 changes: 1 addition & 1 deletion scripts/release/publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ if [[ "$dry_run" == 1 ]]; then
fi

# shellcheck source=scripts/release/check_commit_metadata.sh
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_tag..$new_ref"
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_tag" "$new_ref"

# Craft the release notes.
release_notes="$(execrelative ./generate_release_notes.sh --old-version "$old_tag" --new-version "$new_tag" --ref "$new_ref")"
Expand Down