277 lines
12 KiB
JavaScript
277 lines
12 KiB
JavaScript
import { readFileSync } from 'node:fs'
|
|
import { dirname, join, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { parse } from 'yaml'
|
|
|
|
const projectDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
|
|
const packageJson = JSON.parse(readFileSync(join(projectDir, 'package.json'), 'utf8'))
|
|
|
|
describe('Electron runtime package contract', () => {
|
|
it('keeps root postinstall as the single Electron binary install owner', () => {
|
|
expect(packageJson.scripts.postinstall).toBe('node config/scripts/rebuild-native-deps.mjs')
|
|
expect(packageJson.pnpm.onlyBuiltDependencies).not.toContain('electron')
|
|
})
|
|
|
|
it('guards package scripts that launch Electron tooling', () => {
|
|
const scripts = packageJson.scripts
|
|
const guardedScripts = [
|
|
'start',
|
|
'dev',
|
|
'dev-stable-name',
|
|
'build:unpack',
|
|
'build:win',
|
|
'build:mac',
|
|
'build:mac:release',
|
|
'build:linux',
|
|
'test:e2e',
|
|
'test:e2e:terminal-rendering-golden',
|
|
'test:e2e:terminal-rendering-release-evidence',
|
|
'test:e2e:headful'
|
|
]
|
|
|
|
for (const scriptName of guardedScripts) {
|
|
expect(scripts[scriptName], scriptName).toContain('pnpm run ensure:electron-runtime &&')
|
|
}
|
|
})
|
|
|
|
it('keeps Windows and Linux package builds off the macOS native helper build', () => {
|
|
const scripts = packageJson.scripts
|
|
|
|
expect(scripts['build:desktop']).not.toContain('build:computer-macos')
|
|
expect(scripts['build:win']).toContain('pnpm run build:desktop')
|
|
expect(scripts['build:win']).not.toContain('pnpm run build ')
|
|
expect(scripts['build:win']).not.toContain('build:computer-macos')
|
|
expect(scripts['build:linux']).toContain('pnpm run build:desktop')
|
|
expect(scripts['build:linux']).not.toContain('pnpm run build ')
|
|
expect(scripts['build:linux']).not.toContain('build:computer-macos')
|
|
expect(scripts['build:mac']).toContain('pnpm run build:computer-macos')
|
|
expect(scripts['build:release']).toContain('pnpm run build:native')
|
|
expect(scripts['build:release']).not.toContain('build:computer-macos')
|
|
})
|
|
|
|
it('guards release publishing before electron-builder runs', () => {
|
|
const releaseWorkflow = readFileSync(
|
|
join(projectDir, '.github/workflows/release-cut.yml'),
|
|
'utf8'
|
|
)
|
|
const parsedWorkflow = parse(releaseWorkflow)
|
|
const releaseCommands = new Map(
|
|
parsedWorkflow.jobs.build.strategy.matrix.include.map(({ platform, release_command }) => [
|
|
platform,
|
|
release_command
|
|
])
|
|
)
|
|
|
|
expect([...releaseCommands.keys()].sort()).toEqual(['linux', 'mac', 'win'])
|
|
for (const command of releaseCommands.values()) {
|
|
expect(command).toContain('node config/scripts/ensure-native-runtime.mjs --runtime=electron')
|
|
expect(command).toContain('electron-builder')
|
|
expect(command.indexOf('ensure-native-runtime')).toBeLessThan(
|
|
command.indexOf('electron-builder')
|
|
)
|
|
}
|
|
expect(releaseCommands.get('mac')).toContain(' && ORCA_MAC_RELEASE=1 ')
|
|
expect(releaseCommands.get('linux')).toContain(' && pnpm exec electron-builder ')
|
|
expect(releaseCommands.get('win')).toContain(
|
|
'; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; pnpm exec electron-builder '
|
|
)
|
|
})
|
|
|
|
it('lets release-cut tag a version that is already present on main', () => {
|
|
const releaseWorkflow = readFileSync(
|
|
join(projectDir, '.github/workflows/release-cut.yml'),
|
|
'utf8'
|
|
)
|
|
const parsedWorkflow = parse(releaseWorkflow)
|
|
const bumpStep = parsedWorkflow.jobs.cut.steps.find(
|
|
(step) => step.name === 'Bump package.json and tag'
|
|
)
|
|
|
|
expect(bumpStep.run).toContain('git diff --cached --quiet')
|
|
expect(bumpStep.run).toContain('git commit --allow-empty -m "$commit_message"')
|
|
})
|
|
|
|
it('keeps release-cut RC retries monotonic across stale attempts', () => {
|
|
const releaseWorkflow = readFileSync(
|
|
join(projectDir, '.github/workflows/release-cut.yml'),
|
|
'utf8'
|
|
)
|
|
const parsedWorkflow = parse(releaseWorkflow)
|
|
const versionStep = parsedWorkflow.jobs.cut.steps.find(
|
|
(step) => step.name === 'Compute next version'
|
|
)
|
|
|
|
expect(versionStep.run).toContain('node config/scripts/release-rc-history.mjs "$1"')
|
|
expect(versionStep.run).toContain('tag_matches_current_ref')
|
|
expect(versionStep.run).toContain('cutting the next version instead of reusing stale artifacts')
|
|
expect(versionStep.run).toContain('git rev-parse "$existing_rc_tag"')
|
|
})
|
|
|
|
it('bumps separate Homebrew casks for stable and RC desktop tags', () => {
|
|
const releaseWorkflow = parse(
|
|
readFileSync(join(projectDir, '.github/workflows/release-cut.yml'), 'utf8')
|
|
)
|
|
const homebrewWorkflow = parse(
|
|
readFileSync(join(projectDir, '.github/workflows/homebrew-bump.yml'), 'utf8')
|
|
)
|
|
|
|
expect(releaseWorkflow.jobs['homebrew-bump'].if).toContain(
|
|
"startsWith(needs.cut.outputs.tag, 'v')"
|
|
)
|
|
expect(releaseWorkflow.jobs['homebrew-bump'].if).not.toContain('-rc.')
|
|
expect(releaseWorkflow.jobs['homebrew-bump-published-rc-draft'].with.tag).toBe(
|
|
'${{ needs.cut.outputs.latest_published_rc_tag }}'
|
|
)
|
|
|
|
const resolveCaskStep = homebrewWorkflow.jobs['bump-cask'].steps.find(
|
|
(step) => step.name === 'Resolve cask target'
|
|
)
|
|
const renderStep = homebrewWorkflow.jobs['bump-cask'].steps.find(
|
|
(step) => step.name === 'Render updated cask file'
|
|
)
|
|
const copyStep = homebrewWorkflow.jobs['bump-cask'].steps.find(
|
|
(step) => step.name === 'Copy cask into tap and open PR'
|
|
)
|
|
|
|
expect(resolveCaskStep.run).toContain('token="orca@rc"')
|
|
expect(resolveCaskStep.run).toContain('token="orca"')
|
|
expect(renderStep.env.CASK_PATH).toBe('${{ steps.cask.outputs.path }}')
|
|
expect(copyStep.run).toContain('cp "$CASK_PATH" "tap/$CASK_PATH"')
|
|
expect(copyStep.run).toContain('git add "$CASK_PATH"')
|
|
})
|
|
|
|
it('installs the Electron package binary in PR checks without changing native module ABI', () => {
|
|
const prWorkflow = readFileSync(join(projectDir, '.github/workflows/pr.yml'), 'utf8')
|
|
const parsedWorkflow = parse(prWorkflow)
|
|
const installStep = parsedWorkflow.jobs.verify.steps.find(
|
|
(step) => step.name === 'Install Electron package binary for tests'
|
|
)
|
|
|
|
expect(installStep.run).toBe('node config/scripts/install-electron-package-binary.mjs')
|
|
})
|
|
|
|
it('smokes the packaged CLI from outside the checkout in PR checks', () => {
|
|
const prWorkflow = readFileSync(join(projectDir, '.github/workflows/pr.yml'), 'utf8')
|
|
const parsedWorkflow = parse(prWorkflow)
|
|
const smokeStep = parsedWorkflow.jobs.verify.steps.find(
|
|
(step) => step.name === 'Smoke packaged CLI'
|
|
)
|
|
|
|
expect(smokeStep.run).toBe(
|
|
'node config/scripts/smoke-packaged-cli.mjs --app-dir=dist/linux-unpacked'
|
|
)
|
|
})
|
|
|
|
it('keeps terminal scale perf wired to the report budget gate', () => {
|
|
const packageScripts = packageJson.scripts
|
|
const terminalPerfWorkflow = parse(
|
|
readFileSync(join(projectDir, '.github/workflows/terminal-perf.yml'), 'utf8')
|
|
)
|
|
const steps = terminalPerfWorkflow.jobs['terminal-perf'].steps
|
|
const runStep = steps.find((step) => step.name === 'Run terminal scale perf report gate')
|
|
const uploadStep = steps.find((step) => step.name === 'Upload terminal perf report')
|
|
|
|
expect(packageScripts['test:e2e:terminal-perf:scale:report']).toContain(
|
|
'run-terminal-scale-perf-report-gate.mjs'
|
|
)
|
|
expect(runStep.run).toContain('pnpm run test:e2e:terminal-perf:scale:report')
|
|
expect(runStep.run).toContain('xvfb-run --auto-servernum')
|
|
const manualProfileKnobs = [
|
|
['ORCA_TERMINAL_PERF_FRAME_COUNT', 'frame_count', 'ORCA_E2E_OPENCODE_FRAME_COUNT'],
|
|
[
|
|
'ORCA_TERMINAL_PERF_FRAME_INTERVAL_MS',
|
|
'frame_interval_ms',
|
|
'ORCA_E2E_OPENCODE_FRAME_INTERVAL_MS'
|
|
],
|
|
[
|
|
'ORCA_TERMINAL_PERF_PRESSURE_OUTPUT_CHARS',
|
|
'pressure_output_chars',
|
|
'ORCA_E2E_OPENCODE_PRESSURE_OUTPUT_CHARS'
|
|
],
|
|
['ORCA_TERMINAL_PERF_SCALE_PANES', 'scale_panes', 'ORCA_E2E_OPENCODE_SCALE_PANES'],
|
|
[
|
|
'ORCA_TERMINAL_PERF_SCALE_CROSS_WORKSPACE_PANES',
|
|
'scale_cross_workspace_panes',
|
|
'ORCA_E2E_OPENCODE_SCALE_CROSS_WORKSPACE_PANES'
|
|
],
|
|
[
|
|
'ORCA_TERMINAL_PERF_SCALE_PRESSURE_PANES',
|
|
'scale_pressure_panes',
|
|
'ORCA_E2E_OPENCODE_SCALE_PRESSURE_PANES'
|
|
],
|
|
[
|
|
'ORCA_TERMINAL_PERF_SCALE_HIDDEN_PRESSURE_PANES',
|
|
'scale_hidden_pressure_panes',
|
|
'ORCA_E2E_OPENCODE_SCALE_HIDDEN_PRESSURE_PANES'
|
|
]
|
|
]
|
|
for (const [workflowEnv, inputName, runnerEnv] of manualProfileKnobs) {
|
|
expect(runStep.env[workflowEnv]).toBe(`\${{ inputs.${inputName} }}`)
|
|
expect(runStep.run).toContain(runnerEnv)
|
|
}
|
|
expect(uploadStep.uses).toBe('actions/upload-artifact@v7')
|
|
expect(uploadStep.with.path).toBe('${{ env.ORCA_E2E_TERMINAL_PERF_REPORT_PATH }}')
|
|
})
|
|
|
|
it('keeps terminal rendering regressions in the fast golden E2E gate', () => {
|
|
const packageScripts = packageJson.scripts
|
|
const goldenWorkflow = parse(
|
|
readFileSync(join(projectDir, '.github/workflows/golden-e2e-experiment.yml'), 'utf8')
|
|
)
|
|
const releaseWorkflow = parse(
|
|
readFileSync(join(projectDir, '.github/workflows/release-cut.yml'), 'utf8')
|
|
)
|
|
const steps = goldenWorkflow.jobs['golden-e2e'].steps
|
|
const linuxRunStep = steps.find((step) => step.name === 'Run golden E2E tests on Linux')
|
|
const macRunStep = steps.find((step) => step.name === 'Run golden E2E tests on macOS')
|
|
const windowsRunStep = steps.find((step) => step.name === 'Run golden E2E tests on Windows')
|
|
const pullRequestPaths = goldenWorkflow.on.pull_request.paths
|
|
const releaseGoldenJob = releaseWorkflow.jobs['terminal-rendering-golden']
|
|
const releaseEvidenceJob = releaseWorkflow.jobs['terminal-rendering-release-evidence']
|
|
const releaseBuildNeeds = releaseWorkflow.jobs.build.needs
|
|
const publishReleaseNeeds = releaseWorkflow.jobs['publish-release'].needs
|
|
|
|
expect(packageScripts['test:e2e:terminal-rendering-golden']).toContain(
|
|
'@terminal-rendering-golden'
|
|
)
|
|
expect(packageScripts['test:e2e:terminal-rendering-golden']).toContain(
|
|
'terminal-raw-emoji-table-scroll-restore.spec.ts'
|
|
)
|
|
expect(packageScripts['test:e2e:terminal-rendering-golden']).not.toContain(
|
|
'terminal-long-table-scroll-restore.spec.ts'
|
|
)
|
|
expect(packageScripts['test:e2e:terminal-rendering-release-evidence']).toContain(
|
|
'terminal-opencode-emoji-table-rendering.spec.ts'
|
|
)
|
|
expect(packageScripts['test:e2e:terminal-rendering-release-evidence']).toContain(
|
|
'terminal-long-table-scroll-restore.spec.ts'
|
|
)
|
|
for (const runStep of [linuxRunStep, macRunStep, windowsRunStep]) {
|
|
expect(runStep.run).toContain('pnpm run test:e2e:terminal-rendering-golden')
|
|
}
|
|
expect(pullRequestPaths).toContain('tests/e2e/terminal-raw-emoji-table-scroll-restore.spec.ts')
|
|
expect(pullRequestPaths).toContain('tests/e2e/fixtures/terminal-emoji-table.md')
|
|
expect(pullRequestPaths).toContain('src/renderer/src/lib/pane-manager/**')
|
|
expect(releaseBuildNeeds).not.toContain('terminal-rendering-golden')
|
|
expect(releaseBuildNeeds).not.toContain('terminal-rendering-release-evidence')
|
|
expect(publishReleaseNeeds).toContain('terminal-rendering-golden')
|
|
expect(publishReleaseNeeds).toContain('build')
|
|
expect(publishReleaseNeeds).not.toContain('terminal-rendering-release-evidence')
|
|
expect(releaseGoldenJob['continue-on-error']).toBeUndefined()
|
|
expect(releaseGoldenJob.strategy.matrix.include.map(({ platform }) => platform).sort()).toEqual(
|
|
['linux', 'mac', 'windows']
|
|
)
|
|
expect(releaseGoldenJob.steps.map((step) => step.run ?? '')).toContain(
|
|
'xvfb-run --auto-servernum env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 pnpm run test:e2e:terminal-rendering-golden'
|
|
)
|
|
expect(releaseEvidenceJob['continue-on-error']).toBe(true)
|
|
expect(
|
|
releaseEvidenceJob.strategy.matrix.include.map(({ platform }) => platform).sort()
|
|
).toEqual(['linux', 'mac', 'windows'])
|
|
expect(releaseEvidenceJob.steps.map((step) => step.run ?? '')).toContain(
|
|
'xvfb-run --auto-servernum env SKIP_BUILD=1 ORCA_E2E_FORWARD_APP_LOGS=1 pnpm run test:e2e:terminal-rendering-release-evidence'
|
|
)
|
|
})
|
|
})
|