Adopt scripts-to-rule-them-all: script/ entrypoints, Makefile shims
This commit is contained in:
@@ -6,5 +6,5 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# actions/checkout v4.2.2, 2026-02-22
|
# actions/checkout v4.2.2, 2026-02-22
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||||
- run: docker build .
|
- run: script/cibuild
|
||||||
- run: docker build -f Dockerfile.backend .
|
- run: docker build -f Dockerfile.backend .
|
||||||
|
|||||||
28
Makefile
28
Makefile
@@ -1,21 +1,35 @@
|
|||||||
.PHONY: dev test lint fmt fmt-check check docker
|
.PHONY: bootstrap setup dev test lint fmt fmt-check check docker hooks
|
||||||
|
|
||||||
|
# Standard targets are thin shims; the implementations live in script/
|
||||||
|
# per the scripts-to-rule-them-all pattern (see the Entrypoints section
|
||||||
|
# of README.md).
|
||||||
|
|
||||||
|
bootstrap:
|
||||||
|
@script/bootstrap
|
||||||
|
|
||||||
|
setup:
|
||||||
|
@script/setup
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
yarn dev
|
yarn dev
|
||||||
|
|
||||||
test:
|
test:
|
||||||
timeout 30 yarn build
|
@script/test
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
yarn prettier --check .
|
@script/lint
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
yarn prettier --write .
|
@script/fmt
|
||||||
|
|
||||||
fmt-check:
|
fmt-check:
|
||||||
yarn prettier --check .
|
@script/fmt-check
|
||||||
|
|
||||||
check: test lint fmt-check
|
check:
|
||||||
|
@script/check
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
timeout 300 docker build -t netwatch .
|
@script/docker
|
||||||
|
|
||||||
|
hooks:
|
||||||
|
@script/install-precommit
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -23,6 +23,29 @@ docker build -t netwatch .
|
|||||||
docker run -p 8080:8080 netwatch
|
docker run -p 8080:8080 netwatch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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. We
|
||||||
|
provide:
|
||||||
|
|
||||||
|
- `script/bootstrap` — install all dependencies (pinned node via nvm if needed,
|
||||||
|
yarn via corepack, `yarn install --frozen-lockfile`)
|
||||||
|
- `script/setup` — make a fresh clone ready for development: bootstrap plus the
|
||||||
|
git pre-commit hook
|
||||||
|
- `script/projectname` — print the project name (used for the Docker image tag)
|
||||||
|
- `script/test` — run the production build as the test (no unit tests yet)
|
||||||
|
- `script/lint` — run prettier in check mode
|
||||||
|
- `script/fmt` — format all files (writes)
|
||||||
|
- `script/fmt-check` — check formatting (read-only)
|
||||||
|
- `script/check` — run test, lint, and fmt-check
|
||||||
|
- `script/docker` — build the Docker image tagged via `script/projectname`
|
||||||
|
- `script/cibuild` — CI entrypoint: plain `docker build .`
|
||||||
|
- `script/precommit` — run by the git pre-commit hook; runs `script/check`
|
||||||
|
- `script/install-precommit` — install the git pre-commit hook
|
||||||
|
|
||||||
## Rationale
|
## Rationale
|
||||||
|
|
||||||
When debugging network issues, it's useful to have a persistent at-a-glance view
|
When debugging network issues, it's useful to have a persistent at-a-glance view
|
||||||
|
|||||||
64
TODO.md
64
TODO.md
@@ -1,47 +1,47 @@
|
|||||||
# Workflow
|
# Workflow
|
||||||
|
|
||||||
* branch (from `main`)
|
- branch (from `main`)
|
||||||
* do the work in Next Step
|
- do the work in Next Step
|
||||||
* move Next Step to the top of Completed Steps
|
- move Next Step to the top of Completed Steps
|
||||||
* move the top item of Future Steps into Next Step
|
- move the top item of Future Steps into Next Step
|
||||||
* commit (`TODO.md` changes in the same commit as the work)
|
- commit (`TODO.md` changes in the same commit as the work)
|
||||||
* merge to `main` if the branch is not protected, otherwise open a PR
|
- merge to `main` if the branch is not protected, otherwise open a PR
|
||||||
* push
|
- push
|
||||||
|
|
||||||
# Status
|
# Status
|
||||||
|
|
||||||
pre-1.0. No git tags. Backend work in flight on feat/reportbuf-storage
|
pre-1.0. No git tags. Backend work in flight on feat/reportbuf-storage (dirty:
|
||||||
(dirty: src/main.js). Frontend is functional; backend is new and unmerged.
|
src/main.js). Frontend is functional; backend is new and unmerged.
|
||||||
|
|
||||||
# Next Step
|
# Next Step
|
||||||
|
|
||||||
Land feat/reportbuf-storage: finish the in-progress src/main.js change,
|
Land feat/reportbuf-storage: finish the in-progress src/main.js change, get make
|
||||||
get make check green, and merge the branch to main. The branch adds the
|
check green, and merge the branch to main. The branch adds the backend (buffered
|
||||||
backend (buffered zstd-compressed report storage), the CI workflow, and
|
zstd-compressed report storage), the CI workflow, and backend repo standard
|
||||||
backend repo standard files, so merging it also closes most compliance
|
files, so merging it also closes most compliance gaps.
|
||||||
gaps.
|
|
||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
- 2026-02-27: backend with buffered zstd-compressed report storage; CI
|
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
|
||||||
workflow and backend repo standard files; backend Dockerfile fixed (Go
|
shims, README Entrypoints section
|
||||||
1.25, golangci-lint) and moved to repo root (feat/reportbuf-storage,
|
- 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow
|
||||||
unmerged)
|
and backend repo standard files; backend Dockerfile fixed (Go 1.25,
|
||||||
- 2026-02-26: host row layout redesigned with CSS grid; overflow and
|
golangci-lint) and moved to repo root (feat/reportbuf-storage, unmerged)
|
||||||
spacing fixes; nginx config extracted; port hardcoded to 8080
|
- 2026-02-26: host row layout redesigned with CSS grid; overflow and spacing
|
||||||
- 2026-02-26: debug log panel, median stats, recovery probe, Docker
|
fixes; nginx config extracted; port hardcoded to 8080
|
||||||
build fix, S3 Singapore endpoint added
|
- 2026-02-26: debug log panel, median stats, recovery probe, Docker build fix,
|
||||||
- 2026-02-23: summary box redesign, host pinning, local and UTC clocks,
|
S3 Singapore endpoint added
|
||||||
checks counter
|
- 2026-02-23: summary box redesign, host pinning, local and UTC clocks, checks
|
||||||
- 2026-02-23: hosts sorted by latency; GET instead of HEAD for latency;
|
counter
|
||||||
timeout derived from interval; Hetzner regional endpoints; 3s interval
|
- 2026-02-23: hosts sorted by latency; GET instead of HEAD for latency; timeout
|
||||||
|
derived from interval; Hetzner regional endpoints; 3s interval
|
||||||
- 2026-01-29: initial NetWatch network latency monitor
|
- 2026-01-29: initial NetWatch network latency monitor
|
||||||
|
|
||||||
# Future Steps
|
# Future Steps
|
||||||
|
|
||||||
- Compliance top-up as one small commit: add .editorconfig and add the
|
- Compliance top-up as one small commit: add .editorconfig and add the hooks
|
||||||
hooks target to the Makefile
|
target to the Makefile
|
||||||
- After merge, confirm .gitea/workflows/check.yml is on main and CI is
|
- After merge, confirm .gitea/workflows/check.yml is on main and CI is green
|
||||||
green (main always green policy)
|
(main always green policy)
|
||||||
- Decide what to do with untracked resume.sh: commit it, gitignore it,
|
- Decide what to do with untracked resume.sh: commit it, gitignore it, or delete
|
||||||
or delete it
|
it
|
||||||
|
|||||||
143
script/bootstrap
Executable file
143
script/bootstrap
Executable file
@@ -0,0 +1,143 @@
|
|||||||
|
#!/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. 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-07
|
||||||
|
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=""
|
||||||
|
|
||||||
|
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)
|
||||||
|
if [ -z "$APT_UPDATED" ]; then
|
||||||
|
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get update
|
||||||
|
APT_UPDATED=1
|
||||||
|
fi
|
||||||
|
$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
|
||||||
|
}
|
||||||
|
|
||||||
|
# verify_sha256 <file> <expected-hash>
|
||||||
|
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"
|
||||||
|
|
||||||
|
if missing make; then pkg_install gnumake make make make; fi
|
||||||
|
if missing git; then pkg_install git git git git; fi
|
||||||
|
|
||||||
|
ensure_node
|
||||||
|
ensure_yarn
|
||||||
|
install_js_deps
|
||||||
|
|
||||||
|
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 make 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.
|
||||||
|
# The tag comes from script/projectname.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||||
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
timeout 300 docker build -t "$("$SCRIPT_DIR/projectname")" .
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
12
script/fmt
Executable file
12
script/fmt
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/fmt: format all files (writes).
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
yarn prettier --write .
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
13
script/fmt-check
Executable file
13
script/fmt-check
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/fmt-check: check formatting (read-only). Same scope as
|
||||||
|
# script/fmt, but fails instead of writing.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
yarn prettier --check .
|
||||||
|
}
|
||||||
|
|
||||||
|
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' > "$hook"
|
||||||
|
chmod +x "$hook"
|
||||||
|
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 (prettier in check mode).
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
yarn prettier --check .
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
12
script/precommit
Executable file
12
script/precommit
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/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)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
"$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 "netwatch"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "$@"
|
||||||
13
script/test
Executable file
13
script/test
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# script/test: run the test suite. This repo has no unit tests; the
|
||||||
|
# production build serves as the test (fails on broken code).
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$ROOT"
|
||||||
|
timeout 30 yarn build
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user