All checks were successful
check / check (push) Successful in 3m29s
static/js/alpine.min.js was a committed minified bundle: unreviewable, referenced by no hash, and forbidden by REPO_POLICIES.md on both counts. It is now fetched by script/fetch-assets from a pinned npm registry tarball, with the tarball sha256 and the extracted file's sha256 both hardcoded and checked before anything is installed. The hash of every installed asset lives in static/vendor.sha256, and static/vendor_test.go re-hashes the bytes go:embed actually put in the binary against that manifest, so the pin is enforced on what ships rather than merely recorded. .gitignore keeps the artifact out of the repo and .dockerignore keeps a host copy out of the build context, so the image can only get it by fetching and verifying it. Alpine 3.14.9 is byte-identical to the blob that was committed (3ed1eed252488921df65e363d6715deb04d7f92aaedb9e52199fdf73cb1e0ad3), so the served asset does not change; internal/server/static_assets_test.go fetches every /s/ script base.html loads through the real router to prove the page still gets it.
128 lines
4.1 KiB
Bash
Executable File
128 lines
4.1 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 (not git,
|
|
# make, or go). golangci-lint is packaged in nix, brew, and apk; on apt
|
|
# it is installed from a hash-verified GitHub release archive (never
|
|
# curl | sh). Finishes by running script/fetch-assets, which installs the
|
|
# hash-pinned third-party browser assets the repo does not commit.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
# Pinned versions, 2026-08-07. Never "latest"; exact versions only.
|
|
GOLANGCI_LINT_VERSION="2.12.2"
|
|
# sha256 of golangci-lint-2.12.2-linux-<arch>.tar.gz release archives
|
|
GOLANGCI_LINT_SHA256_AMD64="8df580d2670fed8fa984aac0507099af8df275e665215f5c7a2ae3943893a553"
|
|
GOLANGCI_LINT_SHA256_ARM64="44cd40a8c76c86755375adfeea52cfd3533cb43d7bd647771e0ae065e166df3a"
|
|
|
|
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
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
# apt has no golangci-lint package: install a pinned release archive
|
|
# from GitHub, verified by hardcoded sha256 (never curl | sh).
|
|
install_golangci_lint_release() {
|
|
case "$(uname -m)" in
|
|
x86_64) goarch="amd64"; sha="$GOLANGCI_LINT_SHA256_AMD64" ;;
|
|
aarch64|arm64) goarch="arm64"; sha="$GOLANGCI_LINT_SHA256_ARM64" ;;
|
|
*)
|
|
echo "bootstrap: unsupported architecture $(uname -m)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if missing curl; then pkg_install curl curl curl curl; fi
|
|
name="golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${goarch}"
|
|
tmp="$(mktemp -d)"
|
|
curl -fsSL -o "$tmp/$name.tar.gz" \
|
|
"https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/${name}.tar.gz"
|
|
verify_sha256 "$tmp/$name.tar.gz" "$sha"
|
|
tar -xzf "$tmp/$name.tar.gz" -C "$tmp"
|
|
$SUDO install -m 0755 "$tmp/$name/golangci-lint" /usr/local/bin/golangci-lint
|
|
rm -rf "$tmp"
|
|
}
|
|
|
|
ensure_golangci_lint() {
|
|
if ! missing golangci-lint; then return 0; fi
|
|
detect_pkgmgr
|
|
case "$PKGMGR" in
|
|
apt) install_golangci_lint_release ;;
|
|
*) pkg_install golangci-lint golangci-lint golangci-lint golangci-lint ;;
|
|
esac
|
|
}
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
|
|
# Base tooling
|
|
if missing git; then pkg_install git git git git; fi
|
|
if missing make; then pkg_install gnumake make make make; fi
|
|
|
|
# Go toolchain and linter
|
|
if missing go; then pkg_install go golang go go; fi
|
|
ensure_golangci_lint
|
|
|
|
go mod download
|
|
|
|
# Third-party browser assets are not committed; fetch and verify them
|
|
# so a fresh clone can build and test.
|
|
if missing curl; then pkg_install curl curl curl curl; fi
|
|
"$ROOT/script/fetch-assets"
|
|
|
|
echo "bootstrap complete"
|
|
}
|
|
|
|
main "$@"
|