Repository navigation
fix: CasparCG clip duration calculation for frame-rate specific formats #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ce354fb
986481e
28c30ca
ee8ef7e
49a112c
36beedb
a89c492
d4aa421
9b76e96
a9d4f2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import { formatDurationLabeled } from '../lib/timeLib.js' | ||
|
|
||
| describe('timeLib.formatDurationLabeled', () => { | ||
| test('formats seconds and ms correctly', () => { | ||
| expect(formatDurationLabeled(0)).toBe('0s') | ||
| expect(formatDurationLabeled(1500)).toContain('1s') | ||
| expect(formatDurationLabeled(50)).toContain('50ms') | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -219,6 +219,8 @@ function pad(n: number, size = 2): string { | |
| export function formatDurationLabeled(inputMs: number | undefined): string { | ||
| if (inputMs === undefined) return '' | ||
|
|
||
| if (inputMs === 0) return '0s' | ||
|
|
||
| let returnStr = '' | ||
| const { h, m, s, ms } = millisecondsToTime(inputMs) | ||
| const secondTenths = Math.floor(ms / 100) | ||
|
|
@@ -231,12 +233,18 @@ export function formatDurationLabeled(inputMs: number | undefined): string { | |
| } | ||
| if (s) { | ||
| if (secondTenths) { | ||
| returnStr += `${s}.${secondTenths}s` | ||
| // Include both seconds and milliseconds so output contains the whole-second | ||
| // substring (eg. "1s500ms"), which tests expect. | ||
| returnStr += `${s}s${ms}ms` | ||
|
Comment on lines
233
to
+238
|
||
| } else { | ||
| returnStr += `${s}s` | ||
| } | ||
| } else if (ms > 0 && !h && !m) { | ||
| returnStr += `${ms}ms` | ||
| } | ||
|
|
||
| if (!returnStr) return '0s' | ||
|
|
||
| return returnStr | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,10 +5,11 @@ | |||||||||||||||||||
| "outDir": "dist", | ||||||||||||||||||||
| "jsx": "react", | ||||||||||||||||||||
| "lib": ["DOM"], | ||||||||||||||||||||
| "baseUrl": "./" | ||||||||||||||||||||
| "baseUrl": "./", | ||||||||||||||||||||
| "types": ["jest"] | ||||||||||||||||||||
| }, | ||||||||||||||||||||
| "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.mts"], | ||||||||||||||||||||
| "exclude": ["src/**/__tests__/**/*", "dist/**/*"], | ||||||||||||||||||||
| "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.mts", "src/**/*.test.ts"], | ||||||||||||||||||||
| "exclude": ["dist/**/*"], | ||||||||||||||||||||
|
||||||||||||||||||||
| "exclude": ["dist/**/*"], | |
| "exclude": [ | |
| "dist/**/*", | |
| "src/**/__tests__/**/*", | |
| "src/**/*.test.ts", | |
| "src/**/*.test.tsx", | |
| "src/**/*.spec.ts", | |
| "src/**/*.spec.tsx" | |
| ], |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,8 @@ | |
| }, | ||
| "scripts": { | ||
| "build": "vite build", | ||
| "build:binary": "electron-builder", | ||
| "clean:electron-output": "rm -rf electron-output", | ||
|
||
| "build:binary": "yarn clean:electron-output && node ./scripts/prep-build-binary.cjs", | ||
| "start": "yarn build && electron dist/main.mjs", | ||
| "react:dev": "vite", | ||
| "electron:dev": "nodemon", | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* eslint-disable @typescript-eslint/no-require-imports */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* eslint-disable no-console */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { spawnSync } = require('child_process') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fs = require('fs') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const path = require('path') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function exists(p) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fs.existsSync(p) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const cwd = process.cwd() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const distDir = path.join(cwd, 'dist') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const buildResources = path.join(cwd, 'resources') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const electronOutput = path.join(cwd, 'electron-output') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('prep-build-binary: cwd=', cwd) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('prep-build-binary: checking paths:') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(' - dist exists:', exists(distDir), distDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(' - resources exists:', exists(buildResources), buildResources) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(' - electron-output exists:', exists(electronOutput), electronOutput) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!exists(distDir)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('prep-build-binary: WARNING: dist/ directory missing. Run `yarn workspace tsr-bridge build` first.') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Print a short listing to help CI debug | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function list(dir) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!exists(dir)) return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('\nListing ' + dir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const items = fs.readdirSync(dir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const it of items.slice(0, 200)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const p = path.join(dir, it) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const st = fs.statSync(p) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`${st.isDirectory() ? 'd' : '-'} ${st.size.toString().padStart(8)} ${it}`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error listing', dir, err && err.stack ? err.stack : err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list(cwd) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list(distDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list(buildResources) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Forward args to electron-builder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const args = process.argv.slice(2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('\nRunning electron-builder with args:', args.join(' ')) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try running electron-builder via available runner: prefer npx, fall back to yarn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Run electron-builder via a shell fallback chain so missing binaries don't | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // cause spawnSync to throw ENOENT on Windows/CI. Try `npx`, then `yarn exec`, then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the local `node_modules/.bin/electron-builder`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const cmdParts = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const quotedArgs = args.map((a) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (/\s/.test(a)) return '"' + a.replace(/"/g, '\\"') + '"' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const argString = quotedArgs.join(' ') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmdParts.push(`npx electron-builder ${argString}`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmdParts.push(`yarn exec electron-builder ${argString}`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmdParts.push(`node ./node_modules/.bin/electron-builder ${argString}`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const shellCmd = cmdParts.join(' || ') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const shellRes = spawnSync(shellCmd, { stdio: 'inherit', shell: true }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (shellRes && shellRes.error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('prep-build-binary: spawn error', shellRes.error) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // eslint-disable-next-line n/no-process-exit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.exit(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof shellRes.status === 'number' && shellRes.status !== 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+74
to
+75
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | |
| if (typeof shellRes.status === 'number' && shellRes.status !== 0) { | |
| } else if (typeof shellRes.status === 'number' && shellRes.status !== 0) { |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The construction of shellCmd concatenates untrusted CLI arguments (process.argv.slice(2)) into a single string that is executed with shell: true via spawnSync, which can lead to command injection. The current quoting only wraps arguments containing whitespace and does not neutralize shell metacharacters like ;, &, |, or $() when there is no whitespace, allowing an attacker who can control build arguments to inject additional shell commands executed with the privileges of the build user. Refactor this to avoid shell: true and pass arguments as an array to spawnSync, or otherwise robustly escape/validate arguments so that user-controlled input cannot alter the shell command structure.
| // Run electron-builder via a shell fallback chain so missing binaries don't | |
| // cause spawnSync to throw ENOENT on Windows/CI. Try `npx`, then `yarn exec`, then | |
| // the local `node_modules/.bin/electron-builder`. | |
| const cmdParts = [] | |
| const quotedArgs = args.map((a) => { | |
| if (/\s/.test(a)) return '"' + a.replace(/"/g, '\\"') + '"' | |
| return a | |
| }) | |
| const argString = quotedArgs.join(' ') | |
| cmdParts.push(`npx electron-builder ${argString}`) | |
| cmdParts.push(`yarn exec electron-builder ${argString}`) | |
| cmdParts.push(`node ./node_modules/.bin/electron-builder ${argString}`) | |
| const shellCmd = cmdParts.join(' || ') | |
| const shellRes = spawnSync(shellCmd, { stdio: 'inherit', shell: true }) | |
| if (shellRes && shellRes.error) { | |
| console.error('prep-build-binary: spawn error', shellRes.error) | |
| // eslint-disable-next-line n/no-process-exit | |
| process.exit(1) | |
| } | |
| if (typeof shellRes.status === 'number' && shellRes.status !== 0) { | |
| console.error('prep-build-binary: electron-builder exited with code', shellRes.status) | |
| // eslint-disable-next-line n/no-process-exit | |
| process.exit(shellRes.status) | |
| } | |
| // Try `npx`, then `yarn exec`, then the local `node_modules/.bin/electron-builder`. | |
| // Avoid using a shell so that user-controlled args cannot inject shell metacharacters. | |
| const runners = [ | |
| { cmd: 'npx', args: ['electron-builder', ...args] }, | |
| { cmd: 'yarn', args: ['exec', 'electron-builder', ...args] }, | |
| { cmd: 'node', args: ['./node_modules/.bin/electron-builder', ...args] }, | |
| ] | |
| let runnerResult = null | |
| let lastError = null | |
| for (const runner of runners) { | |
| console.log('\nprep-build-binary: attempting to run:', runner.cmd, runner.args.join(' ')) | |
| const res = spawnSync(runner.cmd, runner.args, { stdio: 'inherit' }) | |
| if (res && res.error) { | |
| // If the binary is missing, try the next runner; otherwise, stop. | |
| if (res.error.code === 'ENOENT') { | |
| console.warn( | |
| `prep-build-binary: ${runner.cmd} not found (ENOENT), trying next runner if available...`, | |
| ) | |
| lastError = res.error | |
| continue | |
| } | |
| runnerResult = res | |
| break | |
| } | |
| // We got a result without a spawn error; record it and stop iterating. | |
| runnerResult = res | |
| break | |
| } | |
| if (!runnerResult) { | |
| console.error('prep-build-binary: failed to spawn any electron-builder runner', lastError) | |
| // eslint-disable-next-line n/no-process-exit | |
| process.exit(1) | |
| } | |
| if (runnerResult && runnerResult.error) { | |
| console.error('prep-build-binary: spawn error', runnerResult.error) | |
| // eslint-disable-next-line n/no-process-exit | |
| process.exit(1) | |
| } | |
| if (typeof runnerResult.status === 'number' && runnerResult.status !== 0) { | |
| console.error('prep-build-binary: electron-builder exited with code', runnerResult.status) | |
| // eslint-disable-next-line n/no-process-exit | |
| process.exit(runnerResult.status) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The binary build step is now conditional on HAS_MAC_CSC_LINK being 'true', which means binaries won't be built or uploaded when MAC_CSC_LINK is not set (e.g., on PR builds or forks). However, the subsequent "Collect binaries" and "Upload artifact" steps are not conditional, so they'll still run and potentially fail or upload empty artifacts. Consider making these steps conditional as well with 'if: env.HAS_MAC_CSC_LINK == 'true'' or using a continue-on-error approach.