check / check (push) Failing after 3s
script/fmt and script/fmt-check now run prettier on every Markdown file after their Go steps, as the standard scripts from sneak/prompts at dd4027b do. script/bootstrap gains the standard node, nvm and yarn install next to its goimports install, and the last Dockerfile stage copies package.json and yarn.lock before running it. .prettierrc, .prettierignore and yarn.lock are the standard copies. package.json is the standard one without its licence field and marked private, because this repo's licence is the WTFPL. .dockerignore keeps the log of a failed yarn install out of the build context. README.md and TODO.md are reformatted once with it; REPO_POLICIES.md already matched. Model: opus-5-5
177 lines
5.5 KiB
Bash
Executable File
177 lines
5.5 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. 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).
|
|
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"
|
|
|
|
# goimports from golang.org/x/tools v0.30.0, 2025-02-10: the last release
|
|
# that Go 1.22, the Go of go.mod and the Dockerfile, can build.
|
|
GOIMPORTS_COMMIT="09747cdf594a7924dcecb506312be3bd6e437962"
|
|
GOIMPORTS_VERSION="v0.30.0"
|
|
|
|
PKGMGR=""
|
|
SUDO=""
|
|
|
|
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) $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
|
|
}
|
|
|
|
# Print the golang.org/x/tools version that the goimports on PATH was
|
|
# built from, or nothing. goimports has no --version flag; `go version -m`
|
|
# prints the module versions Go records in every binary it builds.
|
|
goimports_version() {
|
|
bin="$(command -v goimports)" || return 0
|
|
go version -m "$bin" 2>/dev/null |
|
|
awk '$1 == "mod" && $2 == "golang.org/x/tools" { print $3 }'
|
|
}
|
|
|
|
# Install goimports at the pinned commit unless the one on PATH already
|
|
# reports the pinned version. go install writes to GOBIN, or to the bin
|
|
# directory of GOPATH when GOBIN is unset, which need not be on the
|
|
# caller's PATH; script/fmt puts that directory first on PATH the same
|
|
# way, so the check here sees the goimports that script/fmt runs.
|
|
ensure_goimports() {
|
|
gobin="$(go env GOBIN)"
|
|
PATH="${gobin:-$(go env GOPATH)/bin}:$PATH"
|
|
if [ "$(goimports_version)" != "$GOIMPORTS_VERSION" ]; then
|
|
go install "golang.org/x/tools/cmd/goimports@$GOIMPORTS_COMMIT"
|
|
hash -r
|
|
if [ "$(goimports_version)" != "$GOIMPORTS_VERSION" ]; then
|
|
echo "bootstrap: goimports on PATH is not $GOIMPORTS_VERSION" \
|
|
"after installing it: $(command -v goimports || echo none)" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
echo "goimports $GOIMPORTS_VERSION at $(command -v goimports)"
|
|
}
|
|
|
|
# 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"
|
|
}
|
|
|
|
ensure_node() {
|
|
if ! missing node; then return 0; fi
|
|
ensure_nvm
|
|
nvm_sh "nvm install $NODE_VERSION"
|
|
}
|
|
|
|
ensure_yarn() {
|
|
if ! missing yarn; then return 0; fi
|
|
if ! missing corepack; then
|
|
corepack enable
|
|
corepack prepare "yarn@$YARN_VERSION" --activate
|
|
elif [ -s "$HOME/.nvm/nvm.sh" ]; then
|
|
nvm_sh "nvm use $NODE_VERSION >/dev/null && corepack enable && \
|
|
corepack prepare yarn@$YARN_VERSION --activate"
|
|
else
|
|
npm install -g "yarn@$YARN_VERSION"
|
|
fi
|
|
}
|
|
|
|
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
|
|
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
|
|
|
|
if missing go; then pkg_install go golang go go; fi
|
|
# golangci-lint is not installed: it runs only in docker (script/lint).
|
|
ensure_goimports
|
|
|
|
go mod download
|
|
|
|
ensure_node
|
|
ensure_yarn
|
|
install_js_deps
|
|
|
|
echo "bootstrap complete"
|
|
}
|
|
|
|
main "$@"
|