Pin the remaining developer tool installs (closes #68)
check / check (push) Failing after 2s
check / check (push) Failing after 2s
gofumpt was pinned only by its version tag. It is now a tool of a separate module in tools/, so `go tool` builds it from source checked against the hashes in tools/go.sum, and mfer's own module gains no dependencies. script/prettier no longer falls back to a prettier on PATH, and fails when node_modules holds a different version than package.json pins. The bootstrap comment now says what --frozen-lockfile really does, package.json drops its made-up version, and the golang image comment names its exact version. Model: opus-5-5
This commit is contained in:
+2
-2
@@ -10,7 +10,7 @@ COPY . .
|
||||
|
||||
# Go half of fmt-check only: this image has no node, so no prettier. The
|
||||
# markdown half runs in the mdfmt stage below. The image has no gofumpt
|
||||
# either; script/gofumpt builds the version it pins with `go run`.
|
||||
# either; script/gofumpt builds the version tools/go.mod requires.
|
||||
RUN script/gofumpt --check
|
||||
# The linter directly, not `make lint`: script/lint builds this stage, and
|
||||
# there is no docker inside this build.
|
||||
@@ -31,7 +31,7 @@ COPY . .
|
||||
RUN script/prettier --check
|
||||
|
||||
# Build stage — tests and compilation
|
||||
# golang:1.23 (2026-03-14)
|
||||
# golang:1.23.12, 2026-03-14
|
||||
FROM golang@sha256:60deed95d3888cc5e4d9ff8a10c54e5edc008c6ae3fba6187be6fb592e19e8c0 AS builder
|
||||
|
||||
# Force BuildKit to run the lint and mdfmt stages by creating stage dependencies
|
||||
|
||||
@@ -99,9 +99,10 @@ provide:
|
||||
- `script/fmt` — format all code and docs (writes): `script/gofumpt --write` and
|
||||
`script/prettier --write`
|
||||
- `script/gofumpt` — run `gofumpt` over every Go file in the repository in the
|
||||
given mode, `--write` or `--check`, at the one version it pins (built on
|
||||
demand by `go run`, so nothing installs it); `script/fmt`, `script/fmt-check`
|
||||
and the Docker lint stage all go through it, so they cannot disagree about Go
|
||||
given mode, `--write` or `--check`, at the version `tools/go.mod` requires
|
||||
(built on demand by `go tool` from source checked against the hashes in
|
||||
`tools/go.sum`, so nothing installs it); `script/fmt`, `script/fmt-check` and
|
||||
the Docker lint stage all go through it, so they cannot disagree about Go
|
||||
formatting
|
||||
- `script/prettier` — run prettier over the repository's canonical file set
|
||||
(Markdown and JSON, minus `.prettierignore`) in the given mode, `--write` or
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "mfer",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Development tooling for the mfer repository: prettier, used by script/fmt and script/fmt-check to format and verify Markdown and JSON.",
|
||||
"license": "WTFPL",
|
||||
|
||||
+6
-3
@@ -132,15 +132,18 @@ main() {
|
||||
# ---- JS / docs repos ----
|
||||
# This is a Go repo, but node and yarn are required anyway: prettier
|
||||
# formats the Markdown and JSON, and script/fmt-check verifies it.
|
||||
# The version is pinned by package.json/yarn.lock, whose integrity
|
||||
# hashes --frozen-lockfile enforces.
|
||||
# The version is pinned by package.json/yarn.lock: yarn checks every
|
||||
# package it fetches against its yarn.lock integrity hash, and
|
||||
# --frozen-lockfile fails instead of rewriting a yarn.lock that no
|
||||
# longer matches package.json.
|
||||
ensure_node
|
||||
ensure_yarn
|
||||
install_js_deps
|
||||
|
||||
# ---- Go repos ----
|
||||
if missing go; then pkg_install go golang go go; fi
|
||||
# No golangci-lint: script/lint runs it in Docker only.
|
||||
# No golangci-lint: script/lint runs it in Docker only. No gofumpt:
|
||||
# script/gofumpt builds the version tools/go.mod requires.
|
||||
go mod download
|
||||
|
||||
# ---- Python repos ----
|
||||
|
||||
+8
-9
@@ -10,10 +10,9 @@ set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
|
||||
# gofumpt v0.12.0, 2026-10-04. `go run` fetches and builds exactly this
|
||||
# version, so neither a developer machine nor the lint image needs
|
||||
# gofumpt installed.
|
||||
GOFUMPT="mvdan.cc/gofumpt@v0.12.0"
|
||||
# gofumpt v0.12.0, 2026-10-04, required by tools/go.mod. `go tool` run in
|
||||
# tools/ builds it from source checked against the hashes in tools/go.sum,
|
||||
# so neither a developer machine nor the lint image needs it installed.
|
||||
|
||||
usage() {
|
||||
echo "usage: script/gofumpt --write|--check" >&2
|
||||
@@ -22,15 +21,15 @@ usage() {
|
||||
|
||||
main() {
|
||||
[ "$#" -eq 1 ] || usage
|
||||
cd "$ROOT"
|
||||
# Every Go file in the repo. gofumpt holds generated files, such as
|
||||
# mfer/mf.pb.go, to gofmt's rules only.
|
||||
cd "$ROOT/tools"
|
||||
# Every Go file in the repo, from $ROOT down. gofumpt holds generated
|
||||
# files, such as mfer/mf.pb.go, to gofmt's rules only.
|
||||
case "$1" in
|
||||
--write) go run "$GOFUMPT" -l -w . ;;
|
||||
--write) go tool gofumpt -l -w "$ROOT" ;;
|
||||
--check)
|
||||
# Own line: a failing command inside `[ -n "$(...)" ]` does
|
||||
# not trip `set -e`, so a gofumpt that never ran would pass.
|
||||
unformatted="$(go run "$GOFUMPT" -l .)"
|
||||
unformatted="$(go tool gofumpt -l "$ROOT")"
|
||||
if [ -n "$unformatted" ]; then
|
||||
echo "gofumpt: files need formatting (run make fmt):" >&2
|
||||
echo "$unformatted" >&2
|
||||
|
||||
+16
-24
@@ -18,24 +18,9 @@ usage() {
|
||||
exit 2
|
||||
}
|
||||
|
||||
# Prefer the version pinned by package.json/yarn.lock so that CI and
|
||||
# developer machines format identically. Fall back to a prettier on PATH,
|
||||
# but say so, because a different version formats differently.
|
||||
find_prettier() {
|
||||
if [ -x "$ROOT/node_modules/.bin/prettier" ]; then
|
||||
printf '%s\n' "$ROOT/node_modules/.bin/prettier"
|
||||
return 0
|
||||
fi
|
||||
if command -v prettier >/dev/null 2>&1; then
|
||||
echo "prettier: node_modules/.bin/prettier is absent; using the" \
|
||||
"prettier on PATH, which may be a different version than the" \
|
||||
"one pinned in package.json. Run script/bootstrap to install" \
|
||||
"the pinned version." >&2
|
||||
command -v prettier
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
# Only the prettier yarn installed from yarn.lock, never one on PATH: a
|
||||
# different version formats differently.
|
||||
PRETTIER="$ROOT/node_modules/.bin/prettier"
|
||||
|
||||
main() {
|
||||
[ "$#" -eq 1 ] || usage
|
||||
@@ -46,10 +31,17 @@ main() {
|
||||
|
||||
cd "$ROOT"
|
||||
|
||||
if ! prettier_bin="$(find_prettier)"; then
|
||||
echo "prettier: not found." >&2
|
||||
echo " Install it with: script/bootstrap" >&2
|
||||
echo " (installs the version pinned in package.json/yarn.lock)" >&2
|
||||
# node_modules keeps the old prettier after package.json moves to a new
|
||||
# one, until script/bootstrap runs again, so compare the two. A prettier
|
||||
# that runs also means node is on PATH, which reading package.json needs.
|
||||
if ! installed="$("$PRETTIER" --version 2>/dev/null)"; then
|
||||
echo "prettier: not installed; run script/bootstrap" >&2
|
||||
exit 1
|
||||
fi
|
||||
pinned="$(node -p 'require("./package.json").devDependencies.prettier')"
|
||||
if [ "$installed" != "$pinned" ]; then
|
||||
echo "prettier: package.json pins $pinned but $installed is" \
|
||||
"installed; run script/bootstrap" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -62,8 +54,8 @@ main() {
|
||||
# patterns always match at least one tracked file (README.md,
|
||||
# package.json), so an empty match means the glob broke, and prettier
|
||||
# erroring out is exactly what we want rather than a vacuous pass.
|
||||
"$prettier_bin" "$mode" "**/*.md"
|
||||
"$prettier_bin" "$mode" "**/*.json"
|
||||
"$PRETTIER" "$mode" "**/*.md"
|
||||
"$PRETTIER" "$mode" "**/*.json"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// The developer tools this repo runs with `go tool`, kept out of the mfer
|
||||
// module so they add nothing to what mfer's users download. `go tool` builds
|
||||
// exactly the source whose hashes go.sum here records.
|
||||
module sneak.berlin/go/mfer/tools
|
||||
|
||||
go 1.26.0
|
||||
|
||||
tool mvdan.cc/gofumpt
|
||||
|
||||
require (
|
||||
golang.org/x/mod v0.40.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/tools v0.49.0 // indirect
|
||||
mvdan.cc/gofumpt v0.12.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474=
|
||||
github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
|
||||
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
|
||||
golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
|
||||
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
|
||||
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
mvdan.cc/gofumpt v0.12.0 h1:1Lbudkz2kpM9Cjz2pL4M19u7q+GaEhCTNf7N9mfpcho=
|
||||
mvdan.cc/gofumpt v0.12.0/go.mod h1:SmBHHrljiZu/uoypeKup3rFzP6eoC9UwCp2iH5E3jZA=
|
||||
Reference in New Issue
Block a user