From d20a1a4813ad38cd86f23ee851c5cd991edd51f8 Mon Sep 17 00:00:00 2001 From: Tim Nunamaker Date: Fri, 15 Mar 2024 15:47:39 -0500 Subject: [PATCH] Notarize with API key --- .github/workflows/package.yml | 94 ++++++++++++++++------------------- scripts/package-macos-app.sh | 11 ++++ 2 files changed, 54 insertions(+), 51 deletions(-) mode change 100644 => 100755 scripts/package-macos-app.sh diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index d4c4199..295e7c4 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -101,72 +101,67 @@ jobs: - name: Set executable permissions run: chmod +x dist/selfie/selfie - - name: Package App - if: runner.os == 'macOS' - run: sh scripts/package-macos-app.sh - - - name: Sign the App + - name: Build macOS App if: runner.os == 'macOS' + env: + APPLE_ASC_API_KEY_KEY_BASE64: ${{ secrets.APPLE_ASC_API_KEY_KEY_BASE64 }} run: | - codesign --deep --force --verbose --options runtime --sign "Developer ID Application: Corsali, Inc (G7QNBSSW44)" "${{ github.workspace }}/dist/selfie/Selfie.app" + sh scripts/package-macos-app.sh # TODO: pass in CERT, etc. - - name: Create ZIP Archive for Notarization - if: runner.os == 'macOS' - run: | - ditto -c -k --keepParent dist/selfie selfie.zip + # Create a ZIP archive of the app bundle + ditto -c -k --keepParent "${{ github.workspace }}/dist/selfie/Selfie.app" "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip" - - name: Submit for Notarization - if: runner.os == 'macOS' - id: notarization_submit - run: | - set -x echo "Submitting app for notarization..." - NOTARIZATION_OUTPUT=$(xcrun altool --notarize-app --primary-bundle-id "com.vana.selfie" --username ${{ secrets.APPLE_ID }} --password ${{ secrets.APPLE_SELFIE_PASSWORD }} --file selfie.zip --output-format xml 2>&1) - echo "Notarization output start:" - echo "${NOTARIZATION_OUTPUT}" - echo "Notarization output end" - REQUEST_UUID=$(echo "${NOTARIZATION_OUTPUT}" | grep -oE 'RequestUUID>[^<]+' | sed 's/RequestUUID>//') + API_KEY_PATH=$RUNNER_TEMP/AuthKey_${{secrets.APPLE_ASC_API_KEY_ID}}.p8 + echo -n "$APPLE_ASC_API_KEY_KEY_BASE64" | base64 --decode > $API_KEY_PATH + + # Submit the ZIP archive for notarization + NOTARIZATION_OUTPUT=$(xcrun notarytool submit "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip" --issuer ${{ secrets.APPLE_ASC_API_KEY_ISSUER_UUID }} --key-id ${{ secrets.APPLE_ASC_API_KEY_ID }} --key $API_KEY_PATH --wait 2>&1) + + # Parse the REQUEST_UUID and notarization status from NOTARIZATION_OUTPUT + REQUEST_UUID=$(echo "${NOTARIZATION_OUTPUT}" | grep 'id:' | awk '{print $NF}') + NOTARIZATION_STATUS=$(echo "${NOTARIZATION_OUTPUT}" | grep 'status:' | awk '{print $NF}') + + # Check if REQUEST_UUID is empty if [[ -z "$REQUEST_UUID" ]]; then echo "Failed to submit app for notarization. Full output:" echo "${NOTARIZATION_OUTPUT}" - echo "Error: REQUEST_UUID is empty" exit 1 + else + echo "Notarization submitted; RequestUUID: ${REQUEST_UUID}" fi - echo "::set-output name=request_uuid::${REQUEST_UUID}" - echo "REQUEST_UUID=${REQUEST_UUID}" >> $GITHUB_ENV - echo "Notarization submitted; RequestUUID: ${REQUEST_UUID}" - - name: Poll for Notarization Status - if: runner.os == 'macOS' && env.REQUEST_UUID != '' - run: | - echo "Polling for notarization status..." - while : ; do - STATUS_OUTPUT=$(xcrun altool --notarization-info $REQUEST_UUID --username ${{ secrets.APPLE_ID }} --password ${{ secrets.APPLE_SELFIE_PASSWORD }} --output-format xml) - echo "${STATUS_OUTPUT}" - if echo "${STATUS_OUTPUT}" | grep -q 'Status: success'; then - echo "Notarization succeeded." - break - elif echo "${STATUS_OUTPUT}" | grep -q 'Status: in progress'; then - echo "Notarization still in progress, sleeping for 2 minutes..." - sleep 120 - else - echo "Notarization failed." - exit 1 - fi - done - - - name: Staple Notarization Ticket - if: runner.os == 'macOS' - run: | - echo "Stapling notarization ticket..." + # Handle notarization status + if [[ "$NOTARIZATION_STATUS" == "Invalid" ]]; then + echo "Notarization failed with status: ${NOTARIZATION_STATUS}" + echo "Fetching notarization log for RequestUUID: ${REQUEST_UUID}..." + xcrun notarytool log ${REQUEST_UUID} --key $API_KEY_PATH --key-id ${{ secrets.APPLE_ASC_API_KEY_ID }} --issuer ${{ secrets.APPLE_ASC_API_KEY_ISSUER_UUID }} + exit 1 + elif [[ "$NOTARIZATION_STATUS" != "Accepted" ]]; then + echo "Notarization failed with an unexpected status: ${NOTARIZATION_STATUS}" + echo "Full notarization output:" + echo "${NOTARIZATION_OUTPUT}" + exit 1 + else + echo "Notarization successful; status: ${NOTARIZATION_STATUS}" + fi + + # Staple the notarization ticket to the app bundle xcrun stapler staple "${{ github.workspace }}/dist/selfie/Selfie.app" + # Create the final ZIP archive of the notarized app bundle + ditto -c -k --keepParent "${{ github.workspace }}/dist/selfie/Selfie.app" "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip" + + - name: Build Non-macOS App + if: runner.os != 'macOS' + run: zip -r ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip dist/selfie + shell: bash - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }} - path: dist + path: ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip overwrite: true - name: Clean up keychain and provisioning profile @@ -174,6 +169,3 @@ jobs: run: | security delete-keychain $RUNNER_TEMP/github-actions.keychain-db rm ~/Library/MobileDevice/Provisioning\ Profiles/apple_provisioning_profile.provisionprofile - -# security delete-keychain $KEYCHAIN_PATH -# rm $PROVISIONING_PROFILE_PATH diff --git a/scripts/package-macos-app.sh b/scripts/package-macos-app.sh old mode 100644 new mode 100755 index 12ffbf3..78ba55f --- a/scripts/package-macos-app.sh +++ b/scripts/package-macos-app.sh @@ -44,3 +44,14 @@ cat < "${INFO_PLIST}" EOF echo "${APP_NAME}.app bundle has been created." + +# Developer ID +CERT="Developer ID Application: Corsali, Inc (G7QNBSSW44)" + +APP_CONTENTS="${APP_DIR}/Contents" + +# Find and sign all executables, dylibs, and .so files +find "$APP_CONTENTS" \( -type f -perm +111 -o -name "*.dylib" -o -name "*.so" \) -exec codesign --force --sign "$CERT" --timestamp --options runtime '{}' + + +# Sign the app bundle itself +codesign --deep --force --verbose --timestamp --options runtime --sign "$CERT" "${APP_DIR}"