fix: fail Linux packaging when libffmpeg staging is missing

This commit is contained in:
2026-04-05 10:55:55 -07:00
parent fa89c43f74
commit 1a70a59ab1
3 changed files with 40 additions and 13 deletions

View File

@@ -1,11 +1,11 @@
--- ---
id: TASK-279 id: TASK-279
title: Fix Linux AppImage child-process libffmpeg resolution title: Fix Linux AppImage child-process libffmpeg resolution
status: Done status: In Progress
assignee: assignee:
- '@codex' - '@codex'
created_date: '2026-04-05 17:17' created_date: '2026-04-05 17:17'
updated_date: '2026-04-05 17:21' updated_date: '2026-04-05 17:55'
labels: [] labels: []
dependencies: [] dependencies: []
references: references:
@@ -45,6 +45,8 @@ Chose a repo-local electron-builder `afterPack` hook instead of patching/forking
Added regression coverage for both config wiring (`src/release-workflow.test.ts`) and the hook behavior (`scripts/electron-builder-after-pack.test.ts`), then wired the new script test into `test:fast` so the maintained lane keeps exercising the fix. Added regression coverage for both config wiring (`src/release-workflow.test.ts`) and the hook behavior (`scripts/electron-builder-after-pack.test.ts`), then wired the new script test into `test:fast` so the maintained lane keeps exercising the fix.
Verification passed: `bun test scripts/electron-builder-after-pack.test.ts src/release-workflow.test.ts`, `bun run typecheck`, `bun run test:fast`, `bun run test:env`, `bun run build`, `bun run test:smoke:dist`. Verification passed: `bun test scripts/electron-builder-after-pack.test.ts src/release-workflow.test.ts`, `bun run typecheck`, `bun run test:fast`, `bun run test:env`, `bun run build`, `bun run test:smoke:dist`.
Addressed PR #45 CodeRabbit review thread: Linux `afterPack` staging now hard-fails when `libffmpeg.so` is missing instead of silently no-oping. Updated focused hook tests to assert the new failure contract and that `afterPack` propagates Linux staging errors.
<!-- SECTION:NOTES:END --> <!-- SECTION:NOTES:END -->
## Final Summary ## Final Summary

View File

@@ -17,8 +17,13 @@ async function stageLinuxAppImageSharedLibrary(
try { try {
await deps.access(sourceLibraryPath); await deps.access(sourceLibraryPath);
} catch { } catch (error) {
return false; if (error && typeof error === 'object' && error.code === 'ENOENT') {
throw new Error(
`Linux packaging requires ${LINUX_FFMPEG_LIBRARY} at ${sourceLibraryPath} so AppImage child processes can resolve it.`,
);
}
throw error;
} }
const targetLibraryDir = path.join(context.appOutDir, 'usr', 'lib'); const targetLibraryDir = path.join(context.appOutDir, 'usr', 'lib');

View File

@@ -6,9 +6,11 @@ import test from 'node:test';
const { const {
LINUX_FFMPEG_LIBRARY, LINUX_FFMPEG_LIBRARY,
default: afterPack,
stageLinuxAppImageSharedLibrary, stageLinuxAppImageSharedLibrary,
} = require('./electron-builder-after-pack.cjs') as { } = require('./electron-builder-after-pack.cjs') as {
LINUX_FFMPEG_LIBRARY: string; LINUX_FFMPEG_LIBRARY: string;
default: (context: { appOutDir: string; electronPlatformName: string }) => Promise<void>;
stageLinuxAppImageSharedLibrary: (context: { stageLinuxAppImageSharedLibrary: (context: {
appOutDir: string; appOutDir: string;
electronPlatformName: string; electronPlatformName: string;
@@ -63,21 +65,39 @@ test('stageLinuxAppImageSharedLibrary skips non-Linux packaging contexts', async
} }
}); });
test('stageLinuxAppImageSharedLibrary no-ops when libffmpeg.so is absent', async () => { test('stageLinuxAppImageSharedLibrary throws when Linux packaging is missing libffmpeg.so', async () => {
const workspace = createWorkspace('subminer-after-pack-missing-library'); const workspace = createWorkspace('subminer-after-pack-missing-library');
const appOutDir = path.join(workspace, 'SubMiner-linux-x64'); const appOutDir = path.join(workspace, 'SubMiner-linux-x64');
const targetLibraryPath = path.join(appOutDir, 'usr', 'lib', LINUX_FFMPEG_LIBRARY);
fs.mkdirSync(appOutDir, { recursive: true }); fs.mkdirSync(appOutDir, { recursive: true });
try { try {
const staged = await stageLinuxAppImageSharedLibrary({ await assert.rejects(
appOutDir, stageLinuxAppImageSharedLibrary({
electronPlatformName: 'linux', appOutDir,
}); electronPlatformName: 'linux',
}),
assert.equal(staged, false); new RegExp(`Linux packaging requires ${LINUX_FFMPEG_LIBRARY} at .*${LINUX_FFMPEG_LIBRARY}`),
assert.equal(fs.existsSync(targetLibraryPath), false); );
} finally {
fs.rmSync(workspace, { recursive: true, force: true });
}
});
test('afterPack propagates Linux staging failures', async () => {
const workspace = createWorkspace('subminer-after-pack-propagates-linux-failure');
const appOutDir = path.join(workspace, 'SubMiner-linux-x64');
fs.mkdirSync(appOutDir, { recursive: true });
try {
await assert.rejects(
afterPack({
appOutDir,
electronPlatformName: 'linux',
}),
/Linux packaging requires libffmpeg\.so/,
);
} finally { } finally {
fs.rmSync(workspace, { recursive: true, force: true }); fs.rmSync(workspace, { recursive: true, force: true });
} }