From 2604f9ab0d326889689cbf9e17e74ccf88a4b5e4 Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Thu, 9 Jul 2026 17:51:32 +0100 Subject: [PATCH] ci: add stale override detection to frontend build gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parses npm explain output for each overridden package. If the parent's required range already satisfies the override target, flags it as stale — dev must remove the override. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .gitea/workflows/ci.yaml | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 773bd01..d285eb5 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -282,6 +282,49 @@ jobs: }); " + - name: Check for stale overrides + run: | + cd frontend && node -e " + const { execSync } = require('child_process'); + const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8')); + const overrides = pkg.overrides || {}; + const keys = Object.keys(overrides); + if (!keys.length) { console.log('No overrides configured'); process.exit(0); } + + function parseMin(range) { + const v = range.replace(/^[\^~>=<]*/, '').split('.').map(Number); + return { major: v[0]||0, minor: v[1]||0, patch: v[2]||0 }; + } + function gte(a, b) { + if (a.major !== b.major) return a.major > b.major; + if (a.minor !== b.minor) return a.minor > b.minor; + return a.patch >= b.patch; + } + + let stale = []; + for (const key of keys) { + const explain = execSync('npm explain ' + key + ' 2>/dev/null || true').toString(); + const was = explain.match(/\(was \"([^\"]+)\"\)/); + if (!was) { + const found = explain.includes('node_modules/' + key); + console.log(key + ': ' + (found ? 'override active' : 'not in tree')); + continue; + } + const parentRange = was[1]; + const overrideTarget = overrides[key]; + if (gte(parseMin(parentRange), parseMin(overrideTarget))) { + stale.push(key + ' (parent requires ' + parentRange + ', override is ' + overrideTarget + ')'); + } + } + + if (stale.length) { + console.log('Stale overrides detected — remove from package.json:'); + stale.forEach(s => console.log(' ' + s)); + process.exit(1); + } + console.log('All overrides appear necessary'); + " + - name: Build run: cd frontend && npm run build