164 lines
6.6 KiB
JavaScript
164 lines
6.6 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: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'
|
|
)
|
|
})
|
|
})
|