mirror of https://github.com/coder/coder.git
ci: Do release tagging in CI and add --draft support (#5652)
* ci: Do release tagging in CI and add --draft support * Add -h, --help to release.sh * Add -h, --help to increment_version_tag.sh * Limit release concurrency * Add automatic release watching * ci: Add git config, tag as "GitHub Actions Bot" Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
parent
e72a2ad907
commit
8e4af79cb2
|
@ -1,11 +1,21 @@
|
|||
# GitHub release workflow.
|
||||
name: release
|
||||
name: 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
|
||||
|
@ -25,9 +35,13 @@ permissions:
|
|||
|
||||
env:
|
||||
CODER_RELEASE: ${{ github.event.inputs.snapshot && 'false' || 'true' }}
|
||||
DRY_RUN: ${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && 'true' || 'false' }}
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Create and publish
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-16-cores' || 'ubuntu-latest' }}
|
||||
env:
|
||||
# Necessary for Docker manifest
|
||||
|
@ -45,6 +59,12 @@ jobs:
|
|||
- name: Fetch git tags
|
||||
run: git fetch --tags --force
|
||||
|
||||
# Configure git user name/email for creating annotated version tag.
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config user.name "GitHub Actions Bot"
|
||||
git config user.email ""
|
||||
|
||||
- name: Docker Login
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
|
@ -100,6 +120,38 @@ 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: |
|
||||
set -euo pipefail
|
||||
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"
|
||||
|
||||
# Create new release tag.
|
||||
version="$(
|
||||
./scripts/release/tag_version.sh \
|
||||
${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \
|
||||
--ref "$ref" \
|
||||
--${{ github.event.inputs.increment }}
|
||||
)"
|
||||
|
||||
# Generate notes.
|
||||
release_notes_file="$(mktemp -t release_notes.XXXXXX)"
|
||||
./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref" >> "$release_notes_file"
|
||||
echo CODER_RELEASE_NOTES_FILE="$release_notes_file" >> $GITHUB_ENV
|
||||
|
||||
- name: Echo release notes
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cat "$CODER_RELEASE_NOTES_FILE"
|
||||
|
||||
- name: Build binaries
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
@ -157,8 +209,11 @@ jobs:
|
|||
|
||||
- name: Publish release
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./scripts/release/publish.sh \
|
||||
${{ github.event.inputs.draft && '--draft' }} \
|
||||
${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \
|
||||
--release-notes-file "$CODER_RELEASE_NOTES_FILE" \
|
||||
./build/*_installer.exe \
|
||||
./build/*.zip \
|
||||
./build/*.tar.gz \
|
||||
|
@ -195,6 +250,7 @@ jobs:
|
|||
with:
|
||||
name: release-artifacts
|
||||
path: |
|
||||
./build/*_installer.exe
|
||||
./build/*.zip
|
||||
./build/*.tar.gz
|
||||
./build/*.tgz
|
||||
|
|
|
@ -1,44 +1,80 @@
|
|||
#!/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.
|
||||
#
|
||||
# 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 <ref>] [--minor]
|
||||
|
||||
set -euo pipefail
|
||||
# shellcheck source=scripts/lib.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
|
||||
cdroot
|
||||
|
||||
ref=
|
||||
minor=0
|
||||
usage() {
|
||||
cat <<EOH
|
||||
Usage: ./release.sh [--branch <name>] [--draft] [--dry-run] [--ref <ref>] [--major | --minor | --patch]
|
||||
|
||||
args="$(getopt -o n -l ref:,minor -- "$@")"
|
||||
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 <my-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 h -l branch:,draft,dry-run,help,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
|
||||
;;
|
||||
--dry-run)
|
||||
dry_run=1
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--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,15 +90,20 @@ 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
|
||||
log "Fetching $branch and tags from origin..."
|
||||
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
|
||||
|
||||
|
@ -71,42 +112,73 @@ 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"
|
||||
|
||||
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/tag_version.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
|
||||
log
|
||||
read -p "Preview release notes? (y/n) " -n 1 -r show_reply
|
||||
echo
|
||||
log
|
||||
if [[ $show_reply =~ ^[Yy]$ ]]; then
|
||||
echo -e "$release_notes\n"
|
||||
fi
|
||||
|
||||
read -p "Create release? (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"
|
||||
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
|
||||
log
|
||||
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
|
||||
|
||||
log
|
||||
gh workflow run release.yaml \
|
||||
--ref "$branch" \
|
||||
-F increment="$increment" \
|
||||
-F snapshot=false \
|
||||
"${args[@]}"
|
||||
log
|
||||
|
||||
read -p "Watch release? (y/n) " -n 1 -r watch
|
||||
log
|
||||
if ! [[ $watch =~ ^[Yy]$ ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log 'Waiting for job to become "in_progress"...'
|
||||
|
||||
# Wait at most 3 minutes (3*60)/3 = 60 for the job to start.
|
||||
for _ in $(seq 1 60); do
|
||||
mapfile -t run < <(
|
||||
# Output:
|
||||
# 3886828508
|
||||
# in_progress
|
||||
gh run list -w release.yaml \
|
||||
--limit 1 \
|
||||
--json status,databaseId \
|
||||
--jq '.[] | (.databaseId | tostring), .status'
|
||||
)
|
||||
if [[ ${run[1]} != "in_progress" ]]; then
|
||||
sleep 3
|
||||
continue
|
||||
fi
|
||||
gh run watch --exit-status "${run[0]}"
|
||||
exit 0
|
||||
done
|
||||
|
||||
error "Waiting for job to start timed out."
|
||||
|
|
|
@ -34,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]*\))?:"
|
||||
|
@ -87,9 +91,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 +105,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
|
||||
|
@ -137,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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@ if [[ "${CI:-}" == "" ]]; then
|
|||
fi
|
||||
|
||||
version=""
|
||||
release_notes_file=""
|
||||
draft=0
|
||||
dry_run=0
|
||||
|
||||
args="$(getopt -o "" -l version:,dry-run -- "$@")"
|
||||
args="$(getopt -o "" -l version:,release-notes-file:,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-file)
|
||||
release_notes_file="$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_file ]]; then
|
||||
error "No release notes files specified, use --release-notes-file."
|
||||
fi
|
||||
|
||||
# realpath-ify all input files so we can cdroot below.
|
||||
files=()
|
||||
for f in "$@"; do
|
||||
|
@ -96,25 +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"
|
||||
|
||||
# Create temporary release folder so we can generate checksums. Both the
|
||||
# sha256sum and gh binaries support symlinks as input files so this works well.
|
||||
temp_dir="$(mktemp -d)"
|
||||
|
@ -127,10 +122,10 @@ 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
|
||||
sed -e 's/^/\t/' - <"$release_notes_file" 1>&2
|
||||
log
|
||||
log "Contents:"
|
||||
pushd "$temp_dir"
|
||||
|
@ -139,11 +134,20 @@ popd
|
|||
log
|
||||
log
|
||||
|
||||
log "Pushing git tag"
|
||||
maybedryrun "$dry_run" git push --quiet origin "$new_tag"
|
||||
|
||||
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"/*
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
# shellcheck source=scripts/lib.sh
|
||||
source "$(dirname "$(dirname "${BASH_SOURCE[0]}")")/lib.sh"
|
||||
cdroot
|
||||
|
||||
usage() {
|
||||
cat <<EOH
|
||||
Usage: ./version_tag.sh [--dry-run] [--ref <ref>] <--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 h -l dry-run,help,ref:,major,minor,patch -- "$@")"
|
||||
eval set -- "$args"
|
||||
while true; do
|
||||
case "$1" in
|
||||
--dry-run)
|
||||
dry_run=1
|
||||
shift
|
||||
;;
|
||||
--ref)
|
||||
ref="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--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
|
||||
message="Ref \"$ref\" is already tagged with a release ($cur_tag)"
|
||||
if ! ((dry_run)); then
|
||||
error "$message."
|
||||
fi
|
||||
log "DRYRUN: $message, echoing current tag."
|
||||
echo "$cur_tag"
|
||||
exit 0
|
||||
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"
|
||||
|
||||
echo "$new_version"
|
Loading…
Reference in New Issue