Skip to content

Commit 7c5e2ae

Browse files
jefkingmoltenhub-bot
andauthored
Automate production release tags (#948)
Co-authored-by: moltenhub-bot <moltenhub-bot@users.noreply.github.com>
1 parent cac562c commit 7c5e2ae

2 files changed

Lines changed: 107 additions & 21 deletions

File tree

.github/workflows/deploy-prod.yml

Lines changed: 93 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,19 @@ on:
88
required: true
99
default: vnext
1010
type: string
11-
release_tag:
12-
description: Git tag to publish to GitHub Releases
11+
bump:
12+
description: Version bump to apply when creating the release tag
1313
required: true
14+
default: patch
15+
type: choice
16+
options:
17+
- patch
18+
- minor
19+
- major
20+
first_release:
21+
description: First release tag to create when no vX.Y.Z tag exists
22+
required: true
23+
default: v1.0.0
1424
type: string
1525

1626
permissions:
@@ -25,31 +35,90 @@ jobs:
2535
name: Publish GitHub Release artifacts
2636
runs-on: ubuntu-latest
2737
timeout-minutes: 30
38+
outputs:
39+
release_tag: ${{ steps.release.outputs.tag }}
2840
steps:
29-
- name: Checkout release tag
41+
- name: Checkout
3042
uses: actions/checkout@v6
3143
with:
32-
ref: ${{ github.event.inputs.release_tag }}
3344
fetch-depth: 0
45+
fetch-tags: true
46+
47+
- name: Configure Git author
48+
run: |
49+
git config user.name "github-actions[bot]"
50+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
3451
35-
- name: Validate release tag
52+
- name: Compute release tag
53+
id: release
3654
env:
37-
RELEASE_TAG: ${{ github.event.inputs.release_tag }}
55+
BUMP: ${{ github.event.inputs.bump }}
56+
FIRST_RELEASE: ${{ github.event.inputs.first_release }}
3857
run: |
39-
case "${RELEASE_TAG}" in
40-
v[0-9]*.[0-9]*.[0-9]*)
41-
;;
42-
*)
43-
echo "Invalid release_tag: ${RELEASE_TAG}" >&2
44-
exit 1
45-
;;
46-
esac
58+
set -euo pipefail
59+
60+
if [[ ! "${BUMP}" =~ ^(patch|minor|major)$ ]]; then
61+
echo "Invalid bump: ${BUMP}" >&2
62+
exit 1
63+
fi
64+
65+
if [[ ! "${FIRST_RELEASE}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
66+
echo "Invalid first_release: ${FIRST_RELEASE}" >&2
67+
exit 1
68+
fi
69+
70+
latest_tag=""
71+
while IFS= read -r tag; do
72+
if [[ "${tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
73+
latest_tag="${tag}"
74+
break
75+
fi
76+
done < <(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname)
77+
78+
if [[ -z "${latest_tag}" ]]; then
79+
release_tag="${FIRST_RELEASE}"
80+
else
81+
version="${latest_tag#v}"
82+
IFS=. read -r major minor patch <<< "${version}"
83+
84+
case "${BUMP}" in
85+
major)
86+
major=$((major + 1))
87+
minor=0
88+
patch=0
89+
;;
90+
minor)
91+
minor=$((minor + 1))
92+
patch=0
93+
;;
94+
patch)
95+
patch=$((patch + 1))
96+
;;
97+
esac
98+
99+
release_tag="v${major}.${minor}.${patch}"
100+
fi
47101
48-
if ! git rev-parse --verify "refs/tags/${RELEASE_TAG}^{commit}" >/dev/null; then
49-
echo "Missing release tag: ${RELEASE_TAG}" >&2
102+
if git rev-parse --verify "refs/tags/${release_tag}^{commit}" >/dev/null 2>&1; then
103+
echo "Release tag already exists: ${release_tag}" >&2
50104
exit 1
51105
fi
52106
107+
echo "tag=${release_tag}" >> "${GITHUB_OUTPUT}"
108+
echo "Release tag: ${release_tag}"
109+
echo "### Release" >> "${GITHUB_STEP_SUMMARY}"
110+
echo "- Tag: ${release_tag}" >> "${GITHUB_STEP_SUMMARY}"
111+
echo "- Bump: ${BUMP}" >> "${GITHUB_STEP_SUMMARY}"
112+
113+
- name: Create release tag
114+
env:
115+
RELEASE_TAG: ${{ steps.release.outputs.tag }}
116+
run: |
117+
set -euo pipefail
118+
git tag -a "${RELEASE_TAG}" -m "Release ${RELEASE_TAG}"
119+
git push origin "refs/tags/${RELEASE_TAG}"
120+
git checkout --detach "${RELEASE_TAG}"
121+
53122
- name: Setup Go
54123
uses: actions/setup-go@v6
55124
with:
@@ -83,7 +152,10 @@ jobs:
83152
- name: Promote source tag to latest
84153
env:
85154
SOURCE_TAG: ${{ github.event.inputs.source_tag }}
155+
RELEASE_TAG: ${{ needs.release.outputs.release_tag }}
86156
run: |
157+
set -euo pipefail
158+
87159
case "${SOURCE_TAG}" in
88160
''|*[!A-Za-z0-9_.-]*)
89161
echo "Invalid source_tag: ${SOURCE_TAG}" >&2
@@ -94,3 +166,8 @@ jobs:
94166
docker buildx imagetools create \
95167
--tag moltenai/moltenhub-code:latest \
96168
"moltenai/moltenhub-code:${SOURCE_TAG}"
169+
170+
echo "### Docker promotion" >> "${GITHUB_STEP_SUMMARY}"
171+
echo "- Release: ${RELEASE_TAG}" >> "${GITHUB_STEP_SUMMARY}"
172+
echo "- Promoted: moltenai/moltenhub-code:${SOURCE_TAG}" >> "${GITHUB_STEP_SUMMARY}"
173+
echo "- Latest: moltenai/moltenhub-code:latest" >> "${GITHUB_STEP_SUMMARY}"

internal/library/docker_workflow_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,22 @@ func TestDeployProdPublishesGoReleaserGitHubRelease(t *testing.T) {
9797
content := string(data)
9898
for _, want := range []string{
9999
"contents: write",
100-
"release_tag:",
101-
"description: Git tag to publish to GitHub Releases",
100+
"bump:",
101+
"description: Version bump to apply when creating the release tag",
102+
"type: choice",
103+
"first_release:",
104+
"description: First release tag to create when no vX.Y.Z tag exists",
105+
"default: v1.0.0",
102106
"name: Publish GitHub Release artifacts",
103-
"ref: ${{ github.event.inputs.release_tag }}",
104107
"fetch-depth: 0",
105-
"Invalid release_tag: ${RELEASE_TAG}",
106-
"Missing release tag: ${RELEASE_TAG}",
108+
"fetch-tags: true",
109+
"id: release",
110+
"BUMP: ${{ github.event.inputs.bump }}",
111+
"FIRST_RELEASE: ${{ github.event.inputs.first_release }}",
112+
"Release tag already exists: ${release_tag}",
113+
"git tag -a \"${RELEASE_TAG}\" -m \"Release ${RELEASE_TAG}\"",
114+
"git push origin \"refs/tags/${RELEASE_TAG}\"",
115+
"git checkout --detach \"${RELEASE_TAG}\"",
107116
"uses: goreleaser/goreleaser-action@v7",
108117
"distribution: goreleaser",
109118
"version: '~> v2'",

0 commit comments

Comments
 (0)