mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
ci(release-cut): retry the installs that fetch node-gyp headers
`golden e2e windows` installs with lifecycle scripts enabled, so pnpm runs node-gyp for the `native/windows-registry` workspace project, which downloads that Node version's headers from nodejs.org. A single `read ECONNRESET` on that fetch failed a blocking release gate, and the release build job one screen below already wraps its install in `nick-fields/retry@v4` for exactly this class of failure. Both remaining unretried installs in this workflow (the blocking platform golden and the non-blocking rendering-evidence lane) now use the same wrapper, and a contract test keeps every release-cut install retryable.
This commit is contained in:
@@ -871,8 +871,17 @@ jobs:
|
||||
npm install -g node-gyp@11.5.0
|
||||
echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV"
|
||||
|
||||
# Why: this install runs lifecycle scripts, so node-gyp rebuilds
|
||||
# native/windows-registry and fetches that Node version's headers from
|
||||
# nodejs.org. One `read ECONNRESET` there failed this blocking gate and the
|
||||
# whole cut. Retry like the release build's install below.
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
uses: nick-fields/retry@v4
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 30
|
||||
command: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build Electron app for platform golden
|
||||
run: npx electron-vite build --mode e2e
|
||||
@@ -1088,8 +1097,14 @@ jobs:
|
||||
npm install -g node-gyp@11.5.0
|
||||
echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV"
|
||||
|
||||
# Same node-gyp header fetch as the blocking golden gate above.
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
uses: nick-fields/retry@v4
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 30
|
||||
command: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build Electron app for terminal rendering evidence
|
||||
run: npx electron-vite build --mode e2e
|
||||
|
||||
@@ -32,25 +32,37 @@ describe('CI dependency download caches', () => {
|
||||
describe('release install targets', () => {
|
||||
const macCpuFlag = '--cpu=current,x64,arm64'
|
||||
// Both shapes: `run:` steps and steps wrapped in nick-fields/retry (`with.command`).
|
||||
const installCommand = (step) => step.with?.command ?? step.run
|
||||
const installSteps = (name) =>
|
||||
Object.values(workflow(name).jobs)
|
||||
.flatMap((job) => job.steps ?? [])
|
||||
.map((step) => step.with?.command ?? step.run)
|
||||
.filter((command) => typeof command === 'string' && command.includes('pnpm install '))
|
||||
.filter((step) => installCommand(step)?.includes('pnpm install '))
|
||||
const installCommands = (name) => installSteps(name).map(installCommand)
|
||||
|
||||
it.each(['adhoc-mac-build', 'daily-mac-build', 'hourly-mac-build', 'release-mac-build'])(
|
||||
'%s installs both mac CPU variants for the x64+arm64 package config',
|
||||
(name) => {
|
||||
const installs = installSteps(name)
|
||||
const installs = installCommands(name)
|
||||
expect(installs.length).toBeGreaterThan(0)
|
||||
expect(installs.some((command) => command.includes(macCpuFlag))).toBe(true)
|
||||
}
|
||||
)
|
||||
|
||||
// A transient `read ECONNRESET` fetching this Node version's headers for
|
||||
// native/windows-registry's node-gyp rebuild failed a blocking golden gate and the cut.
|
||||
it('retries every release-cut install so one transient download cannot fail a cut', () => {
|
||||
const installs = installSteps('release-cut')
|
||||
expect(installs.length).toBeGreaterThan(0)
|
||||
for (const step of installs) {
|
||||
expect(step.uses).toBe('nick-fields/retry@v4')
|
||||
expect(step.with.max_attempts).toBeGreaterThan(1)
|
||||
}
|
||||
})
|
||||
|
||||
it.each(['release-cut', 'dev-channel-win-build', 'windows-signing-rehearsal'])(
|
||||
'%s keeps installs scoped to the runner host',
|
||||
(name) => {
|
||||
const installs = installSteps(name)
|
||||
const installs = installCommands(name)
|
||||
expect(installs.length).toBeGreaterThan(0)
|
||||
for (const command of installs) {
|
||||
expect(command).not.toContain('--os=')
|
||||
|
||||
@@ -16,7 +16,7 @@ const openGate = vi.hoisted(() => ({
|
||||
}))
|
||||
|
||||
// Models Windows delete-pending rmdir: the first removal wins and every later one gets EPERM.
|
||||
const deletePendingGate = vi.hoisted(() => ({ removed: null as Set<string> | null }))
|
||||
const deletePendingGate = vi.hoisted((): { removed: Set<string> | null } => ({ removed: null }))
|
||||
|
||||
vi.mock('node:fs/promises', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof NodeFsPromises>()
|
||||
|
||||
Reference in New Issue
Block a user