Apple signed binaries

This commit is contained in:
Pedram Amini
2025-12-12 18:27:06 -06:00
parent db2fc1a7ca
commit b8d557e7c2
6 changed files with 127 additions and 81 deletions

View File

@@ -109,38 +109,38 @@ jobs:
run: mkdir -p release
shell: bash
# Import Apple certificate for code signing
- name: Import Apple certificate
if: matrix.platform == 'mac'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
# Create keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Import certificate
echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
security import $RUNNER_TEMP/certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
# Allow codesign to access the key
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- name: Package for macOS
if: matrix.platform == 'mac'
run: npx electron-builder --mac --publish never --config.extraMetadata.version=${{ steps.version.outputs.VERSION }}
env:
CSC_IDENTITY_AUTO_DISCOVERY: false
CSC_LINK: ""
DEBUG: electron-builder
# Ad-hoc sign macOS apps and re-create archives
# Fixes "code has no resources but signature indicates they must be present"
- name: Ad-hoc sign macOS apps
if: matrix.platform == 'mac'
run: |
VERSION=${{ steps.version.outputs.VERSION }}
# Sign x64 app and recreate zip
if [ -d "release/mac/Maestro.app" ]; then
echo "Ad-hoc signing: release/mac/Maestro.app"
codesign --sign - --deep --force "release/mac/Maestro.app"
echo "Re-creating ZIP for x64..."
rm -f "release/Maestro-${VERSION}-mac.zip"
cd release/mac && zip -r -y "../Maestro-${VERSION}-mac.zip" Maestro.app && cd ../..
fi
# Sign arm64 app and recreate zip
if [ -d "release/mac-arm64/Maestro.app" ]; then
echo "Ad-hoc signing: release/mac-arm64/Maestro.app"
codesign --sign - --deep --force "release/mac-arm64/Maestro.app"
echo "Re-creating ZIP for arm64..."
rm -f "release/Maestro-${VERSION}-arm64-mac.zip"
cd release/mac-arm64 && zip -r -y "../Maestro-${VERSION}-arm64-mac.zip" Maestro.app && cd ../..
fi
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Package for Windows
if: matrix.platform == 'win'

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<false/>
</dict>
</plist>

90
package-lock.json generated
View File

@@ -1,14 +1,14 @@
{
"name": "maestro",
"version": "0.7.0",
"version": "0.8.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "maestro",
"version": "0.7.0",
"version": "0.8.0",
"hasInstallScript": true,
"license": "MIT",
"license": "AGPL 3.0",
"dependencies": {
"@emoji-mart/data": "^1.2.1",
"@emoji-mart/react": "^1.1.1",
@@ -42,6 +42,7 @@
"maestro-cli": "dist/cli/maestro-cli.js"
},
"devDependencies": {
"@electron/notarize": "^3.1.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/adm-zip": "^0.5.7",
@@ -755,57 +756,17 @@
}
},
"node_modules/@electron/notarize": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz",
"integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-3.1.1.tgz",
"integrity": "sha512-uQQSlOiJnqRkTL1wlEBAxe90nVN/Fc/hEmk0bqpKk8nKjV1if/tXLHKUPePtv9Xsx90PtZU8aidx5lAiOpjkQQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"fs-extra": "^9.0.1",
"debug": "^4.4.0",
"promise-retry": "^2.0.1"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/@electron/notarize/node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@electron/notarize/node_modules/jsonfile": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
"dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/@electron/notarize/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
"node": ">= 22.12.0"
}
},
"node_modules/@electron/osx-sign": {
@@ -3448,6 +3409,37 @@
"electron-builder-squirrel-windows": "24.13.3"
}
},
"node_modules/app-builder-lib/node_modules/@electron/notarize": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz",
"integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"fs-extra": "^9.0.1",
"promise-retry": "^2.0.1"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/app-builder-lib/node_modules/@electron/notarize/node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/app-builder-lib/node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
@@ -8510,7 +8502,6 @@
"integrity": "sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@acemir/cssom": "^0.9.23",
"@asamuzakjp/dom-selector": "^6.7.4",
@@ -14160,6 +14151,7 @@
"integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/expect": "4.0.15",
"@vitest/mocker": "4.0.15",

View File

@@ -1,6 +1,6 @@
{
"name": "maestro",
"version": "0.8.0",
"version": "0.8.1",
"description": "Run AI coding agents autonomously for days.",
"main": "dist/main/index.js",
"author": {
@@ -10,7 +10,7 @@
"license": "AGPL 3.0",
"repository": {
"type": "git",
"url": "https://github.com/yourusername/maestro.git"
"url": "https://github.com/pedramamini/maestro.git"
},
"bin": {
"maestro-cli": "./dist/cli/maestro-cli.js"
@@ -51,7 +51,11 @@
],
"mac": {
"category": "public.app-category.developer-tools",
"identity": null,
"hardenedRuntime": true,
"gatekeeperAssess": false,
"notarize": false,
"entitlements": "build/entitlements.mac.plist",
"entitlementsInherit": "build/entitlements.mac.plist",
"target": [
{
"target": "dmg",
@@ -76,6 +80,7 @@
}
]
},
"afterSign": "scripts/notarize.js",
"win": {
"target": [
{
@@ -149,6 +154,7 @@
"ws": "^8.16.0"
},
"devDependencies": {
"@electron/notarize": "^3.1.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/adm-zip": "^0.5.7",

34
scripts/notarize.js Normal file
View File

@@ -0,0 +1,34 @@
const { notarize } = require('@electron/notarize');
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
// Only notarize macOS builds
if (electronPlatformName !== 'darwin') {
return;
}
// Skip if not signing (CI without credentials, etc.)
if (process.env.CSC_IDENTITY_AUTO_DISCOVERY === 'false') {
console.log('Skipping notarization: CSC_IDENTITY_AUTO_DISCOVERY is false');
return;
}
const appName = context.packager.appInfo.productFilename;
const appPath = `${appOutDir}/${appName}.app`;
console.log(`Notarizing ${appPath}...`);
try {
await notarize({
appPath,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD,
teamId: process.env.APPLE_TEAM_ID,
});
console.log('Notarization complete!');
} catch (error) {
console.error('Notarization failed:', error);
throw error;
}
};

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { X, Wand2, ExternalLink, FileCode, BarChart3, Loader2, Trophy, Globe } from 'lucide-react';
import { X, Wand2, ExternalLink, FileCode, BarChart3, Loader2, Trophy, Globe, Check } from 'lucide-react';
import type { Theme, Session, AutoRunStats } from '../types';
import { useLayerStack } from '../contexts/LayerStackContext';
import { MODAL_PRIORITIES } from '../constants/modalPriorities';
@@ -329,7 +329,7 @@ export function AboutModal({ theme, sessions, autoRunStats, onClose, onOpenLeade
</span>
</div>
{isLeaderboardRegistered ? (
<span className="text-xs px-1.5 py-0.5 rounded font-medium" style={{ backgroundColor: theme.colors.success, color: '#000' }}>Active</span>
<Check className="w-4 h-4" style={{ color: theme.colors.success }} />
) : (
<ExternalLink className="w-4 h-4" style={{ color: theme.colors.textDim }} />
)}