Skip to content

Commit a495e43

Browse files
committed
ci: Do release tagging in CI and add --draft support
1 parent 52d7dfa commit a495e43

File tree

5 files changed

+229
-55
lines changed

5 files changed

+229
-55
lines changed

.github/workflows/release.yaml

+38-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
# GitHub release workflow.
2-
name: release
2+
name: New Release
33
on:
4-
push:
5-
tags:
6-
- "v*"
74
workflow_dispatch:
85
inputs:
6+
increment:
7+
description: Preferred version increment (release script may promote e.g. patch to minor depending on changes).
8+
type: choice
9+
required: true
10+
default: patch
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
draft:
16+
description: Create a draft release (for manually editing release notes before publishing).
17+
type: boolean
18+
required: true
919
snapshot:
1020
description: Force a dev version to be generated, implies dry_run.
1121
type: boolean
@@ -100,6 +110,27 @@ jobs:
100110
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
101111
AC_APIKEY_P8_BASE64: ${{ secrets.AC_APIKEY_P8_BASE64 }}
102112

113+
- name: Create release tag and release notes
114+
run: |
115+
ref=HEAD
116+
old_version="$(git describe --abbrev=0 "$ref^1")"
117+
118+
# Cache commit metadata.
119+
. ./scripts/release/check_commit_metadata.sh "$old_version" "$ref"
120+
121+
# Create new release tag.
122+
version="$(
123+
./scripts/release/increment_version_tag.sh \
124+
${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \
125+
--ref "$ref" \
126+
${{ github.event.inputs.increment }}
127+
)"
128+
129+
# Generate notes.
130+
echo 'CODER_RELEASE_NOTES<<RN_EOF' >> $GITHUB_ENV
131+
./scripts/release/generate_release_notes.sh --old-version "$old_version" --new-version "$version" --ref "$ref"
132+
echo 'RN_EOF' >> $GITHUB_ENV
133+
103134
- name: Build binaries
104135
run: |
105136
set -euo pipefail
@@ -158,7 +189,9 @@ jobs:
158189
- name: Publish release
159190
run: |
160191
./scripts/release/publish.sh \
192+
${{ github.event.inputs.draft && '--draft' }} \
161193
${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \
194+
--release-notes "$CODER_RELEASE_NOTES" \
162195
./build/*_installer.exe \
163196
./build/*.zip \
164197
./build/*.tar.gz \
@@ -195,6 +228,7 @@ jobs:
195228
with:
196229
name: release-artifacts
197230
path: |
231+
./build/*_installer.exe
198232
./build/*.zip
199233
./build/*.tar.gz
200234
./build/*.tgz

scripts/release.sh

+53-30
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,49 @@
1212
# be tagged at, otherwise the latest commit will be used.
1313
#
1414
# Set --minor to force a minor version bump, even when there are no breaking
15-
# changes.
15+
# changes. Likewise for --major. By default a patch version will be created.
16+
#
17+
# Set --dry-run to run the release workflow in CI as a dry-run (no release will
18+
# be created).
1619
#
1720
# To mark a release as containing breaking changes, the commit title should
1821
# either contain a known prefix with an exclamation mark ("feat!:",
1922
# "feat(api)!:") or the PR that was merged can be tagged with the
2023
# "release/breaking" label.
2124
#
22-
# Usage: ./release.sh [--ref <ref>] [--minor]
25+
# Usage: ./release.sh [--draft] [--dry-run] [--ref <ref>] [--major | --minor | --patch]
2326

2427
set -euo pipefail
2528
# shellcheck source=scripts/lib.sh
2629
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
2730
cdroot
2831

32+
draft=0
33+
dry_run=0
2934
ref=
30-
minor=0
35+
increment=
3136

32-
args="$(getopt -o n -l ref:,minor -- "$@")"
37+
args="$(getopt -o n -l draft,dry-run,ref:,major,minor,patch -- "$@")"
3338
eval set -- "$args"
3439
while true; do
3540
case "$1" in
41+
--draft)
42+
draft=1
43+
shift
44+
;;
45+
--dry-run)
46+
dry_run=1
47+
shift
48+
;;
3649
--ref)
3750
ref="$2"
3851
shift 2
3952
;;
40-
--minor)
41-
minor=1
53+
--major | --minor | --patch)
54+
if [[ -n $increment ]]; then
55+
error "Cannot specify multiple version increments."
56+
fi
57+
increment=${1#--}
4258
shift
4359
;;
4460
--)
@@ -54,6 +70,11 @@ done
5470
# Check dependencies.
5571
dependencies gh sort
5672

73+
if [[ -z $increment ]]; then
74+
# Default to patch versions.
75+
increment="patch"
76+
fi
77+
5778
# Make sure the repository is up-to-date before generating release notes.
5879
log "Fetching main and tags from origin..."
5980
git fetch --quiet --tags origin main
@@ -75,24 +96,7 @@ log "Checking commit metadata for changes since $old_version..."
7596
# shellcheck source=scripts/release/check_commit_metadata.sh
7697
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref"
7798

78-
mapfile -d . -t version_parts <<<"$old_version"
79-
if [[ $minor == 1 ]] || [[ $COMMIT_METADATA_BREAKING == 1 ]]; then
80-
if [[ $COMMIT_METADATA_BREAKING == 1 ]]; then
81-
log "Breaking change detected, incrementing minor version..."
82-
else
83-
log "Forcing minor version bump..."
84-
fi
85-
version_parts[1]=$((version_parts[1] + 1))
86-
version_parts[2]=0
87-
else
88-
log "No breaking changes detected, incrementing patch version..."
89-
version_parts[2]=$((version_parts[2] + 1))
90-
fi
91-
new_version="${version_parts[0]}.${version_parts[1]}.${version_parts[2]}"
92-
93-
log "Old version: ${old_version}"
94-
log "New version: ${new_version}"
95-
99+
new_version="$(execrelative ./release/increment_version_tag.sh --dry-run --ref "$ref" --"$increment")"
96100
release_notes="$(execrelative ./release/generate_release_notes.sh --old-version "$old_version" --new-version "$new_version" --ref "$ref")"
97101

98102
echo
@@ -102,11 +106,30 @@ if [[ $show_reply =~ ^[Yy]$ ]]; then
102106
echo -e "$release_notes\n"
103107
fi
104108

105-
read -p "Create release? (y/n) " -n 1 -r create
109+
create_message="Create release"
110+
if ((draft)); then
111+
create_message="Create draft release"
112+
fi
113+
if ((dry_run)); then
114+
create_message+=" (DRYRUN)"
115+
fi
116+
read -p "$create_message? (y/n) " -n 1 -r create
106117
echo
107-
if [[ $create =~ ^[Yy]$ ]]; then
108-
log "Tagging commit $ref as $new_version..."
109-
git tag -a "$new_version" -m "$new_version" "$ref"
110-
log "Pushing tag to origin..."
111-
git push -u origin "$new_version"
118+
if ! [[ $create =~ ^[Yy]$ ]]; then
119+
exit 0
120+
fi
121+
122+
args=()
123+
if ((draft)); then
124+
args+=(-F draft=true)
125+
fi
126+
if ((dry_run)); then
127+
args+=(-F dry_run=true)
112128
fi
129+
130+
gh workflow run release.yaml \
131+
--ref main \
132+
-F increment="$increment" \
133+
"${args[@]}"
134+
135+
log "Release process started, you can watch the release via: gh run watch --exit-status <run-id>"

scripts/release/generate_release_notes.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ if [[ -z $ref ]]; then
5959
fi
6060

6161
# shellcheck source=scripts/release/check_commit_metadata.sh
62-
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "${old_version}" "${ref}"
62+
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref"
6363

6464
# Sort commits by title prefix, then by date, only return sha at the end.
65-
mapfile -t commits < <(git log --no-merges --pretty=format:"%ct %h %s" "${old_version}..${ref}" | sort -k3,3 -k1,1n | cut -d' ' -f2)
65+
mapfile -t commits < <(git log --no-merges --pretty=format:"%ct %h %s" "$old_version..$ref" | sort -k3,3 -k1,1n | cut -d' ' -f2)
6666

6767
# From: https://github.com/commitizen/conventional-commit-types
6868
# 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")"
140140
echo -e "## Changelog
141141
$changelog
142142
143-
Compare: [\`${old_version}...${new_version}\`](https://github.com/coder/coder/compare/${old_version}...${new_version})
143+
Compare: [\`$old_version...$new_version\`](https://github.com/coder/coder/compare/$old_version...$new_version)
144144
145145
## Container Image
146146
+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env bash
2+
3+
# This script should be called to tag a new release. It will take the suggested
4+
# increment (major, minor, patch) and optionally promote e.g. patch -> minor if
5+
# there are breaking changes between the previous version and the given --ref
6+
# (or HEAD).
7+
#
8+
# Usage: ./increment_version_tag.sh [--dry-run] [--ref <ref>] <--major | --minor | --patch>
9+
#
10+
# This script will create a git tag, so it should only be run in CI (or via
11+
# --dry-run).
12+
13+
set -euo pipefail
14+
# shellcheck source=scripts/lib.sh
15+
source "$(dirname "$(dirname "${BASH_SOURCE[0]}")")/lib.sh"
16+
cdroot
17+
18+
dry_run=0
19+
ref=HEAD
20+
increment=
21+
22+
args="$(getopt -o n -l dry-run,ref:,major,minor,patch -- "$@")"
23+
eval set -- "$args"
24+
while true; do
25+
case "$1" in
26+
--dry-run)
27+
dry_run=1
28+
shift
29+
;;
30+
--ref)
31+
ref="$2"
32+
shift 2
33+
;;
34+
--major | --minor | --patch)
35+
if [[ -n $increment ]]; then
36+
error "Cannot specify multiple version increments."
37+
fi
38+
increment=${1#--}
39+
shift
40+
;;
41+
--)
42+
shift
43+
break
44+
;;
45+
*)
46+
error "Unrecognized option: $1"
47+
;;
48+
esac
49+
done
50+
51+
# Check dependencies.
52+
dependencies git
53+
54+
if [[ -z $increment ]]; then
55+
error "No version increment provided."
56+
fi
57+
58+
if [[ $dry_run != 1 ]] && [[ ${CI:-} == "" ]]; then
59+
error "This script must be run in CI or with --dry-run."
60+
fi
61+
62+
old_version="$(git describe --abbrev=0 "$ref^1")"
63+
cur_tag="$(git describe --abbrev=0 "$ref")"
64+
if [[ $old_version != cur_tag ]]; then
65+
error "Ref \"$ref\" is already tagged with a release ($cur_tag)."
66+
fi
67+
ref=$(git rev-parse --short "$ref")
68+
69+
log "Checking commit metadata for changes since $old_version..."
70+
# shellcheck source=scripts/release/check_commit_metadata.sh
71+
source "$SCRIPT_DIR/release/check_commit_metadata.sh" "$old_version" "$ref"
72+
73+
if ((COMMIT_METADATA_BREAKING == 1)); then
74+
prev_increment=$increment
75+
if [[ $increment == patch ]]; then
76+
increment=minor
77+
fi
78+
if [[ $prev_increment != "$increment" ]]; then
79+
log "Breaking change detected, changing version increment from \"$prev_increment\" to \"$increment\"."
80+
else
81+
log "Breaking change detected, provided increment is sufficient, using \"$increment\" increment."
82+
fi
83+
else
84+
log "No breaking changes detected, using \"$increment\" increment."
85+
fi
86+
87+
mapfile -d . -t version_parts <<<"${old_version#v}"
88+
case "$increment" in
89+
patch)
90+
version_parts[2]=$((version_parts[2] + 1))
91+
;;
92+
minor)
93+
version_parts[1]=$((version_parts[1] + 1))
94+
version_parts[2]=0
95+
;;
96+
major)
97+
version_parts[0]=$((version_parts[0] + 1))
98+
version_parts[1]=0
99+
version_parts[2]=0
100+
;;
101+
*)
102+
error "Unrecognized version increment."
103+
;;
104+
esac
105+
106+
new_version="v${version_parts[0]}.${version_parts[1]}.${version_parts[2]}"
107+
108+
log "Old version: $old_version"
109+
log "New version: $new_version"
110+
maybedryrun "$dry_run" git tag -a "$new_version" -m "Release $new_version" "$ref"
111+
maybedryrun "$dry_run" git push --quiet origin "$new_version"
112+
113+
echo "$new_version"

0 commit comments

Comments
 (0)