From 85f293585a0413067acf24f79dd5485c4abacdb4 Mon Sep 17 00:00:00 2001 From: Juha Kangas <42040080+valuecodes@users.noreply.github.com> Date: Sat, 31 Oct 2026 17:09:14 +0200 Subject: [PATCH] chore: move to maintain-kit v1.0.0 and its secret-scan workflow Co-Authored-By: Claude Opus 5.5 --- .claude/settings.json | 1 - .githooks/pre-commit | 11 ++-- .github/scripts/secrets-scan.sh | 63 ------------------- .github/workflows/checks.yml | 21 ++----- .github/workflows/maintain-kit-dashboard.yml | 19 ++++++ ...e-updates.yml => maintain-kit-updates.yml} | 10 +-- .github/workflows/maintenance-dashboard.yml | 19 ------ AGENTS.md | 47 +++++++------- README.md | 13 ++-- package.json | 1 - 10 files changed, 65 insertions(+), 140 deletions(-) delete mode 100644 .github/scripts/secrets-scan.sh create mode 100644 .github/workflows/maintain-kit-dashboard.yml rename .github/workflows/{maintenance-updates.yml => maintain-kit-updates.yml} (66%) delete mode 100644 .github/workflows/maintenance-dashboard.yml diff --git a/.claude/settings.json b/.claude/settings.json index 86468cf..21648f5 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -8,7 +8,6 @@ "Bash(pnpm format:*)", "Bash(pnpm format:check:*)", "Bash(pnpm test:*)", - "Bash(pnpm secrets:scan:*)", "Bash(pnpm knip:*)", "Bash(pnpm --filter web dev:*)", "Bash(pnpm --filter web build:*)", diff --git a/.githooks/pre-commit b/.githooks/pre-commit index d51cb82..e557485 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -11,7 +11,10 @@ set -eu pnpm format:check pnpm lint -# Scan only what is staged. This fails closed: when neither gitleaks nor Docker -# is available, secrets:scan exits 2 and the commit is refused, since the point -# of this hook is to stop a secret before it reaches the remote. -pnpm secrets:scan --staged +# Scan only what is staged, with a local gitleaks (8.19+ for `git --staged`). +# This fails closed: without gitleaks the commit is refused, since the point of +# this hook is to stop a secret before it reaches the remote. CI scans the full +# history through secret-scan.yml from valuecodes/maintain-kit, which pins the +# gitleaks version. +gitleaks git --help >/dev/null 2>&1 || { echo "install gitleaks 8.19+: https://github.com/gitleaks/gitleaks#installing" >&2; exit 2; } +gitleaks git --staged --redact "$(git rev-parse --show-toplevel)" diff --git a/.github/scripts/secrets-scan.sh b/.github/scripts/secrets-scan.sh deleted file mode 100644 index e0329c4..0000000 --- a/.github/scripts/secrets-scan.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# Scan the repo's git history for committed secrets with gitleaks. -# -# Used by `pnpm secrets:scan` and by the `secrets-scan` CI job, so the pinned -# version below is the single source of truth for both. A local `gitleaks` -# binary is preferred when it is on PATH and new enough to have the `git` -# subcommand (v8.19+); otherwise the pinned Docker image runs instead. Extra -# arguments are passed through to `gitleaks git`, e.g. -# `pnpm secrets:scan --log-opts="origin/main..HEAD"`. -# -# Exit code is gitleaks' own: 0 clean, 1 leaks found. 2 means neither runner -# is available. -set -eu - -GITLEAKS_VERSION="8.30.1" -# Digest of the v$GITLEAKS_VERSION multi-arch image, so a re-pushed tag cannot -# change what runs. Bump both together. -GITLEAKS_DIGEST="sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f" - -repo_root=$(git rev-parse --show-toplevel) - -if command -v gitleaks >/dev/null 2>&1 && gitleaks git --help >/dev/null 2>&1; then - exec gitleaks git --redact --verbose "$@" "$repo_root" -fi - -if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then - # Mount read-only (gitleaks only reads) at the real absolute path, not /repo: - # in a git worktree `.git` is a file pointing at an absolute path inside the - # main checkout's git dir, which therefore has to be mounted at its own path. - git_common_dir=$(cd "$repo_root" && cd "$(git rev-parse --git-common-dir)" && pwd) - set -- -v "$repo_root:$repo_root:ro" \ - "ghcr.io/gitleaks/gitleaks:v$GITLEAKS_VERSION@$GITLEAKS_DIGEST" \ - git --redact --verbose "$@" "$repo_root" - case "$git_common_dir" in - "$repo_root"/*) ;; - *) set -- -v "$git_common_dir:$git_common_dir:ro" "$@" ;; - esac - # Inside a commit hook, `git commit -a` and `git commit ` stage the - # commit in a temporary index named by GIT_INDEX_FILE. A local gitleaks - # inherits it but the container does not, so forward it as an absolute path, - # or `--staged` scans the ordinary index instead. It normally lives in the git - # dir, which the mounts above cover; mount its directory when it does not. - if [ -n "${GIT_INDEX_FILE:-}" ]; then - case "$GIT_INDEX_FILE" in - /*) index_file=$GIT_INDEX_FILE ;; - *) index_file=$PWD/$GIT_INDEX_FILE ;; - esac - index_dir=$(dirname "$index_file") - case "$index_dir" in - "$repo_root" | "$repo_root"/* | "$git_common_dir" | "$git_common_dir"/*) ;; - *) set -- -v "$index_dir:$index_dir:ro" "$@" ;; - esac - set -- -e "GIT_INDEX_FILE=$index_file" "$@" - fi - exec docker run --rm "$@" -fi - -cat >&2 <` branch, for updates on the +`maintain-kit-updates.yml` calls the updates workflow from +`valuecodes/maintain-kit` weekly. It keeps one PR per kind open (Node.js, pnpm, +`catalog:`) on a `maintain-kit/` branch, for updates on the current major only; majors stay manual. Those PRs are opened with `GITHUB_TOKEN`, so their `pull_request` checks wait until someone with write access clicks **Approve workflows to run** in the PR. It needs **Allow GitHub Actions to create and approve @@ -115,10 +114,8 @@ pull requests** turned on under Settings → Actions → General. Nothing auto-m Before merging a Node.js or pnpm update, set the Cloudflare `NODE_VERSION` or `PNPM_VERSION` build variable of the `apps/web` deploy to the new version, so the build of the merge commit already uses it (a newer patch or minor on the old -lockfile is harmless). If `GITLEAKS_VERSION` moves out of -`.github/scripts/secrets-scan.sh`, pass the new path as the `gitleaks-script` input to -both callers. The dashboard, updates and workflow-lint callers pin the same -`valuecodes/automation` commit, so bump them together. +lockfile is harmless). The dashboard, updates, secret-scan and workflow-lint callers +pin the same `valuecodes/maintain-kit` commit, so bump them together. --- diff --git a/README.md b/README.md index a5781e5..93fddf2 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,10 @@ Then open http://localhost:3000. `pnpm install` also turns on the git hooks: format, lint and a staged secrets scan before each commit; typecheck, tests and Knip before each push. Committing needs -`gitleaks` v8.19+ on PATH or a running Docker daemon for the staged secrets scan. +`gitleaks` v8.19+ on PATH for the staged secrets scan: `brew install gitleaks` (macOS, +Linux and WSL), or unpack the `linux_x64` tarball from the +[releases page](https://github.com/gitleaks/gitleaks/releases) into a directory on PATH +such as `~/.local/bin`. ## How it works @@ -132,7 +135,6 @@ pnpm test # test suite pnpm build # production builds pnpm format # oxfmt write pnpm format:check # oxfmt check (CI gate) -pnpm secrets:scan # gitleaks secret scan over git history ``` oxlint prints nothing when there are no findings, so silent output means clean. @@ -141,8 +143,7 @@ CI runs typecheck, lint, knip, format:check, test, build and a gitleaks secret s PRs and on push to `main`, plus CodeQL code scanning and actionlint + zizmor over the workflow files. The checks live once in `checks.yml`, called by `feature.yml` (PRs) and `main.yml` (push to `main`). The `all-passed` job fans them in: -require only that check in branch protection. `secrets:scan` needs either `gitleaks` -v8.19+ on PATH or a running Docker daemon. +require only that check in branch protection. The repository settings this CI expects: @@ -153,8 +154,8 @@ The repository settings this CI expects: 3. **Code security → Dependabot**: **alerts** on, **security updates** off. `.github/dependabot.yml` only bumps the SHA-pinned GitHub Actions monthly; npm dependencies are updated by hand. -4. **Issues**: the `Maintenance dashboard` workflow keeps one pinned issue listing the - updates that are due. Run it once by hand (**Actions → Maintenance dashboard → Run +4. **Issues**: the `Maintain-kit dashboard` workflow keeps one pinned issue listing the + updates that are due. Run it once by hand (**Actions → Maintain-kit dashboard → Run workflow**) to create it. ## Limits diff --git a/package.json b/package.json index 171234c..32e3378 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "format": "oxfmt", "format:check": "oxfmt --check", "knip": "knip", - "secrets:scan": "sh .github/scripts/secrets-scan.sh", "clean": "turbo run clean", "prepare": "git rev-parse --git-dir >/dev/null 2>&1 && git config --local core.hooksPath .githooks || true" },