Skip to content

Commit 419fcb0

Browse files
AndrewAndrew
authored andcommitted
fixing mac pkg signing
fix boot race condition
1 parent 84b8f2a commit 419fcb0

File tree

2 files changed

+91
-33
lines changed

2 files changed

+91
-33
lines changed

.github/workflows/release.yml

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,21 @@ jobs:
195195
if [ -n "$APPLE_APP_CERT_BASE64" ]; then
196196
echo "=== Importing 3rd Party Mac Developer Application Certificate ==="
197197
echo "$APPLE_APP_CERT_BASE64" | base64 -d > app_cert.p12
198-
security import app_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
198+
# Use -A flag to allow ALL applications access (required for CI)
199+
security import app_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -A
199200
rm app_cert.p12
200-
echo "✅ Application certificate imported"
201+
echo "✅ Application certificate imported with unrestricted access"
201202
fi
202203
203204
# Import Installer certificate with productsign ACL
204205
if [ -n "$APPLE_INSTALLER_CERT_BASE64" ]; then
205206
echo "=== Importing 3rd Party Mac Developer Installer Certificate ==="
206207
echo "$APPLE_INSTALLER_CERT_BASE64" | base64 -d > installer_cert.p12
207-
# CRITICAL: Must include -T /usr/bin/productsign for installer cert to work
208-
# The -p codesigning policy doesn't include installer certs (different EKU)
209-
security import installer_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign -T /usr/bin/security
208+
# CRITICAL: Use -A flag to allow ALL applications access (required for CI)
209+
# Individual -T flags may not be sufficient on GitHub Actions runners
210+
security import installer_cert.p12 -k temp.keychain -P "$APPLE_CERT_PASSWORD" -A
210211
rm installer_cert.p12
211-
echo "✅ Installer certificate imported with productsign ACL"
212+
echo "✅ Installer certificate imported with unrestricted access"
212213
fi
213214
214215
# Download and import Apple WWDR intermediate certificate (required for cert chain validation)
@@ -218,8 +219,13 @@ jobs:
218219
rm AppleWWDRCAG3.cer
219220
echo "✅ Apple WWDR G3 intermediate certificate imported"
220221
221-
# Configure keychain
222-
security set-key-partition-list -S apple-tool:,apple:,codesign:,productsign: -s -k "$KEYCHAIN_PASSWORD" temp.keychain
222+
# Configure keychain partition list for unrestricted access
223+
# The -A flag during import should have set this, but we ensure it here
224+
# Using empty string ("") after -S allows unrestricted access
225+
security set-key-partition-list -S "apple-tool:,apple:,codesign:,productsign:" -s -k "$KEYCHAIN_PASSWORD" temp.keychain 2>/dev/null || {
226+
echo "Warning: Could not set partition list with specific tools, trying unrestricted..."
227+
security set-key-partition-list -S "" -s -k "$KEYCHAIN_PASSWORD" temp.keychain 2>/dev/null || true
228+
}
223229
security default-keychain -s temp.keychain
224230
security list-keychains -d user -s "$KEYCHAIN_PATH" "$HOME/Library/Keychains/login.keychain-db"
225231
@@ -307,6 +313,7 @@ jobs:
307313
- name: Sign macOS PKG
308314
env:
309315
APPLE_INSTALLER_CERT_BASE64: ${{ secrets.APPLE_INSTALLER_CERT_BASE64 }}
316+
APPLE_CERT_PASSWORD: ${{ secrets.APPLE_CERT_PASSWORD }}
310317
run: |
311318
if [ -z "$APPLE_INSTALLER_CERT_BASE64" ]; then
312319
echo "⚠️ APPLE_INSTALLER_CERT_BASE64 not set - skipping PKG signing"
@@ -315,16 +322,36 @@ jobs:
315322
316323
echo "=== Signing macOS PKG ==="
317324
318-
# CRITICAL: Unlock keychain immediately before productsign
319-
# The keychain may have auto-locked since import step
320-
echo "Unlocking keychain..."
325+
# CRITICAL: Re-unlock keychain and reset partition list
326+
# The build step takes time and keychain may have locked or partition list may need refresh
327+
echo "Step 1: Unlocking keychain..."
321328
security unlock-keychain -p "actions" temp.keychain
322329
security set-keychain-settings -lut 21600 temp.keychain
323330
324331
# Ensure temp.keychain is in search path and default
325332
security list-keychains -d user -s "$HOME/Library/Keychains/temp.keychain-db" "$HOME/Library/Keychains/login.keychain-db"
326333
security default-keychain -s temp.keychain
327334
335+
# CRITICAL: Re-apply partition list for ALL keys in keychain
336+
# This ensures productsign can access the private key without UI prompts
337+
echo "Step 2: Re-applying partition list for productsign access..."
338+
security set-key-partition-list -S "apple-tool:,apple:,codesign:,productsign:" -s -k "actions" temp.keychain 2>/dev/null || {
339+
echo "Warning: Could not set partition list, trying alternative method..."
340+
# Alternative: allow all partitions
341+
security set-key-partition-list -S "apple-tool:,apple:,codesign:,productsign:,teamid:" -s -k "actions" temp.keychain 2>/dev/null || true
342+
}
343+
344+
# Verify keychain is unlocked and has the right identity
345+
echo "Step 3: Verifying keychain state..."
346+
echo "Keychain list:"
347+
security list-keychains
348+
echo ""
349+
echo "Default keychain:"
350+
security default-keychain
351+
echo ""
352+
echo "Installer identities available:"
353+
security find-identity -v temp.keychain | grep -i "installer" || echo "WARNING: No installer identities found!"
354+
328355
PKG=$(find dist -name "*.pkg" | head -n 1)
329356
330357
if [ -z "$PKG" ]; then
@@ -337,19 +364,28 @@ jobs:
337364
fi
338365
339366
if [ -n "$PKG" ]; then
367+
echo ""
340368
echo "Found PKG: $PKG"
341369
echo "PKG size: $(ls -lh "$PKG" | awk '{print $5}')"
342370
343371
# Find installer identity
344372
INSTALLER_IDENTITY=$(security find-identity -v temp.keychain 2>&1 | grep "3rd Party Mac Developer Installer\|Developer ID Installer" | head -1 | sed 's/.*"\(.*\)".*/\1/')
345373
346374
if [ -n "$INSTALLER_IDENTITY" ]; then
347-
echo "Signing with: $INSTALLER_IDENTITY"
375+
echo "Signing with: $(echo "$INSTALLER_IDENTITY" | sed 's/Allow2.*/Allow2 ***/')"
376+
377+
# Final keychain unlock right before signing
378+
security unlock-keychain -p "actions" temp.keychain
379+
380+
echo ""
381+
echo "Step 4: Running productsign..."
348382
349383
# Run productsign with timeout to prevent hanging (macOS compatible)
350384
# 5 minute timeout should be more than enough for any PKG
351385
(
352-
productsign --sign "$INSTALLER_IDENTITY" --keychain temp.keychain "$PKG" "${PKG%.pkg}-signed.pkg"
386+
# Use KEYCHAIN environment variable as fallback
387+
export KEYCHAIN="$HOME/Library/Keychains/temp.keychain-db"
388+
productsign --sign "$INSTALLER_IDENTITY" --keychain temp.keychain "$PKG" "${PKG%.pkg}-signed.pkg" 2>&1
353389
) &
354390
SIGN_PID=$!
355391
@@ -369,16 +405,30 @@ jobs:
369405
if [ $TIMEOUT -eq 0 ]; then
370406
echo "❌ productsign timed out after 5 minutes"
371407
kill -9 $SIGN_PID 2>/dev/null || true
372-
echo "This usually means keychain access is blocked."
408+
echo ""
409+
echo "=== DEBUGGING INFO ==="
410+
echo "This usually means keychain access is blocked by macOS security."
411+
echo ""
373412
echo "Keychain info:"
374413
security list-keychains
414+
echo ""
415+
echo "Default keychain:"
375416
security default-keychain
417+
echo ""
418+
echo "Keychain status:"
419+
security show-keychain-info temp.keychain 2>&1 || true
420+
echo ""
421+
echo "Possible causes:"
422+
echo "1. Keychain partition list not set correctly for productsign"
423+
echo "2. Certificate private key requires interactive authorization"
424+
echo "3. Certificate chain validation failing"
376425
exit 1
377426
elif [ $EXIT_CODE -eq 0 ]; then
378427
mv "${PKG%.pkg}-signed.pkg" "$PKG"
379428
echo "✅ PKG signed successfully"
380429
381430
# Verify signature
431+
echo ""
382432
echo "Verifying signature..."
383433
pkgutil --check-signature "$PKG" || true
384434
else

app/main.js

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -630,25 +630,10 @@ migrateWemo();
630630
}
631631
})();
632632

633-
plugins.getInstalled((err, installedPlugins) => {
634-
if (err) {
635-
console.log('[Plugins] Error getting installed plugins:', err);
636-
return;
637-
}
638-
639-
console.log('[Plugins] Found installed plugins:', Object.keys(installedPlugins || {}).length);
640-
if (installedPlugins && Object.keys(installedPlugins).length > 0) {
641-
console.log('[Plugins] Installed plugin names:', Object.keys(installedPlugins));
642-
}
643-
644-
// Dispatch action to update store
645-
actions.installedPluginReplace(installedPlugins);
646-
console.log('[Plugins] Dispatched installedPluginReplace action to main store');
647-
648-
// Verify it's in the store
649-
const currentState = store.getState();
650-
console.log('[Plugins] Installed plugins in main store:', Object.keys(currentState.installedPlugins || {}).length);
651-
});
633+
// NOTE: plugins.getInstalled() is now called inside app.on('ready') AFTER
634+
// agent services are initialized. This ensures global.services is populated
635+
// before plugins try to access agent service.
636+
// See the initializeInstalledPlugins() function in the ready handler.
652637

653638
// seed test data
654639
function testData() {
@@ -850,6 +835,29 @@ app.on('ready', async () => {
850835
// Continue without agent services - they are optional
851836
}
852837

838+
// CRITICAL: Initialize installed plugins AFTER agent services are ready
839+
// This ensures global.services is populated before plugins try to access it
840+
console.log('[Main] Initializing installed plugins (after agent services)...');
841+
plugins.getInstalled((err, installedPlugins) => {
842+
if (err) {
843+
console.log('[Plugins] Error getting installed plugins:', err);
844+
return;
845+
}
846+
847+
console.log('[Plugins] Found installed plugins:', Object.keys(installedPlugins || {}).length);
848+
if (installedPlugins && Object.keys(installedPlugins).length > 0) {
849+
console.log('[Plugins] Installed plugin names:', Object.keys(installedPlugins));
850+
}
851+
852+
// Dispatch action to update store
853+
actions.installedPluginReplace(installedPlugins);
854+
console.log('[Plugins] Dispatched installedPluginReplace action to main store');
855+
856+
// Verify it's in the store
857+
const currentState = store.getState();
858+
console.log('[Plugins] Installed plugins in main store:', Object.keys(currentState.installedPlugins || {}).length);
859+
});
860+
853861
if (process.platform === 'darwin') {
854862
template.unshift({
855863
label: 'Allow2Automate', //app.getName(),

0 commit comments

Comments
 (0)