fix(actions): streamline macOS build workflow by integrating DMG signing and notarization directly into the macos-notarize action
This commit is contained in:
parent
71e5075d42
commit
659b5de3ea
@ -692,6 +692,113 @@ runs:
|
||||
|
||||
if [ -f "$DMG_FILE" ]; then
|
||||
echo "✅ Created DMG package: $DMG_FILE"
|
||||
|
||||
# Sign the DMG with the same certificate used for the app
|
||||
echo "Signing DMG file..."
|
||||
|
||||
# Decide which keychain to use
|
||||
if [ "${{ steps.setup-cert.outputs.use_system_cert }}" = "true" ]; then
|
||||
echo "Using system keychain identity"
|
||||
# Get certificate hash instead of name to avoid ambiguity
|
||||
IDENTITY_HASH=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | awk '{print $2}')
|
||||
echo "Using certificate hash: $IDENTITY_HASH"
|
||||
else
|
||||
# Make sure keychain is unlocked
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
echo "Using custom keychain identity"
|
||||
# Get certificate hash instead of name to avoid ambiguity
|
||||
IDENTITY_HASH=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep "Developer ID Application" | head -1 | awk '{print $2}')
|
||||
echo "Using certificate hash: $IDENTITY_HASH"
|
||||
fi
|
||||
|
||||
if [ -n "$IDENTITY_HASH" ]; then
|
||||
# Sign the DMG
|
||||
codesign --force --sign "$IDENTITY_HASH" --options runtime --timestamp "$DMG_FILE"
|
||||
|
||||
# Verify DMG signature
|
||||
echo "Verifying DMG signature..."
|
||||
codesign -vvv "$DMG_FILE"
|
||||
|
||||
# Only notarize DMG if the app was successfully notarized
|
||||
if [ "${{ steps.notarize.outputs.notarized }}" = "true" ]; then
|
||||
echo "Notarizing DMG file..."
|
||||
|
||||
# Check if we're using API key notarization method
|
||||
if [ "${{ inputs.notarization-method }}" = "api-key" ] && [ -n "$API_KEY_ID" ] && [ -n "$API_ISSUER_ID" ] && [ -n "$API_KEY_PATH" ]; then
|
||||
# Use the same API key setup from the notarize step
|
||||
echo "Using App Store Connect API key for DMG notarization..."
|
||||
|
||||
echo "Submitting DMG for notarization..."
|
||||
DMG_SUBMIT_OUTPUT=$(xcrun notarytool submit "$DMG_FILE" \
|
||||
--key ~/private_keys/AuthKey_${API_KEY_ID}.p8 \
|
||||
--key-id "$API_KEY_ID" \
|
||||
--issuer "$API_ISSUER_ID" --wait 2>&1)
|
||||
|
||||
echo "DMG notarization submission output:"
|
||||
echo "$DMG_SUBMIT_OUTPUT"
|
||||
|
||||
# Extract DMG submission ID
|
||||
DMG_SUBMISSION_ID=$(echo "$DMG_SUBMIT_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
||||
|
||||
if [ -n "$DMG_SUBMISSION_ID" ] && echo "$DMG_SUBMIT_OUTPUT" | grep -q "status: Accepted"; then
|
||||
echo "✅ DMG notarization completed successfully!"
|
||||
|
||||
# Staple the DMG
|
||||
echo "Stapling notarization ticket to DMG..."
|
||||
xcrun stapler staple "$DMG_FILE"
|
||||
|
||||
# Verify DMG stapling
|
||||
echo "Verifying DMG stapling..."
|
||||
xcrun stapler validate "$DMG_FILE"
|
||||
|
||||
echo "DMG is now fully signed, notarized, and stapled!"
|
||||
else
|
||||
echo "⚠️ DMG notarization may have failed or is still in progress."
|
||||
echo "The app itself is still properly notarized, but the DMG may need manual verification."
|
||||
fi
|
||||
elif [ "${{ inputs.notarization-method }}" = "app-password" ] && [ -n "$APPLE_ID" ] && [ -n "$APP_PASSWORD" ] && [ -n "$APPLE_TEAM_ID" ]; then
|
||||
# Use App-specific password for DMG notarization
|
||||
echo "Using App-specific password for DMG notarization..."
|
||||
|
||||
echo "Submitting DMG for notarization..."
|
||||
DMG_SUBMIT_OUTPUT=$(xcrun notarytool submit "$DMG_FILE" \
|
||||
--apple-id "$APPLE_ID" \
|
||||
--password "$APP_PASSWORD" \
|
||||
--team-id "$APPLE_TEAM_ID" --wait 2>&1)
|
||||
|
||||
echo "DMG notarization submission output:"
|
||||
echo "$DMG_SUBMIT_OUTPUT"
|
||||
|
||||
# Extract DMG submission ID
|
||||
DMG_SUBMISSION_ID=$(echo "$DMG_SUBMIT_OUTPUT" | grep -o "id: [a-f0-9\-]*" | head -1 | cut -d ' ' -f 2)
|
||||
|
||||
if [ -n "$DMG_SUBMISSION_ID" ] && echo "$DMG_SUBMIT_OUTPUT" | grep -q "status: Accepted"; then
|
||||
echo "✅ DMG notarization completed successfully!"
|
||||
|
||||
# Staple the DMG
|
||||
echo "Stapling notarization ticket to DMG..."
|
||||
xcrun stapler staple "$DMG_FILE"
|
||||
|
||||
# Verify DMG stapling
|
||||
echo "Verifying DMG stapling..."
|
||||
xcrun stapler validate "$DMG_FILE"
|
||||
|
||||
echo "DMG is now fully signed, notarized, and stapled!"
|
||||
else
|
||||
echo "⚠️ DMG notarization may have failed or is still in progress."
|
||||
echo "The app itself is still properly notarized, but the DMG may need manual verification."
|
||||
fi
|
||||
else
|
||||
echo "⚠️ DMG not notarized due to missing credentials."
|
||||
echo "The app itself is properly notarized, but the DMG is only signed."
|
||||
fi
|
||||
else
|
||||
echo "App was not notarized, skipping DMG notarization."
|
||||
fi
|
||||
else
|
||||
echo "⚠️ No valid identity found for DMG signing. DMG will be created but not signed."
|
||||
fi
|
||||
|
||||
# Use DMG as the primary package if available
|
||||
echo "::set-output name=package-path::$DMG_FILE"
|
||||
echo "::set-output name=zip-package-path::$ZIP_FILE"
|
||||
|
@ -314,26 +314,6 @@ jobs:
|
||||
echo "STAPLED_APP_PATH=$APP_PATH" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
|
||||
# Create a properly archived ZIP of the stapled app (preserves stapling)
|
||||
- name: Create Stapled App Archive (ZIP)
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none'
|
||||
run: |
|
||||
STAPLED_APP_PATH="${{ env.STAPLED_APP_PATH }}"
|
||||
APP_NAME=$(basename "$STAPLED_APP_PATH" .app)
|
||||
ARCHIVE_DIR="./ArchivedApps"
|
||||
mkdir -p "$ARCHIVE_DIR"
|
||||
|
||||
# Create the ZIP archive (preserving all metadata)
|
||||
echo "Creating ZIP archive of stapled app..."
|
||||
cd "$(dirname "$STAPLED_APP_PATH")"
|
||||
# Use ditto to preserve all metadata and permissions
|
||||
ditto -c -k --keepParent "$(basename "$STAPLED_APP_PATH")" "$GITHUB_WORKSPACE/$ARCHIVE_DIR/$APP_NAME.zip"
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
|
||||
echo "ZIP archive created at: $ARCHIVE_DIR/$APP_NAME.zip"
|
||||
echo "STAPLED_APP_ZIP=$ARCHIVE_DIR/$APP_NAME.zip" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
|
||||
# Create a DMG file (macOS disk image) for easy distribution
|
||||
- name: Create DMG for Distribution
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none'
|
||||
@ -343,77 +323,17 @@ jobs:
|
||||
ARCHIVE_DIR="./ArchivedApps"
|
||||
DMG_FILE="$ARCHIVE_DIR/$APP_NAME.dmg"
|
||||
|
||||
# Create a DMG file
|
||||
echo "Creating DMG file..."
|
||||
hdiutil create -volname "$APP_NAME" -srcfolder "$STAPLED_APP_PATH" -ov -format UDZO "$DMG_FILE"
|
||||
# Note: The actual DMG creation, signing, notarization and stapling
|
||||
# are now handled by the macos-notarize action
|
||||
|
||||
# Sign the DMG with the same certificate
|
||||
echo "Signing DMG file..."
|
||||
# Extract certificate info from the previously signed app
|
||||
CERT_IDENTITY=$(codesign -dvv "$STAPLED_APP_PATH" 2>&1 | grep "Authority" | head -1 | sed -e 's/.*Authority=//g')
|
||||
echo "Using certificate identity: $CERT_IDENTITY"
|
||||
|
||||
# Sign the DMG
|
||||
codesign --sign "$CERT_IDENTITY" --options runtime --timestamp "$DMG_FILE"
|
||||
|
||||
# Verify DMG signature
|
||||
echo "Verifying DMG signature..."
|
||||
codesign -vvv "$DMG_FILE"
|
||||
|
||||
# Notarize the DMG
|
||||
echo "Notarizing DMG file..."
|
||||
# Select which authentication method to use for notarization
|
||||
if [ -n "${{ secrets.NOTARY_API_KEY_ID }}" ] && [ -n "${{ secrets.NOTARY_API_KEY_ISSUER_ID }}" ]; then
|
||||
# Use API Key authentication (preferred)
|
||||
echo "Using Notary API Key authentication..."
|
||||
UUID=$(xcrun notarytool submit "$DMG_FILE" \
|
||||
--key "${{ secrets.NOTARY_API_KEY_PATH }}" \
|
||||
--key-id "${{ secrets.NOTARY_API_KEY_ID }}" \
|
||||
--issuer "${{ secrets.NOTARY_API_KEY_ISSUER_ID }}" \
|
||||
--wait | grep "id:" | awk '{print $2}')
|
||||
elif [ -n "${{ secrets.APPLE_ID }}" ] && [ -n "${{ secrets.APPLE_TEAM_ID }}" ]; then
|
||||
# Use Apple ID authentication
|
||||
echo "Using Apple ID authentication..."
|
||||
UUID=$(xcrun notarytool submit "$DMG_FILE" \
|
||||
--apple-id "${{ secrets.APPLE_ID }}" \
|
||||
--password "${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}" \
|
||||
--team-id "${{ secrets.APPLE_TEAM_ID }}" \
|
||||
--wait | grep "id:" | awk '{print $2}')
|
||||
# Just ensure we have the correct path for outputs
|
||||
if [ -f "${{ steps.sign-and-notarize.outputs.package-path }}" ]; then
|
||||
echo "Using DMG created by the macos-notarize action"
|
||||
echo "DMG file location: ${{ steps.sign-and-notarize.outputs.package-path }}"
|
||||
echo "STAPLED_APP_DMG=${{ steps.sign-and-notarize.outputs.package-path }}" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "⚠️ No notarization credentials available. DMG will not be notarized."
|
||||
UUID=""
|
||||
echo "⚠️ DMG not found from the macos-notarize action output"
|
||||
fi
|
||||
|
||||
echo "Notarization UUID: $UUID"
|
||||
|
||||
# Check notarization status
|
||||
if [ -n "$UUID" ]; then
|
||||
# Use the same authentication method for UUID info
|
||||
if [ -n "${{ secrets.NOTARY_API_KEY_ID }}" ] && [ -n "${{ secrets.NOTARY_API_KEY_ISSUER_ID }}" ]; then
|
||||
xcrun notarytool info "$UUID" \
|
||||
--key "${{ secrets.NOTARY_API_KEY_PATH }}" \
|
||||
--key-id "${{ secrets.NOTARY_API_KEY_ID }}" \
|
||||
--issuer "${{ secrets.NOTARY_API_KEY_ISSUER_ID }}"
|
||||
elif [ -n "${{ secrets.APPLE_ID }}" ] && [ -n "${{ secrets.APPLE_TEAM_ID }}" ]; then
|
||||
xcrun notarytool info "$UUID" \
|
||||
--apple-id "${{ secrets.APPLE_ID }}" \
|
||||
--password "${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}" \
|
||||
--team-id "${{ secrets.APPLE_TEAM_ID }}"
|
||||
fi
|
||||
|
||||
# Staple the DMG
|
||||
echo "Stapling notarization ticket to DMG..."
|
||||
xcrun stapler staple "$DMG_FILE"
|
||||
|
||||
# Verify stapling
|
||||
echo "Verifying DMG stapling..."
|
||||
xcrun stapler validate "$DMG_FILE"
|
||||
else
|
||||
echo "⚠️ Notarization UUID not found. DMG may not be properly notarized."
|
||||
fi
|
||||
|
||||
echo "DMG file created at: $DMG_FILE"
|
||||
echo "STAPLED_APP_DMG=$DMG_FILE" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
|
||||
# Upload stapled app directly (this is the most reliable approach)
|
||||
@ -425,22 +345,32 @@ jobs:
|
||||
path: ${{ env.STAPLED_APP_PATH }}
|
||||
retention-days: 30
|
||||
|
||||
# Upload the ZIP archive (proper archiving that preserves stapling)
|
||||
# Create a properly archived ZIP of the stapled app (preserves stapling)
|
||||
- name: Create Stapled App Archive (ZIP)
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' && steps.sign-and-notarize.outputs.zip-package-path != ''
|
||||
run: |
|
||||
# The ZIP is now created by the macos-notarize action
|
||||
echo "Using ZIP created by the macos-notarize action"
|
||||
echo "ZIP file location: ${{ steps.sign-and-notarize.outputs.zip-package-path }}"
|
||||
echo "STAPLED_APP_ZIP=${{ steps.sign-and-notarize.outputs.zip-package-path }}" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
|
||||
# Upload the ZIP archive from the macos-notarize action
|
||||
- name: Upload Stapled App ZIP Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none'
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none' && steps.sign-and-notarize.outputs.zip-package-path != ''
|
||||
with:
|
||||
name: LuckyWorld-macOS-Stapled-ZIP
|
||||
path: ${{ env.STAPLED_APP_ZIP }}
|
||||
path: ${{ steps.sign-and-notarize.outputs.zip-package-path }}
|
||||
retention-days: 30
|
||||
|
||||
# Upload the DMG file
|
||||
# Upload the DMG file from the macos-notarize action
|
||||
- name: Upload Stapled App DMG
|
||||
uses: actions/upload-artifact@v3
|
||||
if: steps.sign-and-notarize.outputs.notarized == 'true' && steps.sign-and-notarize.outputs.signed != 'none'
|
||||
with:
|
||||
name: LuckyWorld-macOS-Stapled-DMG
|
||||
path: ${{ env.STAPLED_APP_DMG }}
|
||||
path: ${{ steps.sign-and-notarize.outputs.package-path }}
|
||||
retention-days: 30
|
||||
|
||||
# Upload signed app (might be DMG or other package format)
|
||||
|
Loading…
x
Reference in New Issue
Block a user