From 47e48a2529f0a1888a69c205c861597b5251affe Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 6 Oct 2026 06:30:59 +0000 Subject: [PATCH] Format Markdown with prettier in script/fmt and script/fmt-check (refs #7) script/fmt now also runs prettier over every Markdown file, and script/fmt-check checks them without writing. prettier is pinned in package.json and yarn.lock. script/bootstrap keeps its Go and apt handling and gains the canonical pinned node (nvm from a hash-checked archive) and yarn (corepack) install, then installs the locked packages. Both fmt scripts find yarn the canonical way, sourcing nvm when yarn is not on PATH. The new files and the yarn lookup come from sneak/prompts at cc440118c876. The vendored REPO_POLICIES.md already passes prettier, so it is not ignored. The Markdown is reformatted in the next commit. Deviation: package.json drops the canonical "license": "MIT" line; this repo is WTFPL. Model: opus-5-5 --- .prettierignore | 2 ++ .prettierrc | 4 +++ README.md | 12 +++++--- TODO.md | 6 ++-- package.json | 5 +++ script/bootstrap | 80 +++++++++++++++++++++++++++++++++++++++++++++++- script/fmt | 24 ++++++++++++++- script/fmt-check | 24 ++++++++++++++- yarn.lock | 8 +++++ 9 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..23d67fc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +node_modules/ +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..8af31cd --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 4, + "proseWrap": "always" +} diff --git a/README.md b/README.md index 3888c6e..ffaa996 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ Primary development happens on a privately-run Gitea instance at issues are [tracked there](https://git.eeqj.de/sneak/bsdaily/issues). -Changes must always be formatted with a standard `go fmt`, syntactically +Changes must always be formatted with `make fmt` (`go fmt` for Go, +prettier for Markdown), syntactically valid, and must pass the linting defined in the repository (presently the `golangci-lint` defaults), which can be run with a `make lint`. The `main` branch is protected and all changes must be made via [pull @@ -54,7 +55,8 @@ development workflow, and the Makefile targets are thin shims that call them. We provide: - `script/bootstrap` — install all development dependencies (go, Go - module download); the linter is not installed on the host + module download, a pinned node and yarn, and the prettier pinned in + `package.json` and `yarn.lock`); the linter is not installed on the host - `script/setup` — make a fresh clone ready for development: runs `script/bootstrap`, then `script/install-precommit` - `script/projectname` — print the project name (used for the Docker @@ -63,8 +65,10 @@ them. We provide: test suite with `-race` (verbose rerun on failure) - `script/lint` — build the Dockerfile's `lint` phase, which runs `golangci-lint run ./...` -- `script/fmt` — format the Go code with `go fmt` (writes) -- `script/fmt-check` — check the Go formatting with `gofmt` (read-only) +- `script/fmt` — format the Go code with `go fmt` and every Markdown + file with prettier (writes) +- `script/fmt-check` — check the Go formatting with `gofmt` and the + Markdown formatting with prettier (read-only) - `script/check` — run `script/test`, `script/lint`, and `script/fmt-check` - `script/docker` — build the Docker image tagged via diff --git a/TODO.md b/TODO.md index 92ae9e3..3dbdad7 100644 --- a/TODO.md +++ b/TODO.md @@ -20,6 +20,10 @@ v2.14.0 in the same commit, and fix the findings it surfaces # Completed Steps +- 2026-10-06: Formatted Markdown with prettier: `script/fmt` writes and + `script/fmt-check` checks every Markdown file; prettier pinned in + `package.json` and `yarn.lock`, installed by `script/bootstrap` with a + pinned node and yarn; existing Markdown reformatted. - 2026-10-05: Brought the repo up to the standard layout: canonical `.gitignore`, `.dockerignore` and `.editorconfig`; `lint` and `test` phases in the `Dockerfile`, built by `script/lint` and `script/test`; @@ -41,8 +45,6 @@ v2.14.0 in the same commit, and fix the findings it surfaces # Future Steps -- Format Markdown with prettier in `script/fmt` and `script/fmt-check` - (https://git.eeqj.de/sneak/bsdaily/issues/7). - Expand tests beyond the compilation smoke test: unit tests for the extraction, verification, and atomic-publish paths. - Cut a first SemVer release once compliance and test coverage land. diff --git a/package.json b/package.json new file mode 100644 index 0000000..dc05cde --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "prettier": "3.8.1" + } +} diff --git a/script/bootstrap b/script/bootstrap index 4dcdcd7..d2f0739 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -3,11 +3,20 @@ # this repo. Idempotent: every install is guarded by a check so already # installed tools are skipped. Base tooling comes from nix, apt, brew, # or apk (detected in that order); assumes NOTHING is present (not git, -# make, or go). +# make, go, or node). Node is used directly if installed; otherwise it +# is installed at a pinned version via nvm (installing nvm itself first, +# from a hash-verified release archive, never curl | sh). set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +# Pinned versions, 2026-07-06 +NODE_VERSION="22.17.0" +NVM_VERSION="0.40.3" +# sha256 of https://github.com/nvm-sh/nvm/archive/refs/tags/v0.40.3.tar.gz +NVM_SHA256="5f4d6aaa04a177dc93c985e31dbc411ab6b8c6e1e21d8015dbc1372625fcd1d0" +YARN_VERSION="1.22.22" + PKGMGR="" SUDO="" APT_UPDATED="" @@ -56,6 +65,69 @@ missing() { ! command -v "$1" >/dev/null 2>&1 } +# verify_sha256 +verify_sha256() { + if command -v sha256sum >/dev/null 2>&1; then + actual="$(sha256sum "$1" | cut -d' ' -f1)" + else + actual="$(shasum -a 256 "$1" | cut -d' ' -f1)" + fi + if [ "$actual" != "$2" ]; then + echo "bootstrap: sha256 mismatch for $1" >&2 + echo " expected: $2" >&2 + echo " actual: $actual" >&2 + exit 1 + fi +} + +# nvm is a bash script; run a command in a bash with nvm loaded +nvm_sh() { + bash -c ". \"\$HOME/.nvm/nvm.sh\" && $*" +} + +ensure_nvm() { + [ -s "$HOME/.nvm/nvm.sh" ] && return 0 + # nvm prerequisites; nvm itself requires bash + if missing bash; then pkg_install bash bash bash bash; fi + if missing curl; then pkg_install curl curl curl curl; fi + if missing git; then pkg_install git git git git; fi + tmp="$(mktemp -d)" + curl -fsSL -o "$tmp/nvm.tar.gz" \ + "https://github.com/nvm-sh/nvm/archive/refs/tags/v${NVM_VERSION}.tar.gz" + verify_sha256 "$tmp/nvm.tar.gz" "$NVM_SHA256" + mkdir -p "$HOME/.nvm" + tar -xzf "$tmp/nvm.tar.gz" -C "$HOME/.nvm" --strip-components=1 + rm -rf "$tmp" +} + +ensure_node() { + if ! missing node; then return 0; fi + ensure_nvm + nvm_sh "nvm install $NODE_VERSION" +} + +ensure_yarn() { + if ! missing yarn; then return 0; fi + if ! missing corepack; then + corepack enable + corepack prepare "yarn@$YARN_VERSION" --activate + elif [ -s "$HOME/.nvm/nvm.sh" ]; then + nvm_sh "nvm use $NODE_VERSION >/dev/null && corepack enable && \ + corepack prepare yarn@$YARN_VERSION --activate" + else + npm install -g "yarn@$YARN_VERSION" + fi +} + +install_js_deps() { + if missing yarn && [ -s "$HOME/.nvm/nvm.sh" ]; then + nvm_sh "nvm use $NODE_VERSION >/dev/null && cd \"$ROOT\" && \ + yarn install --frozen-lockfile" + else + yarn install --frozen-lockfile + fi +} + main() { cd "$ROOT" @@ -68,6 +140,12 @@ main() { go mod download + # Node and yarn, then the prettier pinned in package.json and + # yarn.lock, which script/fmt and script/fmt-check run + ensure_node + ensure_yarn + install_js_deps + echo "bootstrap complete" } diff --git a/script/fmt b/script/fmt index e95d111..99e1272 100755 --- a/script/fmt +++ b/script/fmt @@ -1,12 +1,34 @@ #!/bin/sh -# script/fmt: format all files (writes). +# script/fmt: format all files (writes): the Go code with go fmt and +# every Markdown file with prettier. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +# Must match the pin in script/bootstrap. +NODE_VERSION="22.17.0" + +# script/bootstrap installs node and yarn under nvm and leaves neither +# on the PATH of the shell that called it, so resolve the pinned +# toolchain here the way bootstrap's own install step does. nvm is a +# bash script, hence the subshell. +run_yarn() { + if command -v yarn >/dev/null 2>&1; then + exec yarn "$@" + fi + if [ ! -s "$HOME/.nvm/nvm.sh" ]; then + echo "fmt: no yarn; run script/bootstrap first" >&2 + exit 1 + fi + exec bash -c '. "$HOME/.nvm/nvm.sh" && nvm use "$1" >/dev/null && + shift && exec yarn "$@"' bash "$NODE_VERSION" "$@" +} + main() { cd "$ROOT" go fmt ./... + # run_yarn replaces this shell, so it stays the last step. + run_yarn run prettier --write '**/*.md' --tab-width 4 --prose-wrap always } main "$@" diff --git a/script/fmt-check b/script/fmt-check index 57e8e5c..0a6e935 100755 --- a/script/fmt-check +++ b/script/fmt-check @@ -1,10 +1,30 @@ #!/bin/sh # script/fmt-check: check formatting (read-only). Same scope as -# script/fmt, but fails instead of writing. +# script/fmt, the Go code and every Markdown file, but fails instead of +# writing. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +# Must match the pin in script/bootstrap. +NODE_VERSION="22.17.0" + +# script/bootstrap installs node and yarn under nvm and leaves neither +# on the PATH of the shell that called it, so resolve the pinned +# toolchain here the way bootstrap's own install step does. nvm is a +# bash script, hence the subshell. +run_yarn() { + if command -v yarn >/dev/null 2>&1; then + exec yarn "$@" + fi + if [ ! -s "$HOME/.nvm/nvm.sh" ]; then + echo "fmt-check: no yarn; run script/bootstrap first" >&2 + exit 1 + fi + exec bash -c '. "$HOME/.nvm/nvm.sh" && nvm use "$1" >/dev/null && + shift && exec yarn "$@"' bash "$NODE_VERSION" "$@" +} + main() { cd "$ROOT" unformatted="$(gofmt -l .)" @@ -13,6 +33,8 @@ main() { echo "$unformatted" >&2 exit 1 fi + # run_yarn replaces this shell, so it stays the last step. + run_yarn run prettier --check '**/*.md' --tab-width 4 --prose-wrap always } main "$@" diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..d846639 --- /dev/null +++ b/yarn.lock @@ -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==