check / check (push) Canceled after 0s
The vendored files are copies from sneak/prompts e3f79c4, with this repository's own entries kept. The script/ builds pass a new CACHEBUST value instead of --no-cache, which emptied Go's build cache mount, so every make test compiled the standard library and every dependency with -race. Every Dockerfile stage declares ARG CACHEBUST first, so every RUN step still reruns on an unchanged tree. The steps that compile mount Go's build cache, and both go test runs keep -count=1. The lint and test builds write no image. script/bootstrap, script/fmt and script/fmt-check are the canonical files plus this repository's Go steps. Model: opus-5-5
172 lines
5.2 KiB
Bash
Executable File
172 lines
5.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/bootstrap: install all dependencies needed to build and develop
|
|
# this repo. Idempotent: every install is guarded by a check so already
|
|
# installed tools are skipped. Base tooling comes from nix, apt, brew,
|
|
# or apk (detected in that order); assumes nothing is present. The
|
|
# installed node is used only when its major version is the pinned one;
|
|
# otherwise (node missing, or another major) the pinned version is
|
|
# installed via nvm (installing nvm itself first, from a hash-verified
|
|
# release archive, never curl | sh), and yarn and the packages are
|
|
# installed under it.
|
|
# golangci-lint is never installed: script/lint runs it in docker.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
# Pinned versions, 2026-07-06
|
|
NODE_VERSION="22.17.0"
|
|
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"
|
|
|
|
PKGMGR=""
|
|
SUDO=""
|
|
APT_UPDATED=""
|
|
|
|
detect_pkgmgr() {
|
|
[ -n "$PKGMGR" ] && return 0
|
|
if command -v nix-env >/dev/null 2>&1; then
|
|
PKGMGR="nix"
|
|
elif command -v apt-get >/dev/null 2>&1; then
|
|
PKGMGR="apt"
|
|
elif command -v brew >/dev/null 2>&1; then
|
|
PKGMGR="brew"
|
|
elif command -v apk >/dev/null 2>&1; then
|
|
PKGMGR="apk"
|
|
else
|
|
echo "bootstrap: no supported package manager (nix, apt, brew, apk)" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$PKGMGR" = "apt" ]; then
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
if [ "$(id -u)" != "0" ]; then
|
|
SUDO="sudo"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# pkg_install <nix-attr> <apt-pkg> <brew-formula> <apk-pkg>
|
|
pkg_install() {
|
|
detect_pkgmgr
|
|
case "$PKGMGR" in
|
|
nix) nix-env -iA "nixpkgs.$1" ;;
|
|
apt)
|
|
# Package lists may be empty (fresh images); refresh once per run.
|
|
if [ -z "$APT_UPDATED" ]; then
|
|
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get update
|
|
APT_UPDATED=1
|
|
fi
|
|
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2"
|
|
;;
|
|
brew) brew install "$3" ;;
|
|
apk) apk add --no-cache "$4" ;;
|
|
esac
|
|
}
|
|
|
|
missing() {
|
|
! command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# verify_sha256 <file> <expected-hash>
|
|
verify_sha256() {
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
actual="$(sha256sum "$1" | cut -d' ' -f1)"
|
|
else
|
|
actual="$(shasum -a 256 "$1" | cut -d' ' -f1)"
|
|
fi
|
|
if [ "$actual" != "$2" ]; then
|
|
echo "bootstrap: sha256 mismatch for $1" >&2
|
|
echo " expected: $2" >&2
|
|
echo " actual: $actual" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# nvm is a bash script; run a command in a bash with nvm loaded
|
|
nvm_sh() {
|
|
bash -c ". \"\$HOME/.nvm/nvm.sh\" && $*"
|
|
}
|
|
|
|
ensure_nvm() {
|
|
[ -s "$HOME/.nvm/nvm.sh" ] && return 0
|
|
# nvm prerequisites; nvm itself requires bash
|
|
if missing bash; then pkg_install bash bash bash bash; fi
|
|
if missing curl; then pkg_install curl curl curl curl; fi
|
|
if missing git; then pkg_install git git git git; fi
|
|
tmp="$(mktemp -d)"
|
|
curl -fsSL -o "$tmp/nvm.tar.gz" \
|
|
"https://github.com/nvm-sh/nvm/archive/refs/tags/v${NVM_VERSION}.tar.gz"
|
|
verify_sha256 "$tmp/nvm.tar.gz" "$NVM_SHA256"
|
|
mkdir -p "$HOME/.nvm"
|
|
tar -xzf "$tmp/nvm.tar.gz" -C "$HOME/.nvm" --strip-components=1
|
|
rm -rf "$tmp"
|
|
}
|
|
|
|
# True when the node on PATH has the pinned major version. Only the
|
|
# major is compared: the Dockerfile stages start from a node 22 alpine
|
|
# image whose exact version is not the pin, and nvm cannot install a
|
|
# prebuilt node on alpine. Another major is not used: the pinned yarn 1
|
|
# prints a deprecation warning under node 24. script/fmt and
|
|
# script/fmt-check carry this function unchanged, to run the yarn
|
|
# installed here.
|
|
node_is_pinned_major() {
|
|
if ! command -v node >/dev/null 2>&1; then return 1; fi
|
|
installed="$(node --version)"
|
|
installed="${installed#v}"
|
|
[ "${installed%%.*}" = "${NODE_VERSION%%.*}" ]
|
|
}
|
|
|
|
ensure_node() {
|
|
if node_is_pinned_major; then
|
|
echo "bootstrap: using node $(node --version)"
|
|
return 0
|
|
fi
|
|
ensure_nvm
|
|
nvm_sh "nvm install $NODE_VERSION"
|
|
nvm_sh "nvm use $NODE_VERSION >/dev/null && \
|
|
echo \"bootstrap: using node \$(node --version)\""
|
|
}
|
|
|
|
ensure_yarn() {
|
|
if ! node_is_pinned_major; then
|
|
nvm_sh "nvm use $NODE_VERSION >/dev/null && corepack enable && \
|
|
corepack prepare yarn@$YARN_VERSION --activate"
|
|
return 0
|
|
fi
|
|
if ! missing yarn; then return 0; fi
|
|
if ! missing corepack; then
|
|
corepack enable
|
|
corepack prepare "yarn@$YARN_VERSION" --activate
|
|
else
|
|
npm install -g "yarn@$YARN_VERSION"
|
|
fi
|
|
}
|
|
|
|
install_js_deps() {
|
|
if node_is_pinned_major; then
|
|
yarn install --frozen-lockfile
|
|
else
|
|
nvm_sh "nvm use $NODE_VERSION >/dev/null && cd \"$ROOT\" && \
|
|
yarn install --frozen-lockfile"
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
|
|
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
|
|
|
|
if missing go; then pkg_install go golang go go; fi
|
|
go mod download
|
|
|
|
echo "bootstrap complete"
|
|
}
|
|
|
|
main "$@"
|