Adopt scripts-to-rule-them-all: script/ entrypoints, Makefile shims
This commit is contained in:
@@ -9,4 +9,4 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: docker build .
|
- run: script/cibuild
|
||||||
|
|||||||
28
Makefile
28
Makefile
@@ -1,28 +1,30 @@
|
|||||||
.PHONY: test fmt fmt-check lint check docker hooks
|
.PHONY: bootstrap setup test fmt fmt-check lint check docker hooks
|
||||||
|
|
||||||
default: check
|
default: check
|
||||||
|
|
||||||
|
bootstrap:
|
||||||
|
@script/bootstrap
|
||||||
|
|
||||||
|
setup:
|
||||||
|
@script/setup
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@go test -v ./...
|
@script/test
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
goimports -l -w .
|
@script/fmt
|
||||||
golangci-lint run --fix
|
|
||||||
|
|
||||||
fmt-check:
|
fmt-check:
|
||||||
@test -z "$$(gofmt -l .)" || { echo "gofmt would reformat:"; gofmt -l .; exit 1; }
|
@script/fmt-check
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
golangci-lint run
|
@script/lint
|
||||||
|
|
||||||
check: fmt-check lint test
|
check:
|
||||||
|
@script/check
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
docker build --progress plain .
|
@script/docker
|
||||||
|
|
||||||
hooks:
|
hooks:
|
||||||
@echo "Installing git hooks..."
|
@script/install-precommit
|
||||||
@mkdir -p .git/hooks
|
|
||||||
@printf '#!/bin/sh\nmake check\n' > .git/hooks/pre-commit
|
|
||||||
@chmod +x .git/hooks/pre-commit
|
|
||||||
@echo "Pre-commit hook installed."
|
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -60,6 +60,40 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Entrypoints
|
||||||
|
|
||||||
|
This repository adheres to the
|
||||||
|
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
|
||||||
|
standard: normalized scripts in `script/` are the entrypoints for the
|
||||||
|
development workflow, and the Makefile targets are thin shims that call them.
|
||||||
|
The scripts are POSIX sh (not bash) so they run in minimal containers such as
|
||||||
|
alpine. We provide:
|
||||||
|
|
||||||
|
- `script/bootstrap` — install all dependencies (go and golangci-lint if
|
||||||
|
missing, then `go mod download`)
|
||||||
|
- `script/setup` — set up the repo for development after a fresh clone: runs
|
||||||
|
`script/bootstrap`, then `script/install-precommit`
|
||||||
|
- `script/projectname` — output the project name (our own extension); used by
|
||||||
|
`script/docker` for the image tag
|
||||||
|
- `script/test` — run the test suite (`go test -v ./...`)
|
||||||
|
- `script/lint` — run golangci-lint
|
||||||
|
- `script/fmt` — format all files (goimports plus `golangci-lint run --fix`;
|
||||||
|
writes)
|
||||||
|
- `script/fmt-check` — check formatting (read-only); fails if `gofmt -l`
|
||||||
|
reports files
|
||||||
|
- `script/check` — run all checks: `test`, `lint`, `fmt-check` (our own
|
||||||
|
extension)
|
||||||
|
- `script/docker` — build the Docker image, tagged via `script/projectname`
|
||||||
|
(byte-identical across repos)
|
||||||
|
- `script/cibuild` — cd to the repo root and `docker build .` (what CI runs;
|
||||||
|
the image build runs the checks)
|
||||||
|
- `script/precommit` — run by the git pre-commit hook (our own extension);
|
||||||
|
runs a `go mod tidy` guard, then `script/check`
|
||||||
|
- `script/install-precommit` — installs the git pre-commit hook (our own
|
||||||
|
extension); `make hooks` shims to it
|
||||||
|
|
||||||
|
`make hooks` installs the pre-commit hook that runs `script/precommit`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[WTFPL](./LICENSE)
|
[WTFPL](./LICENSE)
|
||||||
|
|||||||
2
TODO.md
2
TODO.md
@@ -24,6 +24,8 @@ files it depends on: .golangci.yml, REPO_POLICIES.md, .editorconfig,
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints,
|
||||||
|
Makefile shims, README Entrypoints section
|
||||||
* 2026-02-08: fixed JSONHandler deadlock from recursive log.Println,
|
* 2026-02-08: fixed JSONHandler deadlock from recursive log.Println,
|
||||||
with regression test; tagged 1.0.1
|
with regression test; tagged 1.0.1
|
||||||
* 2024-06-14: 1.0 prep: lint and fmt enforced in Docker build, call
|
* 2024-06-14: 1.0 prep: lint and fmt enforced in Docker build, call
|
||||||
|
|||||||
69
script/bootstrap
Executable file
69
script/bootstrap
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/bootstrap: install all dependencies needed to build and develop
|
||||||
|
# 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.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
PKGMGR=""
|
||||||
|
SUDO=""
|
||||||
|
|
||||||
|
detect_pkgmgr() {
|
||||||
|
[ -n "$PKGMGR" ] && return 0
|
||||||
|
if command -v nix-env >/dev/null 2>&1; then
|
||||||
|
PKGMGR="nix"
|
||||||
|
elif command -v apt-get >/dev/null 2>&1; then
|
||||||
|
PKGMGR="apt"
|
||||||
|
elif command -v brew >/dev/null 2>&1; then
|
||||||
|
PKGMGR="brew"
|
||||||
|
elif command -v apk >/dev/null 2>&1; then
|
||||||
|
PKGMGR="apk"
|
||||||
|
else
|
||||||
|
echo "bootstrap: no supported package manager (nix, apt, brew, apk)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$PKGMGR" = "apt" ]; then
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
SUDO="sudo"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# pkg_install <nix-attr> <apt-pkg> <brew-formula> <apk-pkg>
|
||||||
|
pkg_install() {
|
||||||
|
detect_pkgmgr
|
||||||
|
case "$PKGMGR" in
|
||||||
|
nix) nix-env -iA "nixpkgs.$1" ;;
|
||||||
|
apt) $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2" ;;
|
||||||
|
brew) brew install "$3" ;;
|
||||||
|
apk) apk add --no-cache "$4" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
missing() {
|
||||||
|
! command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
if missing make; then pkg_install gnumake make make make; fi
|
||||||
|
if missing git; then pkg_install git git git git; fi
|
||||||
|
|
||||||
|
if missing go; then pkg_install go golang go go; fi
|
||||||
|
# golangci-lint is packaged in nix, brew, and apk; there is no apt
|
||||||
|
# package (on apt hosts, install it from a hash-verified GitHub
|
||||||
|
# release archive manually, never curl | sh).
|
||||||
|
if missing golangci-lint; then
|
||||||
|
pkg_install golangci-lint golangci-lint golangci-lint golangci-lint
|
||||||
|
fi
|
||||||
|
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
echo "bootstrap complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
14
script/check
Executable file
14
script/check
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/check: run all checks (test, lint, fmt-check). Our own
|
||||||
|
# extension to scripts-to-rule-them-all. Must not modify any files.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
"$SCRIPT_DIR/test"
|
||||||
|
"$SCRIPT_DIR/lint"
|
||||||
|
"$SCRIPT_DIR/fmt-check"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
13
script/cibuild
Executable file
13
script/cibuild
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/cibuild: run the CI build. The Dockerfile runs script/check, so
|
||||||
|
# a successful build implies all checks pass.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
docker build .
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
14
script/docker
Executable file
14
script/docker
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/docker: build the Docker image tagged with the project name.
|
||||||
|
# Identical in all repos; the tag comes from script/projectname.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
docker build -t "$("$SCRIPT_DIR/projectname")" .
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
13
script/fmt
Executable file
13
script/fmt
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/fmt: format all files (writes).
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
goimports -l -w .
|
||||||
|
golangci-lint run --fix
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
18
script/fmt-check
Executable file
18
script/fmt-check
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/fmt-check: check formatting (read-only). Fails and lists the
|
||||||
|
# offending files if gofmt would reformat anything.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
unformatted="$(gofmt -l .)"
|
||||||
|
if [ -n "$unformatted" ]; then
|
||||||
|
echo "gofmt would reformat:"
|
||||||
|
echo "$unformatted"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
16
script/install-precommit
Executable file
16
script/install-precommit
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/install-precommit: install the git pre-commit hook that runs
|
||||||
|
# script/precommit. Our own extension to scripts-to-rule-them-all.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
hook=".git/hooks/pre-commit"
|
||||||
|
printf '#!/bin/sh\nset -e\nscript/precommit\n' > .git/hooks/pre-commit
|
||||||
|
chmod +x .git/hooks/pre-commit
|
||||||
|
echo "pre-commit hook installed: runs script/precommit"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
12
script/lint
Executable file
12
script/lint
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/lint: run the linter.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
golangci-lint run
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
19
script/precommit
Executable file
19
script/precommit
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/precommit: run by the git pre-commit hook; fails the commit if
|
||||||
|
# checks fail. Our own extension to scripts-to-rule-them-all.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
go mod tidy
|
||||||
|
git diff --exit-code -- go.mod go.sum || {
|
||||||
|
echo "go mod tidy changed go.mod/go.sum; stage the changes and retry" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
"$SCRIPT_DIR/check"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
12
script/projectname
Executable file
12
script/projectname
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/projectname: output the name of this project. Our own
|
||||||
|
# extension to scripts-to-rule-them-all. Other scripts that need the
|
||||||
|
# name (e.g. script/docker) call this, so they can stay identical
|
||||||
|
# across all repos.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
main() {
|
||||||
|
echo "simplelog"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
13
script/setup
Executable file
13
script/setup
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/setup: set up the repo for development after a fresh clone:
|
||||||
|
# installs dependencies and the git pre-commit hook.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
"$SCRIPT_DIR/bootstrap"
|
||||||
|
"$SCRIPT_DIR/install-precommit"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
12
script/test
Executable file
12
script/test
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/test: run the test suite.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
go test -v ./...
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user