mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
test(package): reject an Electron install takeover by exact command (#20799)
* test(package): reject an Electron install takeover by exact command CodeRabbit was right about #20787. Replacing the pinned postinstall string with a /electron/i keyword check was wrong in both directions, verified: rebuild-native-deps.mjs && rebuild-native-deps.mjs PASSED (should fail) rebuild-native-deps.mjs && check-electron-version FAILED (should pass) The owner's own path contains no "electron", so duplicating it slipped through -- the one case the contract is named for. And a substring match rejects any later step that merely mentions Electron, which is the same over-tightness that broke every open PR in the first place, relocated. Later steps are now checked against the exact owned command plus the known Electron install commands. A second case pins the rejections themselves, because reading the real postinstall cannot show a bad chain would be caught -- that is how #20787 shipped with a guard that did not guard. Split into its own file rather than adding a max-lines disable (AGENTS.md). * test(package): match install commands as tokens and cover the rebuild:electron alias Both review comments were right, verified by running them: && check-install-app-deps-version.mjs rejected by substring match (should pass) && pnpm run rebuild:electron slipped through (should fail) package.json:101 aliases rebuild:electron to the owned script, so invoking it is the same takeover. Matching is now token-based with the owned command still checked as a phrase, and both cases are pinned.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { parse } from 'yaml'
|
||||
|
||||
const projectDir = resolve(import.meta.dirname, '../..')
|
||||
const readProject = (file) => readFileSync(join(projectDir, file), 'utf8')
|
||||
const packageJson = JSON.parse(readProject('package.json'))
|
||||
const pnpmWorkspace = parse(readProject('pnpm-workspace.yaml'))
|
||||
|
||||
const OWNED_ELECTRON_REBUILD = 'node config/scripts/rebuild-native-deps.mjs'
|
||||
// Why exact tokens and not /electron/i or a substring: the owner's own path has no "electron"
|
||||
// in it, so a keyword check waves a duplicated rebuild through -- the case this contract is
|
||||
// named for (#20787). Substring matching has the opposite fault: `install-app-deps` would also
|
||||
// reject a `check-install-app-deps-version.mjs` that installs nothing. `rebuild:electron` is
|
||||
// package.json's alias for the owned script, so running it is the same takeover.
|
||||
const ELECTRON_INSTALL_COMMANDS = [
|
||||
OWNED_ELECTRON_REBUILD,
|
||||
'config/scripts/rebuild-native-deps.mjs',
|
||||
'rebuild:electron',
|
||||
'electron-rebuild',
|
||||
'electron-builder',
|
||||
'install-app-deps'
|
||||
]
|
||||
const tokenize = (step) => step.split(/[\s]+/).flatMap((word) => [word, ...word.split(/[@]/)])
|
||||
const takesOverElectronInstall = (step) => {
|
||||
if (step.includes(OWNED_ELECTRON_REBUILD)) {
|
||||
return true
|
||||
}
|
||||
const tokens = new Set(tokenize(step))
|
||||
return ELECTRON_INSTALL_COMMANDS.some((command) => tokens.has(command))
|
||||
}
|
||||
|
||||
describe('Electron binary install ownership', () => {
|
||||
it('keeps root postinstall as the single Electron binary install owner', () => {
|
||||
// The invariant is that the root postinstall owns the Electron binary install, not that
|
||||
// nothing may run after it -- pinning the whole string broke every open PR (#20726).
|
||||
const steps = packageJson.scripts.postinstall.split('&&').map((step) => step.trim())
|
||||
expect(steps[0]).toBe(OWNED_ELECTRON_REBUILD)
|
||||
for (const step of steps.slice(1)) {
|
||||
expect(takesOverElectronInstall(step)).toBe(false)
|
||||
}
|
||||
expect(pnpmWorkspace.allowBuilds).not.toHaveProperty('electron')
|
||||
})
|
||||
|
||||
// Why a separate case: the assertion above only reads the real postinstall, so it cannot show
|
||||
// a bad chain would be caught. #20787 shipped a keyword check that missed a duplicated
|
||||
// rebuild; these fixtures pin the rejections themselves.
|
||||
it('rejects a chained step that would take over the Electron install', () => {
|
||||
expect(takesOverElectronInstall(OWNED_ELECTRON_REBUILD)).toBe(true)
|
||||
expect(takesOverElectronInstall('npx electron-rebuild')).toBe(true)
|
||||
expect(takesOverElectronInstall('npx electron-builder install-app-deps')).toBe(true)
|
||||
expect(takesOverElectronInstall('node config/scripts/sync-anti-slop-plugin.mjs')).toBe(false)
|
||||
expect(takesOverElectronInstall('node config/scripts/check-electron-version.mjs')).toBe(false)
|
||||
expect(takesOverElectronInstall('pnpm run rebuild:electron')).toBe(true)
|
||||
expect(takesOverElectronInstall('node config/scripts/check-install-app-deps-version.mjs')).toBe(
|
||||
false
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -24,18 +24,6 @@ describe('Electron runtime package contract', () => {
|
||||
linux: createPackagedRuntimeNodeModuleResources('linux')
|
||||
}
|
||||
|
||||
it('keeps root postinstall as the single Electron binary install owner', () => {
|
||||
// Why not an exact match: the invariant is that the root postinstall owns the Electron
|
||||
// binary install, not that nothing else may run after it. Pinning the whole string made
|
||||
// any unrelated chained step (a lint-plugin sync, say) a CI failure for every open PR.
|
||||
const postinstall = packageJson.scripts.postinstall
|
||||
const steps = postinstall.split('&&').map((step) => step.trim())
|
||||
expect(steps[0]).toBe('node config/scripts/rebuild-native-deps.mjs')
|
||||
// No later step may take over the Electron install the first step owns.
|
||||
expect(steps.slice(1).join(' ')).not.toMatch(/electron/i)
|
||||
expect(pnpmWorkspace.allowBuilds).not.toHaveProperty('electron')
|
||||
})
|
||||
|
||||
it('keeps the native Windows registry addon optional and platform-gated', () => {
|
||||
const rebuildScript = readProject('config/scripts/rebuild-native-deps.mjs')
|
||||
const ensureScript = readProject('config/scripts/ensure-native-runtime.mjs')
|
||||
|
||||
Reference in New Issue
Block a user