bots-garden/sidekickpublic⑂ Fork 0
⑂ main
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 main · k33g · 2d ago
02-build-releases.sh · 174 lines · 6.1 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
 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
#!/bin/bash
: <<'COMMENT'
Build the release binaries of sidekick and stage them under release/${TAG}/

Usage:
  ./02-build-releases.sh          # TAG and ABOUT come from release.env
  ./02-build-releases.sh v0.2.0   # override the tag for this run (what CI does)

Only the Go toolchain is needed: every binary is a plain `go build`, there is
no Makefile and no helper script. The same command works on a laptop and in a
Rickub CI job (runners are linux/amd64; the other targets are cross-compiled).

What ends up in release/${TAG}/:
  sidekick-<version>-<os>-<arch>[.exe]   one binary per platform (web UI embedded)
  SHA256SUMS                             checksums of the binaries
  README.md                              download table + how to run
COMMENT

set -euo pipefail

# Build from the repository, whatever directory the script is started from.
cd "$(dirname "${BASH_SOURCE[0]}")"

# release.env carries TAG ("v0.2.0") and ABOUT (the one-line description). It
# is git-ignored (*.env), so a CI job does not have it: there the tag comes
# from the command line and ABOUT from the environment, or defaults to the
# tag. A tag given on the command line always wins, so a test build never
# edits the file.
if [ -f release.env ]; then
	source release.env
fi
TAG="${1:-${TAG:-}}"
ABOUT="${ABOUT:-Sidekick ${TAG}}"

# A tag that is not vMAJOR.MINOR.PATCH[-prerelease] is a typo — measured: a
# release.env with "v0.o.0" (letter o) would otherwise build and stage
# binaries nobody can name.
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 platforms a release is built for. Add or remove a line and everything
# below follows: the builds, the checksums and the README.
PLATFORMS=(
	"darwin/arm64"
	"linux/amd64"
	"linux/arm64"
	"windows/amd64"
	"windows/arm64"
)

# The tag is "v0.2.0"; the assets carry the bare version, "0.2.0".
VERSION="${TAG#v}"
RELEASES_DIR="release/${TAG}"

# -trimpath keeps this machine's paths out of binaries that go to strangers;
# -s -w drops the symbol table and DWARF, about a third of the size. -X stamps
# the tag into the binary, which is what `sidekick -version` reports: without
# it a downloaded release says "dev" and would not know its own name.
BUILD_FLAGS=(-trimpath -ldflags "-s -w -X main.version=${TAG}")

echo "🚀 Building Sidekick ${TAG} — ${ABOUT}"
echo "🐹 $(go version)"

rm -rf "${RELEASES_DIR}"
mkdir -p "${RELEASES_DIR}"

# assetName is what the binary for a platform is called once staged. Windows
# executables carry .exe, or Windows will not run them.
assetName() {
	local goos=$1 goarch=$2
	local name="sidekick-${VERSION}-${goos}-${goarch}"
	if [ "${goos}" = "windows" ]; then
		name="${name}.exe"
	fi
	printf '%s\n' "${name}"
}

echo ""
echo "🔨 Cross-compiling for ${#PLATFORMS[@]} platforms..."

for platform in "${PLATFORMS[@]}"; do
	goos="${platform%/*}"
	goarch="${platform#*/}"
	asset="$(assetName "${goos}" "${goarch}")"

	# CGO_ENABLED=0: nothing to link against on the other side of a
	# cross-compile, and sidekick needs no C — gorilla/websocket is pure Go.
	# Without it, a darwin build from a Linux box fails at link time.
	# The main package is in cmd/server: the module root has no Go file.
	if ! CGO_ENABLED=0 GOOS="${goos}" GOARCH="${goarch}" \
		go build "${BUILD_FLAGS[@]}" -o "${RELEASES_DIR}/${asset}" ./cmd/server; then
		echo "   ❌ ${platform}"
		exit 1
	fi
	echo "   ✅ ${asset}"
done

# The binary for this machine is the only one that can run here, and running
# it is the one proof that what ships starts at all: -h prints the usage and
# exits 0 before any agent is started.
HOST_ASSET="$(assetName "$(go env GOOS)" "$(go env GOARCH)")"
if [ -x "${RELEASES_DIR}/${HOST_ASSET}" ]; then
	if ! "${RELEASES_DIR}/${HOST_ASSET}" -h >/dev/null 2>&1; then
		echo "   ❌ ${HOST_ASSET} does not start (sidekick -h failed)"
		exit 1
	fi
	# The stamp is a string passed to the linker: a renamed package or variable
	# does not fail the build, it silently leaves the binary reporting "dev".
	# Ask the binary itself, here, while the release can still be stopped.
	if ! "${RELEASES_DIR}/${HOST_ASSET}" -version | grep -q -- "${TAG}"; then
		echo "   ❌ ${HOST_ASSET} does not report ${TAG}: $("${RELEASES_DIR}/${HOST_ASSET}" -version)"
		echo "   💡 check -X main.version in BUILD_FLAGS"
		exit 1
	fi
	echo "   ✅ ${HOST_ASSET} starts and reports ${TAG}"
fi

# checksum runs whichever of the two tools this machine has: sha256sum on
# Linux, shasum on macOS.
checksum() {
	if command -v sha256sum >/dev/null 2>&1; then
		sha256sum "$@"
	else
		shasum -a 256 "$@"
	fi
}

# One SHA256SUMS for every platform, names only (no directory), which is what
# `sha256sum -c` expects to read next to the downloaded files.
(cd "${RELEASES_DIR}" && checksum sidekick-"${VERSION}"-* >SHA256SUMS)
echo "   ✅ SHA256SUMS"

# downloadTable lists the platforms as a Markdown table, so the README grows
# and shrinks with PLATFORMS rather than repeating it by hand.
downloadTable() {
	printf '| Platform | Download |\n|---|---|\n'
	for platform in "${PLATFORMS[@]}"; do
		local goos="${platform%/*}" goarch="${platform#*/}"
		printf '| %s | `%s` |\n' "${platform}" "$(assetName "${goos}" "${goarch}")"
	done
}

cat >"${RELEASES_DIR}/README.md" <<EOM
# Sidekick ${TAG}

${ABOUT}

A web client for the Mini-Me ACP agent. Built with $(go env GOVERSION), CGO
disabled. The web UI is embedded in the binary; the only other thing it needs
is the \`mm\` agent, which it starts itself (in ACP mode).

$(downloadTable)

## Running it

    chmod +x sidekick-${VERSION}-<platform>
    ./sidekick-${VERSION}-<platform> mm --config config.yaml               # http://localhost:6767
    ./sidekick-${VERSION}-<platform> -port 9000 mm --config config.yaml    # another port

On macOS, an unsigned download is quarantined until you say otherwise:

    xattr -d com.apple.quarantine sidekick-${VERSION}-darwin-arm64

## Verifying the download

    sha256sum -c SHA256SUMS --ignore-missing     # shasum -a 256 -c on macOS
EOM
echo "   ✅ README.md"

echo ""
echo "✨ Build complete!"
ls -lh "${RELEASES_DIR}"