fmt: format and check Markdown with prettier in a container (closes #119)
check / check (push) Failing after 2m11s
check / check (push) Failing after 2m11s
make fmt and make fmt-check now cover every Markdown file with prettier (4-space tabs, proseWrap always), as template-app-go does: prettier is pinned by package.json and yarn.lock and runs in a docker build on a digest-pinned node image, never on the host. The check is forced to run with --no-cache-filter, as script/lint is. script/fmt-check is split into a Go half and a Markdown half because the Dockerfile lint stage cannot run docker: that stage now runs the Go half and script/cibuild runs the Markdown half after the build. *.md leaves .dockerignore so documents reach the build context. README.md, TESTING.md and TODO.md are reformatted by make fmt; apart from the README Entrypoints entries, its make fmt line under Building and the TODO entry, that diff is mechanical. Model: opus-5-5
This commit was merged in pull request #196.
This commit is contained in:
+48
-2
@@ -1,19 +1,65 @@
|
||||
#!/bin/sh
|
||||
# script/fmt: format all files (writes).
|
||||
# script/fmt: format all files (writes). Go with gofmt and goimports on
|
||||
# the host, markdown with the prettier pinned by Dockerfile.fmt.
|
||||
#
|
||||
# goimports runs with `go run` at a pinned commit, never from PATH, so
|
||||
# every machine formats with the same version and nothing installs it.
|
||||
#
|
||||
# The markdown pass is a `docker build --output type=local` rather than a
|
||||
# `docker run -v`, so it needs no bind mount and behaves the same against
|
||||
# a remote daemon; the formatted documents come back out of the build and
|
||||
# are copied over the tree here.
|
||||
#
|
||||
# Unlike script/fmt-check-markdown this does not bust the cache: it is
|
||||
# not a gate, and any edit to a document changes the COPY layer above the
|
||||
# prettier step, so a cached result is a result over this exact tree.
|
||||
set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
|
||||
# goimports v0.42.0, 2026-08-07. Must match script/fmt-check.
|
||||
# goimports v0.42.0, 2026-08-07. Must match script/fmt-check-go.
|
||||
GOIMPORTS_REF="golang.org/x/tools/cmd/goimports@009367f5c17a8d4c45a961a3a509277190a9a6f0"
|
||||
|
||||
# Must match the export stage name in Dockerfile.fmt.
|
||||
stage=fmt-out
|
||||
|
||||
die() {
|
||||
echo "script/fmt: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$ROOT"
|
||||
gofmt -s -w .
|
||||
go run "$GOIMPORTS_REF" -w .
|
||||
|
||||
tmp="$(mktemp -d "${TMPDIR:-/tmp}/dnswatcher-fmt.XXXXXX")"
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
docker build \
|
||||
--target "$stage" \
|
||||
--output "type=local,dest=$tmp/out" \
|
||||
-f Dockerfile.fmt .
|
||||
|
||||
# An empty export means prettier was handed nothing, which must not
|
||||
# read as "already formatted".
|
||||
(cd "$tmp/out" && find . -type f -name '*.md') |
|
||||
sed 's|^\./||' | LC_ALL=C sort >"$tmp/files"
|
||||
|
||||
[ -s "$tmp/files" ] ||
|
||||
die "the formatting build produced no markdown; the build" \
|
||||
"context reached prettier empty"
|
||||
|
||||
# Copied only where the bytes differ, so an already-formatted tree
|
||||
# keeps its timestamps and says nothing.
|
||||
while IFS= read -r f; do
|
||||
[ -n "$f" ] || continue
|
||||
if [ -f "$f" ] && cmp -s "$tmp/out/$f" "$f"; then
|
||||
continue
|
||||
fi
|
||||
cp "$tmp/out/$f" "$f"
|
||||
echo "prettier: reformatted $f"
|
||||
done <"$tmp/files"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user