From 6668157c994ee72f575cfe8bac48d4baa5f2ef05 Mon Sep 17 00:00:00 2001 From: Juha Kangas <42040080+valuecodes@users.noreply.github.com> Date: Fri, 30 Oct 2026 09:55:16 +0200 Subject: [PATCH 1/2] chore: add maintenance updates workflow and pin automation v0.8.0 Port the maintenance-updates caller from the starter: one PR per update kind (Node.js, pnpm, gitleaks, catalog) on the current major. Move saveExact from .npmrc into pnpm-workspace.yaml, since pnpm 12 reads only auth settings from .npmrc, and add engineStrict. Pin the dashboard, updates and workflow-lint callers to automation v0.8.0. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/checks.yml | 2 +- .github/workflows/maintenance-dashboard.yml | 2 +- .github/workflows/maintenance-updates.yml | 24 +++++++++++++++++ .npmrc | 5 ---- AGENTS.md | 30 ++++++++++++++------- apps/web/AGENTS.md | 3 ++- apps/web/README.md | 8 +++--- package.json | 3 +-- pnpm-workspace.yaml | 9 +++++++ 9 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/maintenance-updates.yml delete mode 100644 .npmrc diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c4ecd61..525b5c8 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -104,4 +104,4 @@ jobs: workflow-lint: permissions: contents: read - uses: valuecodes/automation/.github/workflows/workflow-lint.yml@c207ce5866c0f7893ecc481f596edd7fe7cfae62 # v0.4.0 + uses: valuecodes/automation/.github/workflows/workflow-lint.yml@27353e6fad6ba1f837490d0daab7c7cc7112d7ca # v0.8.0 diff --git a/.github/workflows/maintenance-dashboard.yml b/.github/workflows/maintenance-dashboard.yml index 2e87ab8..e6923d2 100644 --- a/.github/workflows/maintenance-dashboard.yml +++ b/.github/workflows/maintenance-dashboard.yml @@ -16,4 +16,4 @@ jobs: permissions: contents: read issues: write - uses: valuecodes/automation/.github/workflows/maintenance-dashboard.yml@c207ce5866c0f7893ecc481f596edd7fe7cfae62 # v0.4.0 + uses: valuecodes/automation/.github/workflows/maintenance-dashboard.yml@27353e6fad6ba1f837490d0daab7c7cc7112d7ca # v0.8.0 diff --git a/.github/workflows/maintenance-updates.yml b/.github/workflows/maintenance-updates.yml new file mode 100644 index 0000000..8f2c62b --- /dev/null +++ b/.github/workflows/maintenance-updates.yml @@ -0,0 +1,24 @@ +name: Maintenance updates + +on: + schedule: + # Weekly on Monday, after the daily dashboard run. An off-peak minute avoids + # the top-of-the-hour queue. + - cron: "17 6 * * 1" + workflow_dispatch: + +permissions: {} + +jobs: + # Keeps one PR per update kind (Node.js, pnpm, gitleaks, catalog) open for + # updates on the current major. Nothing auto-merges. The PRs are opened with + # GITHUB_TOKEN, so their `pull_request` checks wait for someone with write + # access to approve them in the PR. A called workflow cannot raise the + # caller's token, so the job grants it here. + maintenance-updates: + permissions: + contents: write # push the update branches + pull-requests: write # open, edit and close the PRs + actions: write # required by the called job even without ci-workflow + issues: read # link the dashboard issue + uses: valuecodes/automation/.github/workflows/maintenance-updates.yml@27353e6fad6ba1f837490d0daab7c7cc7112d7ca # v0.8.0 diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 05ddaaf..0000000 --- a/.npmrc +++ /dev/null @@ -1,5 +0,0 @@ -# Don't use caret (^) or tilde (~) in package versions -save-prefix= - -# Always save exact versions -save-exact=true diff --git a/AGENTS.md b/AGENTS.md index 6346648..8f96072 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,7 +37,7 @@ and inside an app use the `~/` alias (`src/*`) to go up the tree. ## Commands -**Prerequisites:** Node.js 24 (exact version in `.nvmrc`), pnpm 12.11.2 (`packageManager` in root `package.json`). +**Prerequisites:** Node.js 24 (exact version in `.nvmrc`), pnpm 12 (exact version in `packageManager` in root `package.json`). ```bash pnpm install # Install all dependencies @@ -103,12 +103,22 @@ It keeps one issue, **Maintenance dashboard** (label `maintenance-dashboard`), l what is due: `catalog:` updates, pnpm (`packageManager`), gitleaks (`GITLEAKS_VERSION` in the secrets-scan script), Node.js (`.nvmrc`) and `pnpm audit` findings. Like `minimumReleaseAge`, a release shows up only once it is 14 days old; a Node.js security -release shows up right away and is flagged. It never opens PRs or commits; doing the -updates stays manual. For a Node.js bump, change only `.nvmrc` (the one place that -holds the exact version) and the Cloudflare `NODE_VERSION` build variable of the -`apps/web` deploy. If `GITLEAKS_VERSION` moves out of `.github/scripts/secrets-scan.sh`, -pass the new path as the `gitleaks-script` input. The dashboard and workflow-lint -callers pin the same `valuecodes/automation` commit, so bump them together. +release shows up right away and is flagged. It never opens PRs or commits. + +`maintenance-updates.yml` calls the maintenance updates workflow from +`valuecodes/automation` weekly. It keeps one PR per kind open (Node.js, pnpm, +gitleaks, `catalog:`) on a `maintenance-updates/` 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 +pull requests** turned on under Settings → Actions → General. Nothing auto-merges. +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. --- @@ -123,6 +133,6 @@ callers pin the same `valuecodes/automation` commit, so bump them together. Update with `pnpm up --latest -r`; `updateConfig.ignoreDependencies` holds `@types/node` to the `.nvmrc` major, so bump it by hand. - Every install enforces the supply-chain settings in `pnpm-workspace.yaml` - (`minimumReleaseAge`, `trustPolicy: no-downgrade`) plus pnpm 12's default - `blockExoticSubdeps`. When one fails, investigate: never disable it, and never - exclude a whole package to get past it. + (`minimumReleaseAge`, `trustPolicy: no-downgrade`, `engineStrict`) plus pnpm + 12's default `blockExoticSubdeps`. When one fails, investigate: never disable + it, and never exclude a whole package to get past it. diff --git a/apps/web/AGENTS.md b/apps/web/AGENTS.md index 26240eb..69989fe 100644 --- a/apps/web/AGENTS.md +++ b/apps/web/AGENTS.md @@ -240,7 +240,8 @@ Or run repo-wide via root `pnpm typecheck` / `pnpm test` / `pnpm build`. `VITE_CF_BEACON_TOKEN`, the Web Analytics token: `vite.config.ts` adds the beacon script to `index.html` only when it is set (production builds only, and the dashboard site on manual installation, so there is one beacon). Also set - `NODE_VERSION` (the version in `.nvmrc`) and `PNPM_VERSION=12.11.2`: the version files sit + `NODE_VERSION` (the version in `.nvmrc`) and `PNPM_VERSION` (the version in the + root `packageManager`): the version files sit outside the `apps/web` root, and the build image's defaults are older. - **Runtime secret:** `TURNSTILE_SECRET` under the Worker's Settings → Variables and Secrets, type Secret, or `pnpm --filter web exec wrangler secret put diff --git a/apps/web/README.md b/apps/web/README.md index 6ca0b70..5adb9ca 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -116,10 +116,10 @@ Also set these build variables (Settings → Build → Variables). With `apps/we as the root, the repository's `.nvmrc` and `packageManager` sit outside it, so the build image is not guaranteed to pick them up, and its defaults are older: -| Variable | Value | -| -------------- | ----------------------- | -| `NODE_VERSION` | the version in `.nvmrc` | -| `PNPM_VERSION` | `12.11.2` | +| Variable | Value | +| -------------- | ------------------------------- | +| `NODE_VERSION` | the version in `.nvmrc` | +| `PNPM_VERSION` | the version in `packageManager` | Keep them in step with `.nvmrc` and the root `packageManager` field. diff --git a/package.json b/package.json index 582ec78..f2a943d 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "description": "Walk through a codebase as a Backrooms level", "private": true, "engines": { - "node": "^24.22.1 || >=26.12.1", - "pnpm": ">=12.0.0" + "node": "^24.22.1 || >=26.12.1" }, "packageManager": "pnpm@12.11.2+sha512.25a51652a196785af5f28bda6dfe8dc582ebefa4ac1d180221ce1390231c5fb76637822ea4b6e4633ce74acdcb0a77f725af11bad38177fdeddaee818a955cb9", "scripts": { diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4801034..275158f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -52,6 +52,10 @@ updateConfig: # guardrail, not a CI check. catalogMode: strict +# Writes exact versions (no `^` or `~`) on `pnpm add`. pnpm 12 reads only +# auth settings from `.npmrc`, so this has to live here. +saveExact: true + allowBuilds: # Installs Tailwind 4's native binary. Without it Tailwind silently emits no # styles, and `pnpm build` still passes. @@ -65,6 +69,11 @@ allowBuilds: # install fails with ERR_PNPM_IGNORED_BUILDS. workerd: false +# pnpm already fails the install when the root `engines.node` doesn't match. +# This also refuses any non-optional dependency whose own `engines` excludes +# the running Node.js, instead of only warning. +engineStrict: true + # 14 days, in minutes: a new release is not resolvable until it is this old. # So `pnpm up --latest` deliberately skips fresh releases; use # `minimumReleaseAgeExclude` if one package must move faster. From c3cd4edc40219ddbd32de65affc3062ca54e324b Mon Sep 17 00:00:00 2001 From: Juha Kangas <42040080+valuecodes@users.noreply.github.com> Date: Fri, 30 Oct 2026 09:58:49 +0200 Subject: [PATCH 2/2] docs: reflow the web build variables paragraph Co-Authored-By: Claude Opus 5.5 --- apps/web/AGENTS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/AGENTS.md b/apps/web/AGENTS.md index 69989fe..97a422c 100644 --- a/apps/web/AGENTS.md +++ b/apps/web/AGENTS.md @@ -241,8 +241,8 @@ Or run repo-wide via root `pnpm typecheck` / `pnpm test` / `pnpm build`. beacon script to `index.html` only when it is set (production builds only, and the dashboard site on manual installation, so there is one beacon). Also set `NODE_VERSION` (the version in `.nvmrc`) and `PNPM_VERSION` (the version in the - root `packageManager`): the version files sit - outside the `apps/web` root, and the build image's defaults are older. + root `packageManager`): the version files sit outside the `apps/web` root, and + the build image's defaults are older. - **Runtime secret:** `TURNSTILE_SECRET` under the Worker's Settings → Variables and Secrets, type Secret, or `pnpm --filter web exec wrangler secret put TURNSTILE_SECRET`. Never a build variable: those exist only during the build,