1 Commits
Author SHA1 Message Date
sneak 1cdf2013c8 Bootstrap keeps yarn and node only at their pinned versions (closes #154)
check / check (push) Canceled after 0s
script/bootstrap kept any yarn found on PATH, so YARN_VERSION applied
only where none was installed. It now keeps the yarn on PATH only when
yarn --version is exactly YARN_VERSION, and otherwise installs that
version as before. The node on PATH is used only when it has the
pinned major version, as REPO_POLICIES.md asks, and is at least
NODE_MIN_VERSION. After installing either, bootstrap looks the tool up
through PATH again, stops, naming the path, if that one fails the same
check, and prints the version it uses, as it does for Go. Every host
script except bootstrap that runs yarn now runs it through the new
script/yarn, which uses the first node on PATH, with ~/.local/bin
first, when it passes the same test, and otherwise the pinned node in
nvm.

Model: opus-5-5
2026-10-19 04:54:44 +00:00
4 changed files with 34 additions and 34 deletions
+11 -10
View File
@@ -42,12 +42,12 @@ either one is broken. We provide:
- `script/bootstrap` — install all dependencies (the pinned node via nvm unless - `script/bootstrap` — install all dependencies (the pinned node via nvm unless
the `node` on `PATH` has the pinned major version and is new enough for the the `node` on `PATH` has the pinned major version and is new enough for the
frontend's dependencies, yarn `YARN_VERSION` via corepack unless the `yarn` on frontend's dependencies, yarn `YARN_VERSION` via corepack, or npm where there
`PATH` is exactly that version, `yarn install --frozen-lockfile`, Go is no corepack, unless the `yarn` on `PATH` is exactly that version,
`GO_VERSION` unless the `go` on `PATH` is exactly that version, and the Go `yarn install --frozen-lockfile`, Go `GO_VERSION` unless the `go` on `PATH` is
modules), linking what it installs itself into `~/.local/bin`, which has to be exactly that version, and the Go modules), linking what it installs itself
on `PATH`. It installs no Go linter and not Docker: `make test` and into `~/.local/bin`, which has to be on `PATH`. It installs no Go linter and
`make lint` run in Docker not Docker: `make test` and `make lint` run in Docker
- `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/dev` — run the Vite dev server, which proxies `/api` to a locally - `script/dev` — run the Vite dev server, which proxies `/api` to a locally
@@ -61,10 +61,11 @@ either one is broken. We provide:
- `script/clean` — remove what `script/build` writes - `script/clean` — remove what `script/build` writes
- `script/projectname` — print the project name (used for the Docker image tag) - `script/projectname` — print the project name (used for the Docker image tag)
- `script/yarn` — run yarn with the given arguments under the node - `script/yarn` — run yarn with the given arguments under the node
`script/bootstrap` would use: with `~/.local/bin` first on `PATH`, the `node` `script/bootstrap` would use: with `~/.local/bin` first on `PATH`, the first
there when it has the pinned major version and is new enough for the `node` on that `PATH` when it has the pinned major version and is new enough
frontend's dependencies, and otherwise the pinned node in nvm. Every other for the frontend's dependencies, and otherwise the pinned node in nvm. Every
script that runs yarn on the host runs it through this one script that runs yarn on the host runs it through this one, except
`script/bootstrap`, which picks its own node and yarn
- `script/test` — build the `test` phase of `Dockerfile`, writing no image: the - `script/test` — build the `test` phase of `Dockerfile`, writing no image: the
frontend's unit tests in its `frontend-test` stage, and the backend's Go tests frontend's unit tests in its `frontend-test` stage, and the backend's Go tests
with the race detector and coverage. The frontend's production build is left with the race detector and coverage. The frontend's production build is left
+10 -9
View File
@@ -22,17 +22,18 @@ Run `make frontend-viewport-test` in CI as its own step; it is not part of
# Completed Steps # Completed Steps
- 2026-10-19: `script/bootstrap` keeps the `yarn` on `PATH` only when - 2026-10-19: `script/bootstrap` keeps the `yarn` on `PATH` only when
`yarn --version` is exactly `YARN_VERSION`, and otherwise prepares that `yarn --version` is exactly `YARN_VERSION`, and otherwise installs that
version through corepack, as it did when no yarn was installed version as it did when no yarn was installed
([#154](https://git.eeqj.de/sneak/netwatch/issues/154)); any yarn used to be ([#154](https://git.eeqj.de/sneak/netwatch/issues/154)); any yarn used to be
kept. It uses the `node` on `PATH` only when that node has the major version kept. It uses the `node` on `PATH` only when that node has the major version
of `NODE_VERSION` as well as being at least `NODE_MIN_VERSION`, as of `NODE_VERSION`, as `REPO_POLICIES.md` asks, and is at least
`REPO_POLICIES.md` asks; a node 24 was kept before. After installing node or `NODE_MIN_VERSION`; a node 24 was kept before. After installing node or yarn
yarn it looks the tool up through `PATH` again and stops if that is not the it looks the tool up through `PATH` again and stops if that one fails the same
pinned one, as it does for Go, and it prints the node and yarn versions it check, as it does for Go, and it prints the node and yarn versions it uses.
uses. Every script that runs yarn on the host runs it through the new Every script that runs yarn on the host, except `script/bootstrap`, which
`script/yarn`, which puts `~/.local/bin` first on `PATH`, uses the `node` picks its own node and yarn, runs it through the new `script/yarn`. That
there when it passes the same test, and otherwise runs yarn under the pinned script puts `~/.local/bin` first on `PATH`, uses the first `node` on that
`PATH` when it passes the same test, and otherwise runs yarn under the pinned
node in nvm; `make build` ran yarn under whatever node was first on `PATH` node in nvm; `make build` ran yarn under whatever node was first on `PATH`
- 2026-10-19: report file writes no longer overlap - 2026-10-19: report file writes no longer overlap
([#150](https://git.eeqj.de/sneak/netwatch/issues/150)), so the reports of ([#150](https://git.eeqj.de/sneak/netwatch/issues/150)), so the reports of
+6 -7
View File
@@ -7,7 +7,8 @@
# at least NODE_MIN_VERSION; otherwise NODE_VERSION is installed via nvm # at least NODE_MIN_VERSION; otherwise NODE_VERSION is installed via nvm
# (installing nvm itself first, from a hash-verified release archive, # (installing nvm itself first, from a hash-verified release archive,
# never curl | sh). Yarn is used directly only if it is exactly # never curl | sh). Yarn is used directly only if it is exactly
# YARN_VERSION; otherwise that version is prepared through corepack. # YARN_VERSION; otherwise that version is prepared through corepack,
# or installed with npm where there is no corepack.
# Go, with its gofmt, is used directly only if it is exactly GO_VERSION; # Go, with its gofmt, is used directly only if it is exactly GO_VERSION;
# otherwise that release is installed from its hash-verified archive. # otherwise that release is installed from its hash-verified archive.
# #
@@ -145,12 +146,10 @@ ensure_nvm() {
} }
# node_ok: the node on PATH has the major version of NODE_VERSION and is # node_ok: the node on PATH has the major version of NODE_VERSION and is
# at least NODE_MIN_VERSION. Only the major is compared with the pin: # at least NODE_MIN_VERSION. Only the major is compared with the pin,
# the Dockerfile's node stages start from a node 22 alpine image whose # as REPO_POLICIES.md asks. node itself compares the versions: major,
# exact version is not the pin, and nvm cannot install a prebuilt node # then minor, then patch. A node that fails does not pass.
# on alpine. node itself compares the versions: major, then minor, then # script/bootstrap and script/yarn carry this function unchanged.
# patch. A node that fails does not pass. script/bootstrap and
# script/yarn carry this function unchanged.
node_ok() { node_ok() {
if ! command -v node >/dev/null 2>&1; then return 1; fi if ! command -v node >/dev/null 2>&1; then return 1; fi
node -e ' node -e '
+7 -8
View File
@@ -1,7 +1,8 @@
#!/bin/sh #!/bin/sh
# script/yarn: run yarn with the given arguments under the node # script/yarn: run yarn with the given arguments under the node
# script/bootstrap would use. Every other script that runs yarn on the # script/bootstrap would use. Every script that runs yarn on the host
# host runs it through this one. # runs it through this one, except script/bootstrap, which picks its
# own node and yarn.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
@@ -11,12 +12,10 @@ NODE_VERSION="22.17.0"
NODE_MIN_VERSION="22.13.0" NODE_MIN_VERSION="22.13.0"
# node_ok: the node on PATH has the major version of NODE_VERSION and is # node_ok: the node on PATH has the major version of NODE_VERSION and is
# at least NODE_MIN_VERSION. Only the major is compared with the pin: # at least NODE_MIN_VERSION. Only the major is compared with the pin,
# the Dockerfile's node stages start from a node 22 alpine image whose # as REPO_POLICIES.md asks. node itself compares the versions: major,
# exact version is not the pin, and nvm cannot install a prebuilt node # then minor, then patch. A node that fails does not pass.
# on alpine. node itself compares the versions: major, then minor, then # script/bootstrap and script/yarn carry this function unchanged.
# patch. A node that fails does not pass. script/bootstrap and
# script/yarn carry this function unchanged.
node_ok() { node_ok() {
if ! command -v node >/dev/null 2>&1; then return 1; fi if ! command -v node >/dev/null 2>&1; then return 1; fi
node -e ' node -e '