mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 08:03:33 +00:00
fix(ci): make accelerated checks runtime-safe
This commit is contained in:
@@ -26,4 +26,10 @@ describe('Electron Vite output contract', () => {
|
||||
expect(external('@xterm/headless', undefined, false)).toBe(false)
|
||||
expect(external('@xterm/addon-serialize', undefined, false)).toBe(false)
|
||||
})
|
||||
|
||||
it('isolates renderer entry side effects behind strict facades', () => {
|
||||
expect(electronViteConfig.renderer?.build?.rollupOptions?.preserveEntrySignatures).toBe(
|
||||
'strict'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -49,15 +49,18 @@ describe('PR workflow parallelism', () => {
|
||||
const shellStep = workflow.jobs.shell_contracts.steps.find(
|
||||
(step) => step.name === 'Test real shell contracts'
|
||||
)
|
||||
const shellInstall = workflow.jobs.shell_contracts.steps.find(
|
||||
(step) => step.uses === './.github/actions/install-node-dependencies'
|
||||
)
|
||||
|
||||
expect(workflow.jobs.test.steps.some((step) => step.name === 'Install zsh')).toBe(false)
|
||||
expect(workflow.jobs.shell_contracts.steps.some((step) => step.name === 'Install zsh')).toBe(
|
||||
true
|
||||
)
|
||||
expect(shellInstall.with['native-runtime']).toBe('node')
|
||||
for (const testFile of nativeShellContractFiles) {
|
||||
expect(shellStep.run).toContain(testFile)
|
||||
}
|
||||
expect(shellStep.run).toContain('ensure-native-runtime.mjs --runtime=node')
|
||||
})
|
||||
|
||||
it('keeps every real-zsh test in the dedicated shell lane', () => {
|
||||
@@ -74,7 +77,6 @@ describe('PR workflow parallelism', () => {
|
||||
)
|
||||
|
||||
expect(buildStep.run).toContain('scripts=(build:relay build:electron-vite:parallel)')
|
||||
expect(buildStep.run).toContain('pnpm run ensure:electron-runtime &')
|
||||
expect(buildStep.run).toContain('pnpm run "$script" &')
|
||||
expect(
|
||||
workflow.jobs.package.steps.find(
|
||||
@@ -94,41 +96,45 @@ describe('PR workflow parallelism', () => {
|
||||
expect(steps[nodeIndex].with.cache).toBe('pnpm')
|
||||
})
|
||||
|
||||
it('skips lifecycle scripts outside native-runtime test setup', () => {
|
||||
for (const jobName of [
|
||||
'static_analysis',
|
||||
'typecheck',
|
||||
'git_compatibility',
|
||||
'test',
|
||||
'package'
|
||||
]) {
|
||||
const installStep = workflow.jobs[jobName].steps.find(
|
||||
(step) => step.uses === './.github/actions/install-node-dependencies'
|
||||
)
|
||||
expect(installStep.with['ignore-scripts'], jobName).toBe('true')
|
||||
}
|
||||
|
||||
const shellInstall = workflow.jobs.shell_contracts.steps.find(
|
||||
it('restores Electron downloads before preparing the package runtime', () => {
|
||||
const steps = workflow.jobs.package.steps
|
||||
const cacheIndex = steps.findIndex((step) => step.name === 'Cache electron-builder downloads')
|
||||
const installIndex = steps.findIndex(
|
||||
(step) => step.uses === './.github/actions/install-node-dependencies'
|
||||
)
|
||||
expect(shellInstall.with).toBeUndefined()
|
||||
|
||||
expect(cacheIndex).toBeLessThan(installIndex)
|
||||
})
|
||||
|
||||
it('prepares each native runtime before its consumers start', () => {
|
||||
const installFor = (jobName) =>
|
||||
workflow.jobs[jobName].steps.find(
|
||||
(step) => step.uses === './.github/actions/install-node-dependencies'
|
||||
)
|
||||
|
||||
for (const jobName of ['static_analysis', 'typecheck', 'git_compatibility']) {
|
||||
expect(installFor(jobName).with, jobName).toBeUndefined()
|
||||
}
|
||||
expect(installFor('shell_contracts').with['native-runtime']).toBe('node')
|
||||
expect(installFor('test').with['native-runtime']).toBe('node')
|
||||
expect(installFor('package').with['native-runtime']).toBe('electron')
|
||||
|
||||
expect(
|
||||
dependencyAction.runs.steps.find((step) => step.name === 'Use external node-gyp').if
|
||||
).toBe("inputs.ignore-scripts != 'true'")
|
||||
).toBe("inputs.native-runtime != 'none'")
|
||||
const dependencyInstall = dependencyAction.runs.steps.find(
|
||||
(step) => step.name === 'Install dependencies'
|
||||
)
|
||||
expect(dependencyInstall.env.IGNORE_SCRIPTS).toBe('${{ inputs.ignore-scripts }}')
|
||||
expect(dependencyInstall.run).toContain(
|
||||
'--no-frozen-lockfile --prefer-frozen-lockfile=false --os=current --os=win32 --cpu=current'
|
||||
)
|
||||
expect(dependencyInstall.run).toContain('install_args+=(--ignore-scripts)')
|
||||
expect(workflow.jobs.test.steps.find((step) => step.name === 'Test shard').run).not.toContain(
|
||||
'ensure-native-runtime'
|
||||
expect(dependencyInstall.run).toContain('--no-frozen-lockfile')
|
||||
expect(dependencyInstall.run).toContain('--ignore-scripts')
|
||||
const prepareRuntime = dependencyAction.runs.steps.find(
|
||||
(step) => step.name === 'Prepare native runtime'
|
||||
)
|
||||
expect(prepareRuntime.if).toBe("inputs.native-runtime != 'none'")
|
||||
expect(prepareRuntime.run).toContain('ensure-native-runtime.mjs --runtime="$NATIVE_RUNTIME"')
|
||||
})
|
||||
|
||||
it('reuses native preparation only after the concurrent runtime gate', () => {
|
||||
it('reuses native preparation after the dependency action gate', () => {
|
||||
const buildStep = workflow.jobs.package.steps.find(
|
||||
(step) => step.name === 'Build package inputs'
|
||||
)
|
||||
@@ -136,7 +142,7 @@ describe('PR workflow parallelism', () => {
|
||||
(step) => step.name === 'Package unpacked app'
|
||||
)
|
||||
|
||||
expect(buildStep.run).toContain('pnpm run ensure:electron-runtime &')
|
||||
expect(buildStep.run).not.toContain('ensure:electron-runtime')
|
||||
expect(packageStep.env.ORCA_REUSE_PREPARED_NATIVE_RUNTIME).toBe('1')
|
||||
})
|
||||
|
||||
|
||||
@@ -19,6 +19,36 @@ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
||||
const selectedFiles = new Set(['web-index.html'])
|
||||
const visitedEntries = new Set()
|
||||
|
||||
function assertEntryIsolation() {
|
||||
const entryKeys = new Set(
|
||||
Object.entries(manifest)
|
||||
.filter(([, entry]) => entry?.isEntry === true)
|
||||
.map(([key]) => key)
|
||||
)
|
||||
|
||||
for (const sourceEntry of entryKeys) {
|
||||
const visited = new Set()
|
||||
const pending = [sourceEntry]
|
||||
while (pending.length > 0) {
|
||||
const key = pending.pop()
|
||||
if (visited.has(key)) {
|
||||
continue
|
||||
}
|
||||
visited.add(key)
|
||||
const entry = manifest[key]
|
||||
if (!entry || typeof entry !== 'object') {
|
||||
throw new Error(`Renderer manifest is missing entry: ${key}`)
|
||||
}
|
||||
for (const dependency of [...(entry.imports ?? []), ...(entry.dynamicImports ?? [])]) {
|
||||
if (entryKeys.has(dependency) && dependency !== sourceEntry) {
|
||||
throw new Error(`Renderer entry ${sourceEntry} executes entry ${dependency}`)
|
||||
}
|
||||
pending.push(dependency)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addOutputPath(outputPath) {
|
||||
if (
|
||||
typeof outputPath !== 'string' ||
|
||||
@@ -107,6 +137,7 @@ async function minifyWebOutput() {
|
||||
)
|
||||
}
|
||||
|
||||
assertEntryIsolation()
|
||||
visitManifestEntry('web-index.html')
|
||||
includeReferencedOutputs()
|
||||
|
||||
|
||||
@@ -98,4 +98,20 @@ describe('renderer web client projection', () => {
|
||||
expect(result.status).toBe(1)
|
||||
expect(result.stderr).toContain('Renderer manifest is missing entry: web-index.html')
|
||||
})
|
||||
|
||||
it('rejects renderer entries that execute another entry root', () => {
|
||||
const root = createRendererFixture()
|
||||
const manifestPath = join(root, 'out/renderer/.vite/manifest.json')
|
||||
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
||||
manifest['web-index.html'].dynamicImports.push('index.html')
|
||||
writeFileSync(manifestPath, JSON.stringify(manifest))
|
||||
|
||||
const result = spawnSync(process.execPath, [scriptPath], {
|
||||
cwd: root,
|
||||
encoding: 'utf8'
|
||||
})
|
||||
|
||||
expect(result.status).toBe(1)
|
||||
expect(result.stderr).toContain('Renderer entry web-index.html executes entry index.html')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user