Skip to content

Commit 2c64fb3

Browse files
JooHyung Parkclaude
andcommitted
fix(mas): re-sign helpers with correct entitlements in postPackage hook
Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 75124cb commit 2c64fb3

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

forge.config.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { FusesPlugin } from '@electron-forge/plugin-fuses';
99
import { FuseV1Options, FuseVersion } from '@electron/fuses';
1010
import { PublisherGithub } from '@electron-forge/publisher-github';
1111
import dotenv from 'dotenv';
12+
import { execSync } from 'child_process';
13+
import * as fs from 'fs';
14+
import * as path from 'path';
1215

1316
// Load environment variables from .env file (local development only)
1417
dotenv.config();
@@ -68,6 +71,64 @@ const config: ForgeConfig = {
6871
},
6972
},
7073
rebuildConfig: {},
74+
// Hooks for post-processing after packaging
75+
hooks: {
76+
postPackage: async (_config, options) => {
77+
// Only run for MAS builds on macOS
78+
if (!isMAS || options.platform !== 'mas') {
79+
return;
80+
}
81+
82+
console.log('[postPackage] Re-signing helper apps with correct entitlements for MAS...');
83+
84+
const appPath = options.outputPaths[0];
85+
const frameworksPath = path.join(appPath, 'Contents', 'Frameworks');
86+
const identity = process.env.SIGNING_IDENTITY_APPSTORE || 'Apple Distribution';
87+
const childEntitlements = path.resolve('entitlements.child.plist');
88+
89+
if (!fs.existsSync(frameworksPath)) {
90+
console.log('[postPackage] No Frameworks directory found, skipping helper re-signing');
91+
return;
92+
}
93+
94+
// Find all helper apps
95+
const items = fs.readdirSync(frameworksPath);
96+
const helperApps = items.filter(item => item.endsWith('.app'));
97+
98+
for (const helperApp of helperApps) {
99+
const helperPath = path.join(frameworksPath, helperApp);
100+
console.log(`[postPackage] Re-signing helper: ${helperApp}`);
101+
102+
try {
103+
// Re-sign the helper app with child entitlements (inherit only)
104+
execSync(
105+
`codesign --force --sign "${identity}" --entitlements "${childEntitlements}" --timestamp=none "${helperPath}"`,
106+
{ stdio: 'inherit' }
107+
);
108+
console.log(`[postPackage] ✅ Successfully re-signed: ${helperApp}`);
109+
} catch (error) {
110+
console.error(`[postPackage] ❌ Failed to re-sign ${helperApp}:`, error);
111+
throw error;
112+
}
113+
}
114+
115+
// Re-sign the main app to update the seal after helper modifications
116+
console.log('[postPackage] Re-signing main app to update seal...');
117+
const mainEntitlements = path.resolve('entitlements.mas.plist');
118+
try {
119+
execSync(
120+
`codesign --force --sign "${identity}" --entitlements "${mainEntitlements}" --timestamp=none "${appPath}"`,
121+
{ stdio: 'inherit' }
122+
);
123+
console.log('[postPackage] ✅ Successfully re-signed main app');
124+
} catch (error) {
125+
console.error('[postPackage] ❌ Failed to re-sign main app:', error);
126+
throw error;
127+
}
128+
129+
console.log('[postPackage] Helper re-signing complete');
130+
},
131+
},
71132
makers: [
72133
// macOS: DMG (primary) and ZIP (backup/CI) for Developer ID distribution
73134
new MakerDMG({

0 commit comments

Comments
 (0)