build: unify the gate so root make check covers the backend (closes #16)
check / check (push) Successful in 11s
check / check (push) Successful in 11s
Root make check, and with it the pre-commit hook, now gates the Go backend too. The backend's Makefile targets are shims over backend/script/*; script/cibuild builds both images and is the workflow's only build step. Root make test runs both halves within one 30-second timeout. Root make lint runs golangci-lint only in Docker, by building the lint stage of Dockerfile.backend without the cache; the .golangci.yml drift check moved into backend/script/lint. script/bootstrap installs no linter: it reuses a Go at least as new as backend/go.mod asks for, otherwise installs the pinned, hash-verified release, linked into ~/.local/bin without replacing anything it did not create. With VERSION unset or empty, the backend version falls back to git describe inside a git checkout, then to dev. Model: opus-5-5
This commit was merged in pull request #38.
This commit is contained in:
+126
-11
@@ -5,7 +5,18 @@
|
||||
# or apk (detected in that order); assumes nothing is present. Node is
|
||||
# used directly if installed; otherwise it is installed at a pinned
|
||||
# version via nvm (installing nvm itself first, from a hash-verified
|
||||
# release archive, never curl | sh).
|
||||
# release archive, never curl | sh). Go, with its gofmt, is used
|
||||
# directly if it is at least the version backend/go.mod asks for;
|
||||
# otherwise the pinned Go release is installed from its hash-verified
|
||||
# archive.
|
||||
#
|
||||
# What this script installs outside the system package manager lives
|
||||
# under $HOME and is linked into ~/.local/bin, where make and the git
|
||||
# hook find it once that directory is on PATH. Nothing in ~/.local/bin
|
||||
# that this script did not create is ever replaced.
|
||||
#
|
||||
# golangci-lint is not installed: make lint runs it in Docker, which
|
||||
# this script does not install either.
|
||||
set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
@@ -16,6 +27,12 @@ NVM_VERSION="0.40.3"
|
||||
# sha256 of https://github.com/nvm-sh/nvm/archive/refs/tags/v0.40.3.tar.gz
|
||||
NVM_SHA256="5f4d6aaa04a177dc93c985e31dbc411ab6b8c6e1e21d8015dbc1372625fcd1d0"
|
||||
YARN_VERSION="1.22.22"
|
||||
# The Go inside the golang:1.25-alpine image Dockerfile.backend builds
|
||||
# with, 2026-08-09. The archive hashes are in ensure_go.
|
||||
GO_VERSION="1.25.7"
|
||||
|
||||
BIN_DIR="$HOME/.local/bin"
|
||||
TOOLCHAIN="$HOME/.local/share/$("$ROOT/script/projectname")/toolchain"
|
||||
|
||||
PKGMGR=""
|
||||
SUDO=""
|
||||
@@ -79,6 +96,26 @@ verify_sha256() {
|
||||
fi
|
||||
}
|
||||
|
||||
# link_bin <target> <name>: make an installed tool reachable as
|
||||
# $BIN_DIR/<name>. Only a symlink this script made, one pointing into
|
||||
# $TOOLCHAIN or ~/.nvm, is ever replaced; if anything else is already
|
||||
# there, bootstrap stops.
|
||||
link_bin() {
|
||||
link="$BIN_DIR/$2"
|
||||
if [ -L "$link" ] || [ -e "$link" ]; then
|
||||
case "$(readlink "$link" || true)" in
|
||||
"$TOOLCHAIN"/* | "$HOME"/.nvm/*) ;;
|
||||
*)
|
||||
echo "bootstrap: $link was not created by this script;" >&2
|
||||
echo " remove or rename it, then re-run bootstrap" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
mkdir -p "$BIN_DIR"
|
||||
ln -sf "$1" "$link"
|
||||
}
|
||||
|
||||
# nvm is a bash script; run a command in a bash with nvm loaded
|
||||
nvm_sh() {
|
||||
bash -c ". \"\$HOME/.nvm/nvm.sh\" && $*"
|
||||
@@ -103,39 +140,117 @@ ensure_node() {
|
||||
if ! missing node; then return 0; fi
|
||||
ensure_nvm
|
||||
nvm_sh "nvm install $NODE_VERSION"
|
||||
link_bin "$HOME/.nvm/versions/node/v$NODE_VERSION/bin/node" node
|
||||
}
|
||||
|
||||
# ensure_yarn: corepack writes its shims (pnpm and yarnpkg as well as
|
||||
# yarn) into $TOOLCHAIN rather than next to itself, and the npm fallback
|
||||
# installs there too; only yarn is linked.
|
||||
ensure_yarn() {
|
||||
if ! missing yarn; then return 0; fi
|
||||
shims="$TOOLCHAIN/corepack-shims"
|
||||
mkdir -p "$shims"
|
||||
if ! missing corepack; then
|
||||
corepack enable
|
||||
corepack enable --install-directory "$shims"
|
||||
corepack prepare "yarn@$YARN_VERSION" --activate
|
||||
elif [ -s "$HOME/.nvm/nvm.sh" ]; then
|
||||
nvm_sh "nvm use $NODE_VERSION >/dev/null && corepack enable && \
|
||||
nvm_sh "nvm use $NODE_VERSION >/dev/null && \
|
||||
corepack enable --install-directory \"$shims\" && \
|
||||
corepack prepare yarn@$YARN_VERSION --activate"
|
||||
else
|
||||
npm install -g "yarn@$YARN_VERSION"
|
||||
npm install -g --prefix "$TOOLCHAIN/npm-global" "yarn@$YARN_VERSION"
|
||||
shims="$TOOLCHAIN/npm-global/bin"
|
||||
fi
|
||||
link_bin "$shims/yarn" yarn
|
||||
}
|
||||
|
||||
install_js_deps() {
|
||||
if missing yarn && [ -s "$HOME/.nvm/nvm.sh" ]; then
|
||||
nvm_sh "nvm use $NODE_VERSION >/dev/null && cd \"$ROOT\" && \
|
||||
yarn install --frozen-lockfile"
|
||||
else
|
||||
yarn install --frozen-lockfile
|
||||
# go_ok: the go on PATH has its gofmt beside it (a Go release ships the
|
||||
# two together) and is at least the version backend/go.mod asks for.
|
||||
# GOTOOLCHAIN=local makes an older go fail here instead of fetching a
|
||||
# newer toolchain for itself.
|
||||
go_ok() {
|
||||
if missing go; then return 1; fi
|
||||
[ -x "$(dirname "$(command -v go)")/gofmt" ] || return 1
|
||||
(cd "$ROOT/backend" && GOTOOLCHAIN=local go list -m >/dev/null 2>&1)
|
||||
}
|
||||
|
||||
# ensure_go: unless go_ok, install GO_VERSION and link its go and gofmt.
|
||||
# They are linked on every run that needs them, so a deleted link is put
|
||||
# back, and the archive is unpacked again if either binary is missing.
|
||||
ensure_go() {
|
||||
if go_ok; then return 0; fi
|
||||
go_dir="$TOOLCHAIN/go-$GO_VERSION"
|
||||
if [ ! -x "$go_dir/bin/go" ] || [ ! -x "$go_dir/bin/gofmt" ]; then
|
||||
# sha256 of each archive, from https://go.dev/dl/?mode=json
|
||||
case "$(uname -s)-$(uname -m)" in
|
||||
Linux-x86_64)
|
||||
plat="linux-amd64"
|
||||
sha="12e6d6a191091ae27dc31f6efc630e3a3b8ba409baf3573d955b196fdf086005"
|
||||
;;
|
||||
Linux-aarch64)
|
||||
plat="linux-arm64"
|
||||
sha="ba611a53534135a81067240eff9508cd7e256c560edd5d8c2fef54f083c07129"
|
||||
;;
|
||||
Darwin-x86_64)
|
||||
plat="darwin-amd64"
|
||||
sha="bf5050a2152f4053837b886e8d9640c829dbacbc3370f913351eb0904cb706f5"
|
||||
;;
|
||||
Darwin-arm64)
|
||||
plat="darwin-arm64"
|
||||
sha="ff18369ffad05c57d5bed888b660b31385f3c913670a83ef557cdfd98ea9ae1b"
|
||||
;;
|
||||
*)
|
||||
echo "bootstrap: no pinned Go release for this platform" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if missing curl; then pkg_install curl curl curl curl; fi
|
||||
mkdir -p "$TOOLCHAIN"
|
||||
curl -fsSL -o "$go_dir.tar.gz" \
|
||||
"https://go.dev/dl/go$GO_VERSION.$plat.tar.gz"
|
||||
verify_sha256 "$go_dir.tar.gz" "$sha"
|
||||
# Unpacked beside its final place and then moved there, so an
|
||||
# interrupted run never leaves a partial Go that looks complete.
|
||||
rm -rf "$go_dir.partial"
|
||||
mkdir "$go_dir.partial"
|
||||
tar -xzf "$go_dir.tar.gz" -C "$go_dir.partial" --strip-components=1
|
||||
rm -rf "$go_dir" "$go_dir.tar.gz"
|
||||
mv "$go_dir.partial" "$go_dir"
|
||||
fi
|
||||
link_bin "$go_dir/bin/go" go
|
||||
link_bin "$go_dir/bin/gofmt" gofmt
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$ROOT"
|
||||
|
||||
# Tools linked on an earlier run count as installed, and tools linked
|
||||
# on this run are found by the steps after it.
|
||||
path_hint=""
|
||||
case ":$PATH:" in
|
||||
*":$BIN_DIR:"*) ;;
|
||||
*) path_hint=yes ;;
|
||||
esac
|
||||
PATH="$BIN_DIR:$PATH"
|
||||
|
||||
if missing make; then pkg_install gnumake make make make; fi
|
||||
if missing git; then pkg_install git git git git; fi
|
||||
|
||||
ensure_node
|
||||
ensure_yarn
|
||||
install_js_deps
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
ensure_go
|
||||
(cd "$ROOT/backend" && go mod download)
|
||||
|
||||
if missing docker; then
|
||||
echo "bootstrap: docker not found; make lint, and so make check" >&2
|
||||
echo " and the pre-commit hook, need it to run the Go linter" >&2
|
||||
fi
|
||||
if [ -n "$path_hint" ] && [ -d "$BIN_DIR" ]; then
|
||||
echo "bootstrap: add $BIN_DIR to the front of your PATH, e.g." >&2
|
||||
echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" >&2
|
||||
fi
|
||||
|
||||
echo "bootstrap complete"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user