feat: site-build-gate as external pkg
Summary
Learn runs the published @netdata/site-build-gate package instead of a copy of the gate checked in under scripts/site-build-gate/. A Dependabot security update to one of the gate's dependencies is then an ordinary yarn.lock change. It no longer fails the Netlify build on a checksum mismatch.
build:netlify
verify-git-history
verify-indexnow-vendor
- npm ci --prefix scripts/site-build-gate # separate npm lock, bound by manifest.json
docusaurus build
run-post-build-gates
- scripts/site-build-gate/site_build_gate.mjs # refuses to run if any file's hash differs
+ node_modules/@netdata/site-build-gate/site_build_gate.mjs
package.json
+ devDependencies: "@netdata/site-build-gate": "^10.1.0"
yarn.lock
+ @netdata/site-build-gate@^10.1.0 # css-tree, parse5, saxes already in the graph
scripts/
-└── site-build-gate/
- ├── manifest.json # SHA-256 of package.json, package-lock.json, site_build_gate.mjs
- ├── package.json
- ├── package-lock.json
- └── site_build_gate.mjs
The gate's rules, baseline (config/site-build-gate-baseline.json) and command-line arguments are unchanged.
- Source and versioning: the package is published from
netdata-labs/seo(vendor/site-build-gate/). Its major version is the ruleset version, so10.xmeans ruleset 10. - Tests: they no longer pin checksums. Instead they check that the installed gate's major version matches the baseline's
ruleset_version. - Docs:
AGENTS.md(static build gate contract) andREADME.md(dependency authority, and the local setup step that mentioned the nested gate install) describe the package instead of the copy.
Evidence
-
Before: a lockfile-only update to a gate dependency, the shape of a Dependabot security PR, fails after the full Docusaurus build:
site build gate contract error: vendor checksum mismatch for package-lock.json: expected a3cac544…, got 3c71e70c… exit=2#3121 (source-map-js 1.2.1 → 1.2.2) shows this in practice: all GitHub checks were green,
netlify/netdata-docusaurus/deploy-previewwas red, and the PR was closed. The fix needed coordinated changes in seo, website and Learn (#3136).After: the same kind of change, only
yarn.lock(entities8.1.0 → 8.0.0, within^8.0.0), installed with--frozen-lockfile:node scripts/run-post-build-gates.mjs "checked_pages": 2030, "regressions": [], exit=0 -
Full Netlify build (
npm run build:netlify, Node 22.23.2): passes. The site build gate scanned 2,030 pages with 0 regressions, the Cloudflare analytics gate passed, and there are 297 broken-anchor warnings, the same asmaster. -
Tests:
yarn test:runpasses: Vitest 494 passed and 1 skipped, plus the first-touch (26), IndexNow (64), Swagger UI assets (3), dependency-authority (3) and site-build-gate (4) suites. -
Pull request checks on
b1eebcd0f(^10.1.0): the Netlify deploy preview, header and redirect rules, the required same-site links job, the advisory cross-site and new third-party link jobs,verifyand the dependency-impact check all pass. -
Published package (
10.1.0on registry.npmjs.org, released by the seo publish workflow through npm trusted publishing): all four files are byte-identical tovendor/site-build-gate/at seomain@7b3e6d83. Installed from the registry, it givessite build gate v10: 2030 pages, 0 regression(s), 0 accepted finding(s)on the same build.
Merge Danger
Door: two-way
Reverting this PR restores the vendored copy and its npm ci step exactly. The published package stays on npm either way; nothing else depends on it yet.
Blast Radius: deploys
- Every Netlify build runs the gate. If the package were missing or broken, every deploy would fail (exit 2), including ingest. It fails loudly; it can't silently let pages through.
- Version range:
^10.1.0lets Dependabot propose later 10.x releases as their own PRs;.github/dependabot.ymlneeds no change. A new major is a ruleset change: its Dependabot PR fails the Netlify build by design (baseline ruleset 10 does not match 11) until the PR also updatesconfig/site-build-gate-baseline.jsonand any new findings are reviewed. - Changes an earlier decision: "Learn commits the checksum-bound gate" becomes "Learn installs a published version". Costa agreed to this experiment.
- Trade-off: the gate's parser dependencies now float within
^ranges in Learn'syarn.lockinstead of matching seo byte for byte.- Caught by the build: a parser update that crashes the gate or reports defects that aren't there.
- Not caught here: a parser update that makes the gate miss a defect. Only seo's fixture tests can catch that.
- Left unchanged on purpose:
config/seo-remediation-contract.jsonstill namesscripts/site-build-gate, because it's a frozen historical acceptance record.
Summary by CodeRabbit
-
Build and Dependency Management
- The site-build gate is now installed as a published package and runs locally after the Docusaurus build.
- The gate’s major version is checked against the configured baseline version.
- The Netlify build no longer performs a separate dependency installation for the gate.
-
Documentation
- Updated setup and dependency guidance to reflect the package-based gate and the project’s Node.js and Yarn versions.