bots-garden/sidekickpublic⑂ Fork 0
⑂ feature/security
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/sidekick.git
git clone ssh://git@rickub.com/bots-garden/sidekick.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 0e8176f · on feature/security · k33g · 2d ago
01-release.tag.sh · 85 lines · 3.0 KBBash Blame HistoryRaw
 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
#!/bin/bash
: <<'COMMENT'
1. Update TAG and ABOUT in release.env
2. Run this script: ./01-release.tag.sh   (commit, push, tag, push the tag)
3. Watch the "Release" workflow on Rickub (Actions tab): the tag push starts
   it; it builds the binaries with ./02-build-releases.sh and publishes the
   release with them, using the job's own token. No personal token is needed.
COMMENT

# Without this, a failing step is ignored and the next one runs anyway. That is
# not theoretical: `git tag` refusing a tag that already existed was skipped in
# silence, and the `git push` below then pushed the OLD tag — so a release was
# cut from a commit nobody meant.
set -euo pipefail

cd "$(dirname "${BASH_SOURCE[0]}")"

set -o allexport
source release.env
set +o allexport

echo "Generating release: ${TAG} ${ABOUT}"

# Same rule as ./02-build-releases.sh, checked here too: once pushed, a
# malformed tag has already started the Release workflow, which then fails.
if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
	echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env)"
	exit 1
fi

# The commit is pushed to main and the tag put on HEAD: from another branch,
# the release would be cut from a commit main does not have.
branch="$(git symbolic-ref --short -q HEAD || true)"
if [ "${branch}" != "main" ]; then
	echo "❌ Releases are cut from main, not from '${branch:-a detached HEAD}'"
	exit 1
fi

# tagExists reports whether TAG is already taken, here or on the remote. The
# remote matters on its own: a tag deleted locally after a failed attempt still
# exists there, and pushing a new one at a different commit is rejected.
tagExists() {
	if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
		printf 'locally, on %s\n' "$(git rev-parse --short "${TAG}^{commit}")"
		return 0
	fi
	if ! remote="$(git ls-remote --tags origin "refs/tags/${TAG}" 2>/dev/null)"; then
		return 1 # the remote is unreachable; the push below will say so
	fi
	if [ -n "${remote}" ]; then
		# No commit is named here on purpose: for an annotated tag ls-remote
		# gives the tag object, not the commit, and printing that as if it were
		# the commit sends the reader looking for a SHA they will never find.
		printf 'on origin\n'
		return 0
	fi
	return 1
}

if where="$(tagExists)"; then
	echo "❌ ${TAG} already exists ${where}"
	echo "💡 Bump TAG in release.env, or move the tag onto this commit:"
	echo "     git tag -f -a ${TAG} -m \"${ABOUT}\""
	echo "     git push --force origin ${TAG}"
	exit 1
fi

find . -name '.DS_Store' -type f -delete

git add .

# Nothing to commit is not a failure — the work may already be committed — but
# under `set -e` a plain `git commit` would stop the release right here.
if git diff --cached --quiet; then
	echo "Nothing to commit; releasing what is already on HEAD"
else
	git commit -m "📦 ${ABOUT}"
fi

git push origin main

# The tag goes on after the push, so a rejected push never leaves a tag behind
# pointing at a commit the remote has never seen.
git tag -a "${TAG}" -m "${ABOUT}"
git push origin "${TAG}"