diff --git a/docs/CI.md b/docs/CI.md index 4a3af75..791ad3d 100644 --- a/docs/CI.md +++ b/docs/CI.md @@ -83,3 +83,18 @@ print order are asserted by: ```bash node --test scripts/check-bindings-cli.test.mjs ``` + +## Deployment documentation check + +Deployment documentation (`docs/DEPLOY.md`) is validated in CI on every PR +alongside the local Markdown link checker (`scripts/check-links.js` and +`pnpm coverage:test`). `scripts/check-deploy-docs.mjs` verifies that every +environment variable referenced in `docs/DEPLOY.md` is documented in +`.env.example` or `apps/web/.env.example`, and every `pnpm` script referenced in +`docs/DEPLOY.md` exists in the corresponding `package.json`: + +```bash +pnpm docs:check +pnpm docs:test +pnpm docs:check-links +``` diff --git a/package.json b/package.json index 66e5b7c..aa491b1 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,9 @@ "web:typecheck": "pnpm --filter @sub-rosa/web typecheck", "snapshot:check": "node scripts/check-snapshots.mjs", "docs:check": "node scripts/check-deploy-docs.mjs", + "docs:test": "node --test scripts/check-deploy-docs.test.mjs", "docs:check-links": "node scripts/check-links.js", - "coverage:test": "node --test scripts/run-ts-coverage.test.mjs && node scripts/run-ts-coverage.mjs", + "coverage:test": "node --test scripts/check-deploy-docs.test.mjs && node scripts/check-deploy-docs.mjs && node --test scripts/run-ts-coverage.test.mjs && node scripts/run-ts-coverage.mjs", "drand:test": "pnpm --filter @sub-rosa/drand-tools test", "drand:typecheck": "pnpm --filter @sub-rosa/drand-tools typecheck", "receipt:test": "pnpm --filter @sub-rosa/receipt-cli test", diff --git a/scripts/check-deploy-docs.test.mjs b/scripts/check-deploy-docs.test.mjs index 86628e0..a483d34 100644 --- a/scripts/check-deploy-docs.test.mjs +++ b/scripts/check-deploy-docs.test.mjs @@ -1,16 +1,17 @@ // Copyright (c) 2026 Sub Rosa contributors import { execFileSync } from "node:child_process"; -import { mkdirSync, mkdtempSync, copyFileSync, writeFileSync, rmSync } from "node:fs"; +import { mkdirSync, mkdtempSync, copyFileSync, writeFileSync, rmSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; +import { fileURLToPath } from "node:url"; import { describe, it } from "node:test"; import assert from "node:assert/strict"; -const SCRIPT_PATH = new URL("check-deploy-docs.mjs", import.meta.url).pathname; -const CWD = new URL("..", import.meta.url).pathname; +const SCRIPT_PATH = fileURLToPath(new URL("check-deploy-docs.mjs", import.meta.url)); +const CWD = fileURLToPath(new URL("..", import.meta.url)); function runCheck(env = {}) { - return execFileSync("node", [SCRIPT_PATH], { + return execFileSync(process.execPath, [SCRIPT_PATH], { encoding: "utf-8", cwd: CWD, stdio: "pipe", @@ -140,4 +141,17 @@ describe("check-deploy-docs", () => { rmSync(tmpDir, { recursive: true, force: true }); } }); + + it("wires docs:check and docs:test into CI alongside the link checker", () => { + const pkg = JSON.parse(readFileSync(join(CWD, "package.json"), "utf8")); + assert.equal(pkg.scripts["docs:check"], "node scripts/check-deploy-docs.mjs"); + assert.equal(pkg.scripts["docs:test"], "node --test scripts/check-deploy-docs.test.mjs"); + assert.match(pkg.scripts["coverage:test"], /check-deploy-docs\.mjs/); + + const checkLinks = readFileSync(join(CWD, "scripts", "check-links.js"), "utf8"); + assert.match(checkLinks, /check-deploy-docs\.mjs/); + + const ciDocs = readFileSync(join(CWD, "docs", "CI.md"), "utf8"); + assert.match(ciDocs, /pnpm docs:check/); + }); }); diff --git a/scripts/check-links.js b/scripts/check-links.js index 73d6ab4..09fa251 100644 --- a/scripts/check-links.js +++ b/scripts/check-links.js @@ -6,6 +6,7 @@ const diagnostics = createLogger("scripts.check-links"); const fs = require('fs'); const path = require('path'); +const { execFileSync } = require('child_process'); const ROOT = path.resolve(__dirname, '..'); @@ -157,6 +158,12 @@ if (external.length > 0) { if (broken === 0) { diagnostics.info("ok", `OK ${checked} local link(s) checked, ${skipped} allowlisted`); + if (!process.argv.includes('--links-only')) { + execFileSync(process.execPath, [path.join(ROOT, 'scripts', 'check-deploy-docs.mjs')], { + cwd: ROOT, + stdio: 'inherit', + }); + } process.exit(0); } else { diagnostics.error("fail", `\nFAIL ${broken} broken link(s) — fix the paths above or add to ALLOWLIST in scripts/check-links.js`);