-
Notifications
You must be signed in to change notification settings - Fork 0
399 lines (385 loc) · 16.2 KB
/
Copy pathcreate-release.yaml
File metadata and controls
399 lines (385 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
name: Create Release
on:
workflow_call:
inputs:
build-release-artifacts:
description: "Build and upload release artifacts for multiple platforms (CLI tools)"
type: boolean
default: false
fetch-deep-gitlog-for-build:
description: "Fetch full git history for build (needed in special cases only)"
type: boolean
default: false
secrets:
TAYLORBOT_GITHUB_ACTION:
required: true
permissions: {}
jobs:
debug_info:
name: Debug info
runs-on: ubuntu-24.04
steps:
- name: Print github context JSON
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
gather_facts:
name: Gather facts
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
project_go_path: ${{ steps.get_project_go_path.outputs.path }}
version: ${{ steps.get_version.outputs.version }}
is_rc: ${{ steps.get_version.outputs.is_rc }}
steps:
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Install gitsemver
uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0
with:
binary: "gitsemver"
# renovate: datasource=github-releases depName=giantswarm/gitsemver
version: "2.0.0"
download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz"
tarball_binary_path: "*/${binary}"
smoke_test: "${binary} --version"
- name: Get version
id: get_version
env:
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
run: |
set -euo pipefail
# Accept release-PR titles of the form:
# - "chore(release): v1.2.3"
# - "chore(release): v1.2.3-rc.4"
# - "chore(release): v1.2.3 (#56)"
# The legacy "Release v..." form is also accepted for backward
# compatibility with PRs created by older versions of
# create-release-pr.yaml. Anything else (no match) yields an empty
# version output, which short-circuits the workflow as before.
title=$(echo -n "${COMMIT_MESSAGE}" | head -1)
version=""
is_rc=false
if echo "${title}" | grep -iqE '^(chore\(release\):|Release) v[^ ]+( \(#[0-9]+\))?$' ; then
candidate=$(echo "${title}" | cut -d ' ' -f 2)
candidate="${candidate#v}"
if gitsemver validate --type any "${candidate}" >/dev/null 2>&1; then
version="${candidate}"
if gitsemver validate --type rc "${candidate}" >/dev/null 2>&1; then
is_rc=true
fi
else
echo "::error::Title looks like a release commit but '${candidate}' is not a valid semver per gitsemver."
exit 1
fi
fi
echo "version=\"${version}\" is_rc=\"${is_rc}\""
echo "version=${version}" >> $GITHUB_OUTPUT
echo "is_rc=${is_rc}" >> $GITHUB_OUTPUT
- name: Checkout code
if: ${{ steps.get_version.outputs.version != '' }}
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Get project.go path
id: get_project_go_path
if: ${{ steps.get_version.outputs.version != '' }}
run: |
path='./pkg/project/project.go'
if [[ ! -f $path ]] ; then
path=''
fi
echo "path=\"$path\""
echo "path=${path}" >> $GITHUB_OUTPUT
update_project_go:
name: Update project.go
runs-on: ubuntu-24.04
permissions:
contents: read
if:
${{ needs.gather_facts.outputs.version != '' && needs.gather_facts.outputs.project_go_path != '' }}
needs:
- gather_facts
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
- name: Install gitsemver
uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0
with:
binary: "gitsemver"
# renovate: datasource=github-releases depName=giantswarm/gitsemver
version: "2.0.0"
download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz"
tarball_binary_path: "*/${binary}"
smoke_test: "${binary} --version"
- name: Update project.go
id: update_project_go
env:
branch: "${{ github.ref }}-version-bump"
IS_RC: "${{ needs.gather_facts.outputs.is_rc }}"
run: |
set -euo pipefail
git checkout -b ${{ env.branch }}
file="${{ needs.gather_facts.outputs.project_go_path }}"
version="${{ needs.gather_facts.outputs.version }}"
if [[ "${IS_RC}" == "true" ]]; then
# An RC like 1.3.0-rc.1 returns project.go to the dev string for the
# stable it is leading toward (1.3.0-dev). This way successive RCs
# do not drift project.go forward and the final stable release lands
# on the version project.go already advertises.
new_version="${version%-rc.*}-dev"
else
new_version="$(gitsemver next patch --last-tag "v${version}")-dev"
fi
echo "version=\"$version\" new_version=\"$new_version\""
echo "new_version=${new_version}" >> $GITHUB_OUTPUT
sed -Ei "s/(version[[:space:]]*=[[:space:]]*)\"${version}\"/\1\"${new_version}\"/" $file
if git diff --exit-code $file ; then
echo "error: no changes in \"$file\"" >&2
exit 1
fi
- name: Set up git identity
run: |
git config --local user.email "dev@giantswarm.io"
git config --local user.name "taylorbot"
- name: Commit changes
run: |
file="${{ needs.gather_facts.outputs.project_go_path }}"
git add $file
git commit -m "chore: bump version to ${{ steps.update_project_go.outputs.new_version }}"
- name: Push changes
env:
REMOTE_REPO:
"https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{
github.repository }}.git"
branch: "${{ github.ref }}-version-bump"
run: |
git push "${REMOTE_REPO}" HEAD:${{ env.branch }}
- name: Create PR
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
base: "${{ github.ref }}"
branch: "${{ github.ref }}-version-bump"
version: "${{ needs.gather_facts.outputs.version }}"
title: "chore: bump version to ${{ steps.update_project_go.outputs.new_version }}"
run: |
gh pr create --title "${{ env.title }}" --body "" \
--base ${{ env.base }} --head ${{ env.branch }} --reviewer ${{ github.actor }}
- name: Enable auto-merge for PR
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
base: "${{ github.ref }}"
branch: "${{ github.ref }}-version-bump"
version: "${{ needs.gather_facts.outputs.version }}"
title: "chore: bump version to ${{ steps.update_project_go.outputs.new_version }}"
run: |
gh pr merge --auto --squash "${{ env.branch }}" \
|| echo "::warning::Auto-merge not allowed. Please adjust the repository settings."
create_release:
name: Create release
runs-on: ubuntu-24.04
permissions:
contents: read
needs:
- gather_facts
if: ${{ needs.gather_facts.outputs.version }}
outputs:
upload_url: ${{ steps.create_gh_release.outputs.upload_url }}
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Ensure correct version in project.go
if: ${{ needs.gather_facts.outputs.project_go_path != '' }}
run: |
file="${{ needs.gather_facts.outputs.project_go_path }}"
version="${{ needs.gather_facts.outputs.version }}"
grep -qE "version[[:space:]]*=[[:space:]]*\"$version\"" $file
- name: Get Changelog Entry
id: changelog_reader
env:
VERSION: ${{ needs.gather_facts.outputs.version }}
run: |
set -euo pipefail
entry=$(awk -v ver="$VERSION" '
/^## \[/ {
if (found) exit
if (index($0, "[" ver "]")) { found = 1; next }
}
found {
if ($0 ~ /^\[[^]]+\]:[ \t]*https?:\/\//) next
if (!started && $0 ~ /^[[:space:]]*$/) next
started = 1
buf[++n] = $0
}
END {
while (n > 0 && buf[n] ~ /^[[:space:]]*$/) n--
for (i = 1; i <= n; i++) print buf[i]
}
' ./CHANGELOG.md)
if [ -z "$(printf %s "$entry" | tr -d '[:space:]')" ]; then
echo "::error::No changelog entry found for version $VERSION in ./CHANGELOG.md"
exit 1
fi
{
echo "changes<<__GHA_EOF__"
printf '%s\n' "$entry"
echo "__GHA_EOF__"
} >> "$GITHUB_OUTPUT"
- name: Set up git identity
run: |
git config --local user.email "dev@giantswarm.io"
git config --local user.name "taylorbot"
- name: Create tag
run: |
version="${{ needs.gather_facts.outputs.version }}"
git tag "v$version" ${{ github.sha }}
- name: Push tag
env:
REMOTE_REPO:
"https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{
github.repository }}.git"
run: |
git push "${REMOTE_REPO}" --tags
- name: Create release
id: create_gh_release
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
with:
body: ${{ steps.changelog_reader.outputs.changes }}
tag: "v${{ needs.gather_facts.outputs.version }}"
token: ${{ secrets.TAYLORBOT_GITHUB_ACTION }}
# Mark release-candidate versions (vX.Y.Z-rc.N) as GitHub pre-releases
# so they don't surface as the repo's "Latest release".
prerelease: ${{ needs.gather_facts.outputs.is_rc == 'true' }}
skipIfReleaseExists: true
create-release-branch:
name: Create release branch
runs-on: ubuntu-24.04
permissions:
contents: write
needs:
- gather_facts
if: ${{ needs.gather_facts.outputs.version && needs.gather_facts.outputs.is_rc != 'true' }}
steps:
- name: Check out the repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0 # Clone the whole history, not just the most recent commit.
persist-credentials: false
- name: Fetch all tags and branches
run: "git fetch --all"
- name: Create long-lived release branch
env:
REMOTE_REPO:
"https://${{ github.actor }}:${{ secrets.TAYLORBOT_GITHUB_ACTION }}@github.com/${{
github.repository }}.git"
run: |
set -euo pipefail
current_version="${{ needs.gather_facts.outputs.version }}"
parent_version="$(git describe --tags --abbrev=0 HEAD^ || true)"
parent_version="${parent_version#v}" # Strip "v" prefix.
if [[ -z "$parent_version" ]] ; then
echo "Unable to find a parent tag version. No branch to create."
exit 0
fi
echo "current_version=$current_version parent_version=$parent_version"
# Strip any pre-release suffix before splitting on '.', so a parent tag
# that happens to be an RC (e.g. 1.2.3-rc.4) is treated as 1.2.3 for
# the comparison.
IFS=. read -r current_major current_minor _ <<<"${current_version%%-*}"
IFS=. read -r parent_major parent_minor _ <<<"${parent_version%%-*}"
echo "current_major=$current_major current_minor=$current_minor"
echo "parent_major=$parent_major parent_minor=$parent_minor"
if [[ $current_major -gt $parent_major ]] ; then
echo "Current tag is a new major version"
elif [[ $current_major -eq $parent_major ]] && [[ $current_minor -gt $parent_minor ]] ; then
echo "Current tag is a new minor version"
else
echo "Current tag is not a new major or minor version. Nothing to do here."
exit 0
fi
release_branch="release-v${parent_major}.${parent_minor}.x"
echo "release_branch=$release_branch"
if git rev-parse --verify "$release_branch" >/dev/null 2>&1; then
echo "Release branch $release_branch already exists. Nothing to do here."
exit 0
fi
git branch "$release_branch" HEAD^
git push "${REMOTE_REPO}" "$release_branch"
create_and_upload_build_artifacts:
name: Create and upload build artifacts
runs-on: ubuntu-24.04
if: ${{ inputs.build-release-artifacts && needs.gather_facts.outputs.version }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
platform:
- darwin-amd64
- linux-amd64
- darwin-arm64
- linux-arm64
- windows-amd64
env:
GITHUB_TOKEN: "${{ secrets.TAYLORBOT_GITHUB_ACTION }}"
# renovate: datasource=golang-version depName=go
GO_VERSION: 1.26.3
ARTIFACT_DIR: bin-dist
TAG: v${{ needs.gather_facts.outputs.version }}
needs:
- create_release
- gather_facts
steps:
# Transitional: only needed by consumer Makefiles still on the pre-gitsemver
# devctl template, where `VERSION := $(shell architect project version)`
# stamps the release artifacts. devctl's current template uses
# `gitsemver version` (installed below), so this install can be dropped
# once all consumers have regenerated their Makefile.gen.go.mk.
- name: Install architect
uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0
with:
binary: "architect"
version: "6.14.1"
- name: Install gitsemver
uses: giantswarm/install-binary-action@5bef88f65012037dd836117c8d344b21bb559854 # v4.1.0
with:
binary: "gitsemver"
# renovate: datasource=github-releases depName=giantswarm/gitsemver
version: "2.0.0"
download_url: "https://github.com/giantswarm/${binary}/releases/download/v${version}/${binary}-v${version}-linux-amd64.tar.gz"
tarball_binary_path: "*/${binary}"
smoke_test: "${binary} --version"
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ env.TAG }}
# Strings ('0' / '1') are required because the GHA ternary idiom
# `cond && A || B` only works when A is truthy. The number `0`
# is falsy, so `cond && 0 || 1` always evaluates to `1`.
fetch-depth: ${{ inputs.fetch-deep-gitlog-for-build && '0' || '1' }}
- name: Create ${{ matrix.platform }} package
run: make package-${{ matrix.platform }}
- name: Specify package file name based on platform
run: |
if [[ "${{ matrix.platform }}" == "windows-amd64" ]]; then
echo "FILE_NAME=${{ github.event.repository.name }}-${{ env.TAG }}-${{ matrix.platform }}.zip" >> $GITHUB_ENV
else
echo "FILE_NAME=${{ github.event.repository.name }}-${{ env.TAG }}-${{ matrix.platform }}.tar.gz" >> $GITHUB_ENV
fi
- name: Add ${{ matrix.platform }} package to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ env.TAG }} \
${{ env.ARTIFACT_DIR }}/${{ env.FILE_NAME }}#${{ env.FILE_NAME }}