bots-garden/hellopublic Fork 0
v0.1.0
Commits
Clone
git clone https://git.rickub.com/bots-garden/hello.git
git clone ssh://git@rickub.com/bots-garden/hello.git

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

01-release.tag.sh · 111 lines · 4.0 KBBash Blame HistoryRaw
📦 Hello 0368b85 k33g 4h ago1#!/bin/bash
2: <<'COMMENT'
3Publishing hello is tagging it. There is no binary to build and nothing to
4upload: a Go module is published by a tag being reachable from its repository.
5
61. Set TAG and ABOUT in release.env
72. Run this script: ./01-release.tag.sh (test, commit, push, tag, push the tag)
83. Watch the "Release" workflow (Actions tab): the tag push starts it, and it
9 creates the release page with the job's own token. Nothing else to run.
10COMMENT
11
12# Without this, a failing step is ignored and the next one runs anyway. That is
13# not theoretical: `git tag` refusing a tag that already existed was skipped in
14# silence in a sibling repository, and the `git push` below then pushed the OLD
15# tag — so a release was cut from a commit nobody meant.
16set -euo pipefail
17
18if [ ! -f release.env ]; then
19 echo "❌ release.env is missing"
20 echo "💡 Create it with the version you are publishing:"
21 echo ' TAG="v0.1.0"'
22 echo ' ABOUT="Hello"'
23 exit 1
24fi
25
26set -o allexport
27# shellcheck source=/dev/null
28source release.env
29set +o allexport
30
31: "${TAG:?TAG is not set in release.env}"
32ABOUT="${ABOUT:-Hello ${TAG}}"
33
34# A tag that is not vMAJOR.MINOR.PATCH[-prerelease] is worse than a typo here:
35# the module proxy will not serve a tag it cannot read as a version, so the
36# release would look fine and fail at every `go get`.
37if ! [[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
38 echo "❌ TAG must look like v1.2.3 or v1.2.3-rc.1, got '${TAG}' (check release.env)"
39 exit 1
40fi
41
42echo "Releasing hello ${TAG}: ${ABOUT}"
43
44# tagExists reports whether TAG is already taken, here or on the remote. The
45# remote matters on its own: a tag deleted locally after a failed attempt still
46# exists there, and pushing a new one at a different commit is rejected.
47tagExists() {
48 if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
49 printf 'locally, on %s\n' "$(git rev-parse --short "${TAG}^{commit}")"
50 return 0
51 fi
52 if ! remote="$(git ls-remote --tags origin "refs/tags/${TAG}" 2>/dev/null)"; then
53 return 1 # the remote is unreachable; the push below will say so
54 fi
55 if [ -n "${remote}" ]; then
56 # No commit is named here on purpose: for an annotated tag ls-remote
57 # gives the tag object, not the commit, and printing that as if it were
58 # the commit sends the reader looking for a SHA they will never find.
59 printf 'on origin\n'
60 return 0
61 fi
62 return 1
63}
64
65if where="$(tagExists)"; then
66 echo "${TAG} already exists ${where}"
67 echo "💡 A published version is not yours to move: somebody may already pin"
68 echo " it, and the module proxy caches what it fetched. Bump TAG in"
69 echo " release.env instead."
70 exit 1
71fi
72
73# A published library must not carry a replace directive: the proxy serves the
74# go.mod as written, and a consumer would be told to look for hello in a
75# directory that does not exist on their machine.
76if grep -qE '^[[:space:]]*replace[[:space:]]' go.mod; then
77 echo "❌ go.mod has a replace directive, which a published module must not"
78 grep -nE '^[[:space:]]*replace[[:space:]]' go.mod
79 exit 1
80fi
81
82# A version somebody may pin is the wrong place to find out the suite was red.
83echo "→ go vet ./..."
84go vet ./...
85echo "→ go test ./..."
86go test ./... -count=1
87
88find . -name '.DS_Store' -type f -delete
89
90git add .
91
92# Nothing to commit is not a failure — the work may already be committed — but
93# under `set -e` a plain `git commit` would stop the release right here.
94if git diff --cached --quiet; then
95 echo "Nothing to commit; releasing what is already on HEAD"
96else
97 git commit -m "📦 ${ABOUT}"
98fi
99
100# --show-current rather than `rev-parse --abbrev-ref HEAD`, which fails on a
101# branch with no commits yet — exactly the state a first release starts from.
102branch="$(git branch --show-current)"
103git push -u origin "${branch}"
104
105# The tag goes on after the push, so a rejected push never leaves a tag behind
106# pointing at a commit the remote has never seen.
107git tag -a "${TAG}" -m "${ABOUT}"
108git push origin "${TAG}"
109
110echo "✅ hello ${TAG} published"
111echo "💡 The tag push started the Release workflow; watch it on the Actions tab."