Skip to content

ci: Revert to local tag creation and push for releases #5714

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 9 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 12 additions & 73 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
# GitHub release workflow.
name: Release
run-name: Release ${{ github.ref_name }}${{ inputs.dry_run && ' (DRYRUN)' || '' }}
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
default: false
dry_run:
description: Perform a dry-run release.
description: Perform a dry-run release (devel). Note that ref must be an annotated tag when run without dry-run.
type: boolean
required: true
default: false
ignore_missing_commit_metadata:
description: WARNING! This option disables the requirement that all commits have a PR. Not needed for dry_run.
type: boolean
default: false

permissions:
# Required to publish a release
Expand All @@ -43,29 +27,19 @@ env:
# booleans, not strings.
# https://github.blog/changelog/2022-06-10-github-actions-inputs-unified-across-manual-and-reusable-workflows/
CODER_RELEASE: ${{ !inputs.dry_run }}
CODER_RELEASE_INCREMENT: ${{ inputs.increment }}
CODER_RELEASE_DRAFT: ${{ inputs.draft }}
CODER_DRY_RUN: ${{ inputs.dry_run }}

jobs:
release:
name: Create and publish
name: Build and publish
runs-on: ${{ github.repository_owner == 'coder' && 'ubuntu-latest-16-cores' || 'ubuntu-latest' }}
env:
# Necessary for Docker manifest
DOCKER_CLI_EXPERIMENTAL: "enabled"
steps:
- name: Check release on main (or dry-run)
if: ${{ github.ref_name != 'main' && !inputs.dry_run }}
run: |
echo "Release not allowed on ${{ github.ref_name }}, use dry-run."
exit 1

- uses: actions/checkout@v3
with:
fetch-depth: 0
# Set token for pushing protected tag (vX.X.X).
token: ${{ secrets.RELEASE_GITHUB_PAT }}

# If the event that triggered the build was an annotated tag (which our
# tags are supposed to be), actions/checkout has a bug where the tag in
Expand All @@ -75,55 +49,23 @@ 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 "Coder CI"
git config user.email "dean+cdrci@coder.com"

- name: Create release tag and release notes
- name: Create release notes
env:
# We always have to set this since there might be commits on
# main that didn't have a PR.
CODER_IGNORE_MISSING_COMMIT_METADATA: "1"
run: |
set -euo pipefail
ref=HEAD
old_version="$(git describe --abbrev=0 "$ref^1")"

if [[ "${{ inputs.ignore_missing_commit_metadata }}" == *t* ]]; then
export CODER_IGNORE_MISSING_COMMIT_METADATA=1
fi

# Warn if CODER_IGNORE_MISSING_COMMIT_METADATA is set any other way
# than via dry-run.
if [[ ${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} != 0 ]]; then
echo "WARNING: CODER_IGNORE_MISSING_COMMIT_METADATA is enabled and we will ignore missing commit metadata." 1>&2
fi

version_args=()
if [[ $CODER_DRY_RUN == *t* ]]; then
# Allow dry-run of branches to pass.
export CODER_IGNORE_MISSING_COMMIT_METADATA=1
version_args+=(--dry-run)
fi

# Cache commit metadata.
. ./scripts/release/check_commit_metadata.sh "$old_version" "$ref"

declare -p version_args

# Create new release tag (note that this tag is not pushed before
# release.sh is run).
version="$(
./scripts/release/tag_version.sh \
"${version_args[@]}" \
--ref "$ref" \
--"$CODER_RELEASE_INCREMENT"
)"
version="$(./scripts/version.sh)"

# 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
- name: Show release notes
run: |
set -euo pipefail
cat "$CODER_RELEASE_NOTES_FILE"
Expand Down Expand Up @@ -243,9 +185,6 @@ jobs:
set -euo pipefail

publish_args=()
if [[ $CODER_RELEASE_DRAFT == *t* ]]; then
publish_args+=(--draft)
fi
if [[ $CODER_DRY_RUN == *t* ]]; then
publish_args+=(--dry-run)
fi
Expand Down
82 changes: 24 additions & 58 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cdroot

usage() {
cat <<EOH
Usage: ./release.sh [--branch <name>] [--draft] [--dry-run] [--ref <ref>] [--major | --minor | --patch]
Usage: ./release.sh [--dry-run] [--ref <ref>] [--major | --minor | --patch]

This script should be called to create a new release.

Expand All @@ -23,47 +23,24 @@ 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).
Set --dry-run to see what this script would do without making actual 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.

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
}

# Warn if CODER_IGNORE_MISSING_COMMIT_METADATA is set any other way than via
# --branch.
if [[ ${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} != 0 ]]; then
log "WARNING: CODER_IGNORE_MISSING_COMMIT_METADATA is enabled externally, we will ignore missing commit metadata."
fi

branch=main
draft=0
dry_run=0
ref=
increment=

args="$(getopt -o h -l branch:,draft,dry-run,help,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
--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
Expand Down Expand Up @@ -115,64 +92,53 @@ fi

# Check the current version tag from GitHub (by number) using the API to
# ensure no local tags are considered.
log "Checking GitHub for latest release..."
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 "Latest release: $old_version"
log

trap 'log "Check commit metadata failed, you can try to set \"export CODER_IGNORE_MISSING_COMMIT_METADATA=1\" and try again, if you know what you are doing."' EXIT
# shellcheck source=scripts/release/check_commit_metadata.sh
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref"
trap - EXIT

new_version="$(execrelative ./release/tag_version.sh --dry-run --ref "$ref" --"$increment")"
log "Executing DRYRUN of release tagging..."
new_version="$(execrelative ./release/tag_version.sh --old-version "$old_version" --ref "$ref" --"$increment" --dry-run)"
log
read -p "Continue? (y/n) " -n 1 -r continue_release
log
if ! [[ $continue_release =~ ^[Yy]$ ]]; then
exit 0
fi

release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_version" --new-version "$new_version" --ref "$ref")"

log
read -p "Preview release notes? (y/n) " -n 1 -r show_reply
log
if [[ $show_reply =~ ^[Yy]$ ]]; then
log
echo -e "$release_notes\n"
fi

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
read -p "Create release? (y/n) " -n 1 -r create
log
if ! [[ $create =~ ^[Yy]$ ]]; then
exit 0
fi

args=()
log
# Run without dry-run to actually create the tag, note we don't update the
# new_version variable here to ensure we're pushing what we showed before.
maybedryrun "$dry_run" execrelative ./release/tag_version.sh --old-version "$old_version" --ref "$ref" --"$increment" >/dev/null
maybedryrun "$dry_run" git push --tags -u origin "$new_version"

# Draft and dry-run are required args.
if ((draft)); then
args+=(-F draft=true)
else
args+=(-F draft=false)
fi
if ((dry_run)); then
args+=(-F dry_run=true)
else
args+=(-F dry_run=false)

# We only set this on non-dry-run releases because it will show a
# warning in CI.
if [[ ${CODER_IGNORE_MISSING_COMMIT_METADATA:-0} == 1 ]]; then
args+=(-F ignore_missing_commit_metadata=true)
fi
# We can't watch the release.yaml workflow if we're in dry-run mode.
exit 0
fi

log
logrun gh workflow run release.yaml \
--ref "$branch" \
-F increment="$increment" \
"${args[@]}"
log

read -p "Watch release? (y/n) " -n 1 -r watch
log
if ! [[ $watch =~ ^[Yy]$ ]]; then
Expand Down
8 changes: 5 additions & 3 deletions scripts/release/check_commit_metadata.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,12 @@ main() {
commit_sha_long=${parts[1]}
commit_prefix=${parts[2]}

if [[ $ignore_missing_metadata != 1 ]]; then
# Safety-check, guarantee all commits had their metadata fetched.
if [[ ! -v labels[$commit_sha_long] ]]; then
# Safety-check, guarantee all commits had their metadata fetched.
if [[ ! -v labels[$commit_sha_long] ]]; then
if [[ $ignore_missing_metadata != 1 ]]; then
error "Metadata missing for commit $commit_sha_short"
else
log "WARNING: Metadata missing for commit $commit_sha_short"
fi
fi

Expand Down
16 changes: 1 addition & 15 deletions scripts/release/publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ fi

version=""
release_notes_file=""
draft=0
dry_run=0

args="$(getopt -o "" -l version:,release-notes-file:,draft,dry-run -- "$@")"
args="$(getopt -o "" -l version:,release-notes-file:,dry-run -- "$@")"
eval set -- "$args"
while true; do
case "$1" in
Expand All @@ -50,10 +49,6 @@ while true; do
release_notes_file="$2"
shift 2
;;
--draft)
draft=1
shift
;;
--dry-run)
dry_run=1
shift
Expand Down Expand Up @@ -134,20 +129,11 @@ 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"/*

Expand Down
Loading