name: Test Local Signing
on:
workflow_dispatch: # Manual trigger
push:
branches: [ozgur/build]
jobs:
test-local-signing:
runs-on: macos
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Create Test Entitlements
run: |
echo "๐ Creating entitlements file..."
cat > LuckyWorld.entitlements << EOF
com.apple.security.cs.allow-jit
com.apple.security.cs.allow-unsigned-executable-memory
com.apple.security.cs.disable-library-validation
com.apple.security.cs.allow-dyld-environment-variables
com.apple.security.device.audio-input
com.apple.security.device.camera
EOF
echo "โ
Created entitlements file"
cat LuckyWorld.entitlements
shell: bash
- name: Create Test App Bundle
run: |
echo "๐ฆ Creating test app bundle..."
# Create test app bundle structure
TEST_APP_DIR="TestApp.app"
mkdir -p "$TEST_APP_DIR/Contents/MacOS"
# Create a simple test executable
echo '#!/bin/bash
echo "Hello from TestApp!"' > "$TEST_APP_DIR/Contents/MacOS/TestApp"
chmod +x "$TEST_APP_DIR/Contents/MacOS/TestApp"
# Create Info.plist
cat > "$TEST_APP_DIR/Contents/Info.plist" << EOF
CFBundleExecutable
TestApp
CFBundleIdentifier
com.luckyrobots.luckyworld.testapp
CFBundleName
TestApp
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
LSMinimumSystemVersion
10.10
EOF
echo "โ
Created test app bundle"
# Verify app bundle exists
if [ ! -d "$TEST_APP_DIR" ]; then
echo "โ Error: App bundle not found at $TEST_APP_DIR"
exit 1
fi
echo "๐ App bundle contents:"
ls -la "$TEST_APP_DIR"
# Store app path as environment variable
echo "APP_PATH=$(pwd)/TestApp.app" >> "$GITHUB_ENV"
shell: bash
- name: Setup Certificate
env:
CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE }}
CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
echo "๐ Setting up certificate..."
# Create a temporary directory for certificates
CERT_DIR="$HOME/certificates"
mkdir -p "$CERT_DIR"
# Decode the certificate to a p12 file
echo "$CERTIFICATE_BASE64" | base64 --decode > "$CERT_DIR/certificate.p12"
# Check certificate format
echo "๐ Certificate format check:"
file "$CERT_DIR/certificate.p12"
# Create keychain
KEYCHAIN_PATH="$CERT_DIR/app-signing.keychain-db"
KEYCHAIN_PASSWORD="$(openssl rand -base64 12)"
# Delete existing keychain if it exists
security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true
# Create new keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -t 3600 -u -l "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Add to search list and make default
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
security default-keychain -s "$KEYCHAIN_PATH"
# Import certificate
echo "๐ Importing developer certificate..."
security import "$CERT_DIR/certificate.p12" -k "$KEYCHAIN_PATH" -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
# Set partition list for codesign to access keychain
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Verify certificate
echo "๐ Verifying certificate..."
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
# Store keychain variables for later steps
echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV"
echo "KEYCHAIN_PASSWORD=$KEYCHAIN_PASSWORD" >> "$GITHUB_ENV"
echo "APPLE_TEAM_ID=$APPLE_TEAM_ID" >> "$GITHUB_ENV"
# Cleanup
rm -f "$CERT_DIR/certificate.p12"
shell: bash
- name: Sign with Developer ID
run: |
echo "๐ Signing app with Developer ID certificate..."
# Make sure keychain is unlocked
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Get the Developer ID Application identity
IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep "Developer ID Application" | head -1 | awk -F '"' '{print $2}')
if [ -z "$IDENTITY" ]; then
echo "โ Error: No valid Developer ID Application identity found"
echo "Please check if your certificate is valid and properly imported"
exit 1
fi
echo "Using identity: $IDENTITY"
# Sign the app bundle
echo "Signing app bundle..."
codesign --force --deep --verbose --options runtime --entitlements LuckyWorld.entitlements --sign "$IDENTITY" --timestamp "$APP_PATH"
# Verify signing
echo "๐ Verifying signature..."
codesign -vvv --deep --strict "$APP_PATH"
# Check entitlements
echo "๐ Checking entitlements..."
codesign -d --entitlements - "$APP_PATH"
shell: bash
- name: Notarize App
if: success()
env:
APPLE_ID: ${{ secrets.APPLE_NOTARY_USER }}
APP_PASSWORD: ${{ secrets.APPLE_NOTARY_PASSWORD }}
run: |
echo "๐ค Notarizing app..."
# Make sure we have required secrets
if [ -z "$APPLE_ID" ] || [ -z "$APP_PASSWORD" ] || [ -z "$APPLE_TEAM_ID" ]; then
echo "โ ๏ธ Missing notarization credentials. Skipping notarization."
echo "NOTARIZED=false" >> "$GITHUB_ENV"
exit 0
fi
# Create zip for notarization
ZIP_PATH="TestApp-notarize.zip"
ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
echo "Submitting for notarization..."
xcrun notarytool submit "$ZIP_PATH" \
--apple-id "$APPLE_ID" \
--password "$APP_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
# Staple the notarization ticket
echo "Stapling notarization ticket..."
xcrun stapler staple "$APP_PATH"
# Verify notarization
echo "๐ Verifying notarization..."
spctl --assess --verbose --type exec "$APP_PATH"
echo "NOTARIZED=true" >> "$GITHUB_ENV"
shell: bash
- name: Package Signed App
run: |
echo "๐ฆ Packaging signed app..."
if [ "${NOTARIZED:-false}" == "true" ]; then
ZIP_FILE="TestApp-Signed-Notarized.zip"
echo "Creating distribution package with notarized app..."
else
ZIP_FILE="TestApp-Signed.zip"
echo "Creating distribution package with signed app..."
fi
# Create zip package
ditto -c -k --keepParent "$APP_PATH" "$ZIP_FILE"
echo "โ
Created package: $ZIP_FILE"
shell: bash
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: LuckyWorld-Signed-App
path: TestApp-*.zip
retention-days: 7
- name: Cleanup
if: always()
run: |
echo "๐งน Cleaning up..."
rm -rf TestApp.app TestApp-*.zip || true
security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true
echo "โ
Cleanup complete"
shell: bash