Compare commits
1 Commits
b100814f8e
...
fix/unify-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c16d50d67 |
12
README.md
12
README.md
@@ -37,11 +37,13 @@ broken. We provide:
|
|||||||
|
|
||||||
- `script/bootstrap` — install all dependencies, assuming nothing is present:
|
- `script/bootstrap` — install all dependencies, assuming nothing is present:
|
||||||
pinned node via nvm if needed, yarn via corepack,
|
pinned node via nvm if needed, yarn via corepack,
|
||||||
`yarn install --frozen-lockfile`, and the backend's toolchain — Go (reused if
|
`yarn install --frozen-lockfile`, and the backend's toolchain — Go (an
|
||||||
already new enough) and golangci-lint at the version `Dockerfile.backend`
|
already-installed Go is reused only when its version falls inside the window
|
||||||
pins. Everything not installed by the system package manager comes from a
|
the pinned golangci-lint can analyse; a newer Go is ignored, not preferred)
|
||||||
hash-verified release archive and is symlinked onto `PATH`, so `make check`
|
and golangci-lint at the version `Dockerfile.backend` pins. Everything not
|
||||||
works in a plain shell afterwards
|
installed by the system package manager comes from a hash-verified release
|
||||||
|
archive and is symlinked into `~/.local/bin`, so `make check` works in a plain
|
||||||
|
shell afterwards
|
||||||
- `script/setup` — make a fresh clone ready for development: bootstrap plus the
|
- `script/setup` — make a fresh clone ready for development: bootstrap plus the
|
||||||
git pre-commit hook
|
git pre-commit hook
|
||||||
- `script/projectname` — print the project name (used for the Docker image tags)
|
- `script/projectname` — print the project name (used for the Docker image tags)
|
||||||
|
|||||||
9
TODO.md
9
TODO.md
@@ -28,7 +28,14 @@ files, so merging it also closes most compliance gaps.
|
|||||||
pre-commit hook installer in `backend/Makefile` was removed, `script/cibuild`
|
pre-commit hook installer in `backend/Makefile` was removed, `script/cibuild`
|
||||||
now builds both images as the workflow's only build step, and
|
now builds both images as the workflow's only build step, and
|
||||||
`script/bootstrap` provisions the backend toolchain (pinned, hash-verified Go
|
`script/bootstrap` provisions the backend toolchain (pinned, hash-verified Go
|
||||||
and golangci-lint) so a fresh clone can pass the widened gate
|
and golangci-lint) so a fresh clone can pass the widened gate. Bootstrap
|
||||||
|
matches the Go pin rather than treating it as a floor, because the pinned
|
||||||
|
golangci-lint cannot analyse packages built by a newer Go; it links only into
|
||||||
|
`~/.local/bin`, never a system-wide prefix, and refuses to replace anything it
|
||||||
|
did not create; and it exits non-zero rather than reporting success when the
|
||||||
|
tools on the caller's `PATH` are not the pinned ones — `gofmt` included, held
|
||||||
|
to the same version agreement as `go` and relinked on every run so a deleted
|
||||||
|
link cannot leave another Go's `gofmt` gating the repo
|
||||||
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
|
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
|
||||||
shims, README Entrypoints section
|
shims, README Entrypoints section
|
||||||
- 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow
|
- 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow
|
||||||
|
|||||||
288
script/bootstrap
288
script/bootstrap
@@ -5,10 +5,11 @@
|
|||||||
# or apk (detected in that order); assumes nothing is present. Node is
|
# or apk (detected in that order); assumes nothing is present. Node is
|
||||||
# used directly if installed; otherwise it is installed at a pinned
|
# used directly if installed; otherwise it is installed at a pinned
|
||||||
# version via nvm (installing nvm itself first, from a hash-verified
|
# version via nvm (installing nvm itself first, from a hash-verified
|
||||||
# release archive, never curl | sh). Go is used directly if it is
|
# release archive, never curl | sh). Go is used directly only if its
|
||||||
# already new enough, and golangci-lint is installed at the exact pinned
|
# version falls inside the pinned window described at GO_MAX_MINOR below
|
||||||
# version; both come from hash-verified official release archives, never
|
# -- a newer Go is ignored, not preferred -- and golangci-lint is
|
||||||
# an install script.
|
# installed at the exact pinned version; both come from hash-verified
|
||||||
|
# official release archives, never an install script.
|
||||||
#
|
#
|
||||||
# The backend's toolchain is bootstrapped here because script/check runs
|
# The backend's toolchain is bootstrapped here because script/check runs
|
||||||
# backend/script/test and backend/script/lint, so a machine that cannot
|
# backend/script/test and backend/script/lint, so a machine that cannot
|
||||||
@@ -16,13 +17,38 @@
|
|||||||
# pre-commit hook that script/setup installs.
|
# pre-commit hook that script/setup installs.
|
||||||
#
|
#
|
||||||
# Anything installed outside the system package manager is symlinked
|
# Anything installed outside the system package manager is symlinked
|
||||||
# into a directory that is on PATH, so a later `make check` in a plain
|
# into ~/.local/bin, so a later `make check` in a plain shell finds it.
|
||||||
# shell finds it. nvm only puts node on PATH for shells that source
|
# nvm only puts node on PATH for shells that source nvm.sh, which
|
||||||
# nvm.sh, which neither make nor the git hook does.
|
# neither make nor the git hook does.
|
||||||
|
#
|
||||||
|
# Three rules govern what this script is allowed to touch:
|
||||||
|
#
|
||||||
|
# 1. Everything it installs itself lands under $HOME, using $TMPDIR
|
||||||
|
# only for scratch downloads it then deletes. The one exception is
|
||||||
|
# the system package manager, which it shells out to for base
|
||||||
|
# tooling (see pkg_install) and which owns those paths already. A
|
||||||
|
# per-repo bootstrap has no business writing to /usr/local/bin, a
|
||||||
|
# Homebrew prefix, or any other system-wide location behind that
|
||||||
|
# package manager's back.
|
||||||
|
# 2. It never replaces something it did not create. Only a symlink
|
||||||
|
# that already points into one of its own managed directories is
|
||||||
|
# overwritten; anything else is left alone and bootstrap exits
|
||||||
|
# non-zero telling you what to remove.
|
||||||
|
# 3. It never reports success while the tools a later `make check`
|
||||||
|
# would pick up are not the ones it provisioned. If it cannot
|
||||||
|
# guarantee the pinned toolchain wins on your PATH, it exits
|
||||||
|
# non-zero rather than leaving you a green bootstrap and a broken
|
||||||
|
# gate.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
# The PATH as the caller had it, captured before ensure_bin_dir amends
|
||||||
|
# it. verify_toolchain checks against this rather than against the PATH
|
||||||
|
# this script builds for itself, so what it reports is what a later
|
||||||
|
# `make check` in the user's own shell will actually resolve.
|
||||||
|
ORIG_PATH="$PATH"
|
||||||
|
|
||||||
# Pinned versions, 2026-07-07
|
# Pinned versions, 2026-07-07
|
||||||
NODE_VERSION="22.17.0"
|
NODE_VERSION="22.17.0"
|
||||||
NVM_VERSION="0.40.3"
|
NVM_VERSION="0.40.3"
|
||||||
@@ -32,10 +58,27 @@ YARN_VERSION="1.22.22"
|
|||||||
|
|
||||||
# Go 1.25.7 (2026-08-09). This is the toolchain inside the pinned
|
# Go 1.25.7 (2026-08-09). This is the toolchain inside the pinned
|
||||||
# golang:1.25-alpine builder of Dockerfile.backend, so a local build
|
# golang:1.25-alpine builder of Dockerfile.backend, so a local build
|
||||||
# uses the same compiler CI does. GO_MIN_VERSION is the floor from
|
# uses the same compiler CI does.
|
||||||
# backend/go.mod; an already-installed go at or above it is used as is.
|
#
|
||||||
|
# The Go pin is a compatibility constraint to match, not a floor to
|
||||||
|
# clear. golangci-lint links go/types from the Go release it was built
|
||||||
|
# with, and go/types refuses to load packages compiled by a newer Go:
|
||||||
|
# with the pinned linter (built with go1.25.4) and a host Go 1.26,
|
||||||
|
# `make check` dies with
|
||||||
|
#
|
||||||
|
# panic: file requires newer Go version go1.26
|
||||||
|
# (application built with go1.25)
|
||||||
|
#
|
||||||
|
# So an already-installed go is reused only inside a window:
|
||||||
|
# GO_MIN_VERSION is the floor from backend/go.mod, and GO_MAX_MINOR is
|
||||||
|
# the major.minor of the Go the pinned golangci-lint was built with.
|
||||||
|
# Anything outside that window is ignored and GO_VERSION is installed
|
||||||
|
# instead. GO_MAX_MINOR is therefore coupled to GOLANGCI_LINT_VERSION
|
||||||
|
# below and must be revisited whenever that pin moves; `golangci-lint
|
||||||
|
# version` prints the "built with goX.Y.Z" it needs.
|
||||||
GO_VERSION="1.25.7"
|
GO_VERSION="1.25.7"
|
||||||
GO_MIN_VERSION="1.25.5"
|
GO_MIN_VERSION="1.25.5"
|
||||||
|
GO_MAX_MINOR="1.25"
|
||||||
|
|
||||||
# golangci-lint 2.7.2 (2026-08-09). MUST stay equal to the golangci-lint
|
# golangci-lint 2.7.2 (2026-08-09). MUST stay equal to the golangci-lint
|
||||||
# pinned in Dockerfile.backend (currently commit
|
# pinned in Dockerfile.backend (currently commit
|
||||||
@@ -47,12 +90,16 @@ GO_MIN_VERSION="1.25.5"
|
|||||||
# v2.12.2, commit c0d3ddc9cf3faa61a4e378e879ece580256d76e5. When that
|
# v2.12.2, commit c0d3ddc9cf3faa61a4e378e879ece580256d76e5. When that
|
||||||
# lands, GOLANGCI_LINT_VERSION and every hash in golangci_lint_sha256()
|
# lands, GOLANGCI_LINT_VERSION and every hash in golangci_lint_sha256()
|
||||||
# below must be updated to the v2.12.2 release archives in the same
|
# below must be updated to the v2.12.2 release archives in the same
|
||||||
# commit, or local and CI will disagree.
|
# commit, or local and CI will disagree. GO_MAX_MINOR must move with
|
||||||
|
# it, to the major.minor that release reports as "built with".
|
||||||
GOLANGCI_LINT_VERSION="2.7.2"
|
GOLANGCI_LINT_VERSION="2.7.2"
|
||||||
|
|
||||||
# Where hash-verified archives are unpacked. Version-scoped, so bumping
|
# Where hash-verified archives are unpacked. Version-scoped, so bumping
|
||||||
# a pin installs alongside the old copy instead of half-overwriting it.
|
# a pin installs alongside the old copy instead of half-overwriting it.
|
||||||
# Filled in by main() from script/projectname.
|
# Filled in by main() from script/projectname. TOOLCHAIN is also the
|
||||||
|
# ownership boundary used by link_bin: a symlink pointing inside it is
|
||||||
|
# one this script created and may replace.
|
||||||
|
TOOLCHAIN=""
|
||||||
GO_DIR=""
|
GO_DIR=""
|
||||||
GOLANGCI_LINT_DIR=""
|
GOLANGCI_LINT_DIR=""
|
||||||
|
|
||||||
@@ -170,33 +217,67 @@ ver_ge() {
|
|||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
|
||||||
# ensure_bin_dir: pick the directory provisioned tools are linked into.
|
# ensure_bin_dir: the directory provisioned tools are linked into. It is
|
||||||
# /usr/local/bin when writable (root, or a Homebrew prefix), otherwise
|
# always ~/.local/bin: per-user, never a system-wide or package-manager
|
||||||
# ~/.local/bin, which is prepended to PATH for the rest of this run and
|
# prefix. It is put at the front of PATH for the rest of this run, and
|
||||||
# reported so the user can add it permanently.
|
# reported if the caller's own PATH did not already contain it.
|
||||||
ensure_bin_dir() {
|
ensure_bin_dir() {
|
||||||
[ -n "$BIN_DIR" ] && return 0
|
[ -n "$BIN_DIR" ] && return 0
|
||||||
if [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then
|
BIN_DIR="$HOME/.local/bin"
|
||||||
BIN_DIR="/usr/local/bin"
|
mkdir -p "$BIN_DIR"
|
||||||
else
|
case "$PATH" in
|
||||||
BIN_DIR="$HOME/.local/bin"
|
"$BIN_DIR":*) ;;
|
||||||
mkdir -p "$BIN_DIR"
|
|
||||||
fi
|
|
||||||
case ":$PATH:" in
|
|
||||||
*":$BIN_DIR:"*) ;;
|
|
||||||
*)
|
*)
|
||||||
PATH="$BIN_DIR:$PATH"
|
PATH="$BIN_DIR:$PATH"
|
||||||
export PATH
|
export PATH
|
||||||
echo "bootstrap: add $BIN_DIR to your PATH" >&2
|
;;
|
||||||
|
esac
|
||||||
|
case ":$ORIG_PATH:" in
|
||||||
|
*":$BIN_DIR:"*) ;;
|
||||||
|
*)
|
||||||
|
echo "bootstrap: add $BIN_DIR to the front of your PATH, e.g." >&2
|
||||||
|
echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" >&2
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# owned_path <path>: true when <path> lies inside a directory this
|
||||||
|
# script provisions, i.e. a link to it is one this script created and
|
||||||
|
# may replace. Everything else belongs to the user or to a package
|
||||||
|
# manager and is never touched.
|
||||||
|
owned_path() {
|
||||||
|
case "$1" in
|
||||||
|
"$TOOLCHAIN"/*) return 0 ;;
|
||||||
|
"$HOME"/.nvm/*) return 0 ;;
|
||||||
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# refuse_clobber <path> <what>: report that <path> is not ours and stop.
|
||||||
|
refuse_clobber() {
|
||||||
|
echo "bootstrap: $1 already exists and $2." >&2
|
||||||
|
echo " Refusing to replace something this script did not create." >&2
|
||||||
|
echo " Remove or rename it and re-run bootstrap." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# link_bin <target> <name>: idempotently expose one provisioned binary
|
# link_bin <target> <name>: idempotently expose one provisioned binary
|
||||||
# on PATH.
|
# on PATH. Only an existing symlink into one of our own directories is
|
||||||
|
# replaced; a regular file, a directory, or a symlink pointing anywhere
|
||||||
|
# else is left intact and bootstrap fails.
|
||||||
link_bin() {
|
link_bin() {
|
||||||
ensure_bin_dir
|
ensure_bin_dir
|
||||||
ln -sfn "$1" "$BIN_DIR/$2"
|
link="$BIN_DIR/$2"
|
||||||
|
if [ -L "$link" ]; then
|
||||||
|
existing="$(readlink "$link")"
|
||||||
|
if ! owned_path "$existing"; then
|
||||||
|
refuse_clobber "$link" \
|
||||||
|
"is a symlink to $existing, outside this repo's toolchain"
|
||||||
|
fi
|
||||||
|
elif [ -e "$link" ]; then
|
||||||
|
refuse_clobber "$link" "is not a symlink"
|
||||||
|
fi
|
||||||
|
ln -sfn "$1" "$link"
|
||||||
}
|
}
|
||||||
|
|
||||||
# nvm is a bash script; run a command in a bash with nvm loaded
|
# nvm is a bash script; run a command in a bash with nvm loaded
|
||||||
@@ -229,19 +310,31 @@ ensure_node() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ensure_yarn: yarn comes from corepack. Left to itself, `corepack
|
||||||
|
# enable` writes its shims next to the corepack binary it resolved, and
|
||||||
|
# it writes four of them (yarn, yarnpkg, pnpm, pnpx), not the one asked
|
||||||
|
# for. --install-directory keeps all four inside this repo's own
|
||||||
|
# toolchain directory, and only yarn is then linked onto PATH. The
|
||||||
|
# no-corepack fallback likewise installs into a per-user npm prefix
|
||||||
|
# under the toolchain directory instead of npm's global one. Nothing
|
||||||
|
# here writes outside $HOME.
|
||||||
ensure_yarn() {
|
ensure_yarn() {
|
||||||
if ! missing yarn; then return 0; fi
|
if ! missing yarn; then return 0; fi
|
||||||
|
yarn_bin="$TOOLCHAIN/corepack-shims"
|
||||||
|
mkdir -p "$yarn_bin"
|
||||||
if ! missing corepack; then
|
if ! missing corepack; then
|
||||||
corepack enable
|
corepack enable --install-directory "$yarn_bin"
|
||||||
corepack prepare "yarn@$YARN_VERSION" --activate
|
corepack prepare "yarn@$YARN_VERSION" --activate
|
||||||
elif [ -s "$HOME/.nvm/nvm.sh" ]; then
|
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 \"$yarn_bin\" && \
|
||||||
corepack prepare yarn@$YARN_VERSION --activate"
|
corepack prepare yarn@$YARN_VERSION --activate"
|
||||||
else
|
else
|
||||||
npm install -g "yarn@$YARN_VERSION"
|
yarn_bin="$TOOLCHAIN/npm-global/bin"
|
||||||
|
npm install -g --prefix "$TOOLCHAIN/npm-global" "yarn@$YARN_VERSION"
|
||||||
fi
|
fi
|
||||||
if [ -n "$NODE_BIN" ] && [ -e "$NODE_BIN/yarn" ]; then
|
if [ -e "$yarn_bin/yarn" ]; then
|
||||||
link_bin "$NODE_BIN/yarn" yarn
|
link_bin "$yarn_bin/yarn" yarn
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,18 +371,46 @@ go_sha256() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# go_ok: an already-installed go is acceptable if it is at least
|
# go_ok: an already-installed go is acceptable only inside the window
|
||||||
# GO_MIN_VERSION, mirroring how node is used when already present.
|
# described at GO_MAX_MINOR: at least GO_MIN_VERSION, and no newer in
|
||||||
|
# major.minor than the Go the pinned golangci-lint was built with. A
|
||||||
|
# newer host Go is not "good enough", it makes `make check` panic, so it
|
||||||
|
# is treated exactly like a missing one.
|
||||||
go_ok() {
|
go_ok() {
|
||||||
if missing go; then return 1; fi
|
if missing go; then return 1; fi
|
||||||
have="$(go version 2>/dev/null | awk '{print $3}')"
|
have="$(go version 2>/dev/null | awk '{print $3}')"
|
||||||
have="${have#go}"
|
have="${have#go}"
|
||||||
[ -n "$have" ] || return 1
|
[ -n "$have" ] || return 1
|
||||||
ver_ge "$have" "$GO_MIN_VERSION"
|
ver_ge "$have" "$GO_MIN_VERSION" || return 1
|
||||||
|
ver_ge "$GO_MAX_MINOR" "$(echo "$have" | cut -d. -f1,2)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# gofmt_ok: gofmt is a gate tool -- backend/script/fmt-check runs it --
|
||||||
|
# and its output is not guaranteed byte-identical across Go releases, so
|
||||||
|
# a gofmt from a different release than the go that compiles the code is
|
||||||
|
# treated exactly like a missing one, the same way a mismatched
|
||||||
|
# golangci-lint is. `go version <file>` prints the toolchain a Go binary
|
||||||
|
# was built with, so this compares the gofmt that resolves on PATH
|
||||||
|
# against the go that resolves on PATH, without depending on where
|
||||||
|
# either one lives. Anything it cannot read -- no go to ask, gofmt
|
||||||
|
# absent, not a Go binary -- fails closed.
|
||||||
|
gofmt_ok() {
|
||||||
|
if missing go; then return 1; fi
|
||||||
|
if missing gofmt; then return 1; fi
|
||||||
|
go_have="$(go version 2>/dev/null | awk '{print $3}')"
|
||||||
|
[ -n "$go_have" ] || return 1
|
||||||
|
fmt_have="$(go version "$(command -v gofmt)" 2>/dev/null | awk '{print $NF}')"
|
||||||
|
[ "$fmt_have" = "$go_have" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# ensure_go: reuse the host toolchain only when the go on PATH is inside
|
||||||
|
# the window AND a gofmt from that same release is on PATH with it. Both
|
||||||
|
# link_bin calls sit outside that early return, so whenever the pinned
|
||||||
|
# toolchain is the one in use they run on every bootstrap, not only on
|
||||||
|
# the run that unpacked the archive: a deleted or never-created gofmt
|
||||||
|
# link is restored rather than silently left to some other Go's gofmt.
|
||||||
ensure_go() {
|
ensure_go() {
|
||||||
if go_ok; then return 0; fi
|
if go_ok && gofmt_ok; then return 0; fi
|
||||||
if [ ! -x "$GO_DIR/bin/go" ]; then
|
if [ ! -x "$GO_DIR/bin/go" ]; then
|
||||||
plat="$(platform)"
|
plat="$(platform)"
|
||||||
tmp="$(mktemp -d)"
|
tmp="$(mktemp -d)"
|
||||||
@@ -371,18 +492,101 @@ ensure_golangci_lint() {
|
|||||||
rm -rf "$tmp"
|
rm -rf "$tmp"
|
||||||
fi
|
fi
|
||||||
link_bin "$GOLANGCI_LINT_DIR/golangci-lint" golangci-lint
|
link_bin "$GOLANGCI_LINT_DIR/golangci-lint" golangci-lint
|
||||||
if ! golangci_lint_ok; then
|
}
|
||||||
echo "bootstrap: a different golangci-lint precedes $BIN_DIR on your" >&2
|
|
||||||
echo " PATH; local lint findings may not match what CI gates on" >&2
|
# verify_toolchain: bootstrap must not exit 0 while the tools the gate
|
||||||
|
# will actually run are not the provisioned ones. Everything above only
|
||||||
|
# guarantees the right tools exist and are linked into $BIN_DIR; if
|
||||||
|
# something earlier on the caller's PATH shadows them, `make check` --
|
||||||
|
# and the pre-commit hook script/setup installs -- still break, and a
|
||||||
|
# warning buried in a long bootstrap log is not enough. So the checks
|
||||||
|
# re-run against the PATH the caller will have (theirs, plus $BIN_DIR at
|
||||||
|
# the front if bootstrap had to ask for it), and a failure is fatal.
|
||||||
|
#
|
||||||
|
# Every gate tool that has a version constraint is checked with the same
|
||||||
|
# predicate its install used -- go_ok, gofmt_ok, golangci_lint_ok -- not
|
||||||
|
# with a bare presence test, because a wrong-version gate tool produces
|
||||||
|
# different results from the one CI runs, which is the failure this
|
||||||
|
# function exists to prevent. node and yarn have no pinned version to
|
||||||
|
# disagree about, so presence is the whole constraint for them.
|
||||||
|
verify_toolchain() {
|
||||||
|
# BIN_DIR is only set once something needed linking, but the remedy
|
||||||
|
# text must name a real directory in every reachable state, so fall
|
||||||
|
# back to the one ensure_bin_dir would have chosen.
|
||||||
|
bin_dir="${BIN_DIR:-$HOME/.local/bin}"
|
||||||
|
|
||||||
|
# Model the PATH the caller will actually have: their own, plus
|
||||||
|
# $BIN_DIR at the front only if bootstrap linked something there and
|
||||||
|
# therefore told them to add it.
|
||||||
|
verify_path="$ORIG_PATH"
|
||||||
|
if [ -n "$BIN_DIR" ]; then
|
||||||
|
case ":$ORIG_PATH:" in
|
||||||
|
*":$BIN_DIR:"*) ;;
|
||||||
|
*) verify_path="$BIN_DIR:$ORIG_PATH" ;;
|
||||||
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
saved_path="$PATH"
|
||||||
|
PATH="$verify_path"
|
||||||
|
export PATH
|
||||||
|
bad=""
|
||||||
|
go_ok || bad="$bad go"
|
||||||
|
gofmt_ok || bad="$bad gofmt"
|
||||||
|
golangci_lint_ok || bad="$bad golangci-lint"
|
||||||
|
for t in node yarn; do
|
||||||
|
if missing "$t"; then bad="$bad $t"; fi
|
||||||
|
done
|
||||||
|
PATH="$saved_path"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
[ -z "$bad" ] && return 0
|
||||||
|
|
||||||
|
# Two different faults land here and they need different remedies: a
|
||||||
|
# tool that resolves but is the wrong build is being shadowed, and
|
||||||
|
# telling the user to fix PATH is right; a tool that does not resolve
|
||||||
|
# at all is not being shadowed by anything, and saying so would send
|
||||||
|
# them hunting for a conflict that does not exist.
|
||||||
|
echo "bootstrap: the toolchain on your PATH cannot run the gate." >&2
|
||||||
|
wrong=""
|
||||||
|
absent=""
|
||||||
|
for t in $bad; do
|
||||||
|
where="$(
|
||||||
|
export PATH="$verify_path"
|
||||||
|
command -v "$t" 2>/dev/null || true
|
||||||
|
)"
|
||||||
|
if [ -n "$where" ]; then
|
||||||
|
echo " $t: $where (wrong version)" >&2
|
||||||
|
wrong="$wrong $t"
|
||||||
|
else
|
||||||
|
echo " $t: not found" >&2
|
||||||
|
absent="$absent $t"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo " The pinned toolchain is linked into $bin_dir." >&2
|
||||||
|
if [ -n "$wrong" ]; then
|
||||||
|
echo " The tools shown with a path resolve to a build this" >&2
|
||||||
|
echo " script did not provision: something earlier on your PATH" >&2
|
||||||
|
echo " shadows $bin_dir. Put $bin_dir first in" >&2
|
||||||
|
echo " PATH, or remove the conflicting tool, then re-run." >&2
|
||||||
|
fi
|
||||||
|
if [ -n "$absent" ]; then
|
||||||
|
echo " The tools shown as not found are on no directory of your" >&2
|
||||||
|
echo " PATH at all, so nothing is shadowing them. Add $bin_dir" >&2
|
||||||
|
echo " to PATH and re-run; if they are still not found after" >&2
|
||||||
|
echo " that, bootstrap failed to install them and that is a bug" >&2
|
||||||
|
echo " in this script, not in your environment." >&2
|
||||||
|
fi
|
||||||
|
echo " Failing rather than leaving you a bootstrap that reports" >&2
|
||||||
|
echo " success and a \`make check\` that does not run." >&2
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
|
||||||
toolchain="$HOME/.local/share/$("$ROOT/script/projectname")/toolchain"
|
TOOLCHAIN="$HOME/.local/share/$("$ROOT/script/projectname")/toolchain"
|
||||||
GO_DIR="$toolchain/go-$GO_VERSION"
|
GO_DIR="$TOOLCHAIN/go-$GO_VERSION"
|
||||||
GOLANGCI_LINT_DIR="$toolchain/golangci-lint-$GOLANGCI_LINT_VERSION"
|
GOLANGCI_LINT_DIR="$TOOLCHAIN/golangci-lint-$GOLANGCI_LINT_VERSION"
|
||||||
|
|
||||||
if missing make; then pkg_install gnumake make make make; fi
|
if missing make; then pkg_install gnumake make make make; fi
|
||||||
if missing git; then pkg_install git git git git; fi
|
if missing git; then pkg_install git git git git; fi
|
||||||
@@ -394,6 +598,8 @@ main() {
|
|||||||
ensure_go
|
ensure_go
|
||||||
ensure_golangci_lint
|
ensure_golangci_lint
|
||||||
|
|
||||||
|
verify_toolchain
|
||||||
|
|
||||||
echo "bootstrap complete"
|
echo "bootstrap complete"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user