Restore Markdown formatting in fmt/fmt-check and pin prettier (closes #19)
script/fmt and script/fmt-check now run gofmt for Go and prettier for Markdown; fmt-check reports each independently. prettier is pinned at 3.8.1 by package.json/yarn.lock (integrity hash); .prettierrc and .prettierignore are the house settings copied from the prompts repo. script/bootstrap installs node and yarn from the host package manager and runs `yarn install --frozen-lockfile`. The Markdown check runs in CI via the Dockerfile build stage, where bootstrap provides prettier; it is removed from the lint stage because the golangci-lint image has no node. JS manifests are copied before bootstrap so the yarn layer caches, and node_modules is dockerignored. node is an unpinned host runtime like git/make/go: nvm's glibc node does not run on the musl/Alpine build image, so the canonical nvm route is not usable here; prettier is the hash-pinned formatter. The wholesale Markdown reformat follows in the next commit. Model: opus-4-8
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
sfdupes
|
sfdupes
|
||||||
files.dat
|
files.dat
|
||||||
|
node_modules
|
||||||
*.log
|
*.log
|
||||||
*.out
|
*.out
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
yarn.lock
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 4,
|
||||||
|
"proseWrap": "always"
|
||||||
|
}
|
||||||
+11
-6
@@ -27,9 +27,12 @@ ARG CHECK_EPOCH
|
|||||||
# target now runs `docker build -f Dockerfile.lint`, and a docker build
|
# target now runs `docker build -f Dockerfile.lint`, and a docker build
|
||||||
# cannot run a docker build: routing the gate through make would mean
|
# cannot run a docker build: routing the gate through make would mean
|
||||||
# nesting docker inside this image. Same reason `make check` is gone
|
# nesting docker inside this image. Same reason `make check` is gone
|
||||||
# from the build stage below. `make fmt-check` stays as it is — it is a
|
# from the build stage below.
|
||||||
# gate, not the aggregate, and it shells out to nothing.
|
#
|
||||||
RUN echo "gate fmt-check, epoch ${CHECK_EPOCH}" && make fmt-check
|
# `make fmt-check` is not run in this stage: it now also runs prettier
|
||||||
|
# over Markdown, and this golangci-lint image has no node. The gate runs
|
||||||
|
# in the build stage below, where script/bootstrap installs node and
|
||||||
|
# prettier.
|
||||||
|
|
||||||
# The FROM above and the one in Dockerfile.lint pin the same linter
|
# The FROM above and the one in Dockerfile.lint pin the same linter
|
||||||
# twice, and nothing else keeps them in sync; this fails the build when
|
# twice, and nothing else keeps them in sync; this fails the build when
|
||||||
@@ -77,10 +80,12 @@ COPY --from=lint /src/go.sum /dev/null
|
|||||||
# rather than duplicating the installs inline. Only script/ and the
|
# rather than duplicating the installs inline. Only script/ and the
|
||||||
# dependency manifests are copied first, nothing else, so this layer
|
# dependency manifests are copied first, nothing else, so this layer
|
||||||
# stays cached until the scripts or the dependencies change — bootstrap
|
# stays cached until the scripts or the dependencies change — bootstrap
|
||||||
# ends in `go mod download`, which is why there is no separate
|
# runs `go mod download` and `yarn install`, which is why there is no
|
||||||
# invocation of it here.
|
# separate invocation of either here. The JS manifests (package.json,
|
||||||
|
# yarn.lock) are copied too so the yarn install layer caches alongside
|
||||||
|
# the Go one.
|
||||||
COPY script/ script/
|
COPY script/ script/
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum package.json yarn.lock ./
|
||||||
RUN script/bootstrap
|
RUN script/bootstrap
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
@@ -452,14 +452,18 @@ and may be invoked directly. The provided entrypoints are:
|
|||||||
|
|
||||||
- `script/bootstrap` — install everything needed to build and
|
- `script/bootstrap` — install everything needed to build and
|
||||||
develop this repository, idempotently, assuming nothing is
|
develop this repository, idempotently, assuming nothing is
|
||||||
present. `git`, `make`, and `go` come from the first of nix, apt,
|
present. `git`, `make`, `go`, and `node` come from the first of nix,
|
||||||
brew, or apk found on the host, and are presence-checked only.
|
apt, brew, or apk found on the host, and are presence-checked only;
|
||||||
`golangci-lint` is deliberately **not** installed: it runs from a
|
`node` is an unpinned host runtime like the rest, because nvm's
|
||||||
digest-pinned image via `script/lint` and never from a host
|
prebuilt node is glibc-linked and does not run on this repo's
|
||||||
install, so there is no host copy to drift from the pin. A missing
|
musl/Alpine build image. The Markdown formatter itself — `prettier` —
|
||||||
`docker` is warned about rather than installed or treated as
|
is pinned by `yarn.lock`'s integrity hash and installed with
|
||||||
fatal — everything except linting works without it. Ends with
|
`yarn install --frozen-lockfile`. `golangci-lint` is deliberately
|
||||||
`go mod download`.
|
**not** installed: it runs from a digest-pinned image via
|
||||||
|
`script/lint` and never from a host install, so there is no host copy
|
||||||
|
to drift from the pin. A missing `docker` is warned about rather than
|
||||||
|
installed or treated as fatal — everything except linting works
|
||||||
|
without it. Ends with `go mod download` and the `yarn` install.
|
||||||
- `script/setup` — make a fresh clone ready for development: runs
|
- `script/setup` — make a fresh clone ready for development: runs
|
||||||
`script/bootstrap`, then `script/install-precommit`.
|
`script/bootstrap`, then `script/install-precommit`.
|
||||||
- `script/projectname` — print this project's name (`sfdupes`).
|
- `script/projectname` — print this project's name (`sfdupes`).
|
||||||
@@ -490,10 +494,15 @@ and may be invoked directly. The provided entrypoints are:
|
|||||||
`go.sum` changes and the download layer goes cold again. Because
|
`go.sum` changes and the download layer goes cold again. Because
|
||||||
the daemon only ever sees a build context, this works when the
|
the daemon only ever sees a build context, this works when the
|
||||||
docker daemon is remote and bind mounts are impossible.
|
docker daemon is remote and bind mounts are impossible.
|
||||||
- `script/fmt` — format the Go sources in place (`gofmt -s -w`).
|
- `script/fmt` — format in place: `gofmt -s -w` for Go sources and
|
||||||
Markdown is not formatted.
|
`prettier` for Markdown (`--tab-width 4 --prose-wrap always`, the
|
||||||
- `script/fmt-check` — the read-only counterpart of `script/fmt`:
|
house settings, also carried in `.prettierrc`). prettier is the
|
||||||
prints any unformatted file and exits non-zero instead of writing.
|
pinned devDependency in `package.json`/`yarn.lock`, installed by
|
||||||
|
`script/bootstrap`.
|
||||||
|
- `script/fmt-check` — the read-only counterpart of `script/fmt`: runs
|
||||||
|
both checks, reports each independently so it is clear which failed,
|
||||||
|
and exits non-zero if either found unformatted files instead of
|
||||||
|
writing.
|
||||||
- `script/check` — run `script/test`, `script/lint`, and
|
- `script/check` — run `script/test`, `script/lint`, and
|
||||||
`script/fmt-check`, in that order. Modifies nothing. Needs
|
`script/fmt-check`, in that order. Modifies nothing. Needs
|
||||||
`docker`, because `script/lint` does.
|
`docker`, because `script/lint` does.
|
||||||
@@ -557,8 +566,8 @@ carries the compile recipe:
|
|||||||
`-v` on failure).
|
`-v` on failure).
|
||||||
- `make lint` — run `golangci-lint` with the repo config, in Docker
|
- `make lint` — run `golangci-lint` with the repo config, in Docker
|
||||||
(see `script/lint`); requires `docker`.
|
(see `script/lint`); requires `docker`.
|
||||||
- `make fmt` / `make fmt-check` — format Go sources / verify
|
- `make fmt` / `make fmt-check` — format Go and Markdown sources /
|
||||||
formatting without writing.
|
verify both without writing.
|
||||||
- `make check` — `test`, `lint`, and `fmt-check`; modifies nothing.
|
- `make check` — `test`, `lint`, and `fmt-check`; modifies nothing.
|
||||||
Requires `docker`, via `lint`.
|
Requires `docker`, via `lint`.
|
||||||
- `make docker` — build the Docker image, which runs the gates as
|
- `make docker` — build the Docker image, which runs the gates as
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- restore Markdown formatting in `script/fmt`/`fmt-check` and reformat
|
||||||
|
all Markdown to the house prettier settings (2026-09-21, closes
|
||||||
|
https://git.eeqj.de/sneak/sfdupes/issues/19)
|
||||||
- fix the lint-image pin comments and `FROM` form in `Dockerfile` and
|
- fix the lint-image pin comments and `FROM` form in `Dockerfile` and
|
||||||
`Dockerfile.lint` (2026-08-10, branch `next`, closes
|
`Dockerfile.lint` (2026-08-10, branch `next`, closes
|
||||||
https://git.eeqj.de/sneak/sfdupes/issues/25): dropped the false
|
https://git.eeqj.de/sneak/sfdupes/issues/25): dropped the false
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "3.8.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,12 @@ set -eu
|
|||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
# yarn provides prettier, which formats Markdown. yarn is a tool, like
|
||||||
|
# node/git/make/go below; the reference that governs formatting output is
|
||||||
|
# prettier, pinned by yarn.lock's integrity hash and installed by
|
||||||
|
# `yarn install --frozen-lockfile`.
|
||||||
|
YARN_VERSION="1.22.22"
|
||||||
|
|
||||||
PKGMGR=""
|
PKGMGR=""
|
||||||
SUDO=""
|
SUDO=""
|
||||||
APT_UPDATED=""
|
APT_UPDATED=""
|
||||||
@@ -58,6 +64,21 @@ missing() {
|
|||||||
! command -v "$1" >/dev/null 2>&1
|
! command -v "$1" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_node() {
|
||||||
|
if ! missing node; then return 0; fi
|
||||||
|
pkg_install nodejs nodejs node nodejs
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_yarn() {
|
||||||
|
if ! missing yarn; then return 0; fi
|
||||||
|
if ! missing corepack; then
|
||||||
|
corepack enable >/dev/null 2>&1 || true
|
||||||
|
corepack prepare "yarn@$YARN_VERSION" --activate
|
||||||
|
else
|
||||||
|
pkg_install yarn yarn yarn yarn
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
|
||||||
@@ -71,6 +92,16 @@ main() {
|
|||||||
if missing make; then pkg_install gnumake make make make; fi
|
if missing make; then pkg_install gnumake make make make; fi
|
||||||
if missing go; then pkg_install go golang go go; fi
|
if missing go; then pkg_install go golang go go; fi
|
||||||
|
|
||||||
|
# node runs prettier and is an unpinned host tool for the same reason
|
||||||
|
# git/make/go are: it comes from the host package manager, whatever
|
||||||
|
# version it ships. It is not installed via nvm the way the canonical
|
||||||
|
# template does, because nvm's prebuilt node is glibc-linked and does
|
||||||
|
# not run on this repo's musl/Alpine build image. prettier — the tool
|
||||||
|
# whose version affects formatting output — is pinned by yarn.lock.
|
||||||
|
ensure_node
|
||||||
|
ensure_yarn
|
||||||
|
yarn install --frozen-lockfile
|
||||||
|
|
||||||
# Linting runs via docker only (script/lint), so docker is a lint
|
# Linting runs via docker only (script/lint), so docker is a lint
|
||||||
# prerequisite rather than something bootstrap installs. Warn, do
|
# prerequisite rather than something bootstrap installs. Warn, do
|
||||||
# not fail: everything except `make lint` — and, through it,
|
# not fail: everything except `make lint` — and, through it,
|
||||||
|
|||||||
+12
-1
@@ -1,12 +1,23 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/fmt: format all files (writes).
|
# script/fmt: format all files (writes). gofmt for Go, prettier for
|
||||||
|
# Markdown. prettier is the pinned devDependency in package.json/
|
||||||
|
# yarn.lock; script/bootstrap installs it (see run_prettier).
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
run_prettier() {
|
||||||
|
if ! command -v yarn >/dev/null 2>&1; then
|
||||||
|
echo "fmt: yarn not found; run script/bootstrap first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
yarn run prettier "$@"
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
gofmt -s -w .
|
gofmt -s -w .
|
||||||
|
run_prettier --write '**/*.md' --tab-width 4 --prose-wrap always
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
+21
-2
@@ -1,18 +1,37 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/fmt-check: check formatting (read-only). Same scope as
|
# script/fmt-check: check formatting (read-only). Same scope as
|
||||||
# script/fmt, but fails instead of writing.
|
# script/fmt: gofmt for Go, prettier for Markdown. Both run every time
|
||||||
|
# and each reports independently, so a failure names which formatter is
|
||||||
|
# unhappy; the script exits non-zero if either found unformatted files.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
run_prettier() {
|
||||||
|
if ! command -v yarn >/dev/null 2>&1; then
|
||||||
|
echo "fmt-check: yarn not found; run script/bootstrap first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
yarn run prettier "$@"
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
rc=0
|
||||||
|
|
||||||
files="$(gofmt -s -l .)"
|
files="$(gofmt -s -l .)"
|
||||||
if [ -n "$files" ]; then
|
if [ -n "$files" ]; then
|
||||||
echo "gofmt: files not formatted:" >&2
|
echo "gofmt: files not formatted:" >&2
|
||||||
echo "$files" >&2
|
echo "$files" >&2
|
||||||
exit 1
|
rc=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! run_prettier --check '**/*.md' --tab-width 4 --prose-wrap always; then
|
||||||
|
echo "prettier: Markdown not formatted; run make fmt" >&2
|
||||||
|
rc=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$rc"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
prettier@3.8.1:
|
||||||
|
version "3.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173"
|
||||||
|
integrity sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==
|
||||||
Reference in New Issue
Block a user