diff --git a/.github/workflows/release-notarized.yml b/.github/workflows/release-notarized.yml index b6fab81..15b8a6b 100644 --- a/.github/workflows/release-notarized.yml +++ b/.github/workflows/release-notarized.yml @@ -1,10 +1,11 @@ name: Release macOS app (notarized) +run-name: notarized release ${{ inputs.tag }} on: workflow_dispatch: inputs: tag: - description: "Release tag (e.g. v0.4.4-beta)" + description: "Existing Git tag to release (e.g. v0.4.5)" required: true type: string @@ -14,38 +15,21 @@ permissions: jobs: release: runs-on: macos-latest + steps: - - name: Checkout (no external actions) + - name: Checkout tag env: TAG_NAME: ${{ inputs.tag }} REPO: ${{ github.repository }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + set -euo pipefail git init git remote add origin "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" git fetch --depth=1 origin "refs/tags/${TAG_NAME}" - git checkout -b "release-${TAG_NAME}" FETCH_HEAD - - name: Verify notarization secrets - env: - MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} - MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} - run: | - missing=0 - for key in MACOS_CERT_P12 MACOS_CERT_PASSWORD KEYCHAIN_PASSWORD APPLE_ID APPLE_TEAM_ID APPLE_APP_SPECIFIC_PASSWORD; do - if [ -z "${!key}" ]; then - echo "Missing required secret: $key" >&2 - missing=1 - fi - done - if [ "$missing" -ne 0 ]; then - exit 1 - fi + git checkout FETCH_HEAD - - name: Show Xcode Version + - name: Show Xcode version run: xcodebuild -version - name: Import signing certificate @@ -54,24 +38,22 @@ jobs: MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | - if [[ -z "${MACOS_CERT_P12}" ]]; then - echo "Missing MACOS_CERT_P12 secret" >&2 - exit 1 - fi - KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain" - echo "${MACOS_CERT_P12}" | base64 --decode > "$RUNNER_TEMP/cert.p12" - security create-keychain -p "${KEYCHAIN_PASSWORD}" "$KEYCHAIN_PATH" - security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" - security unlock-keychain -p "${KEYCHAIN_PASSWORD}" "$KEYCHAIN_PATH" - security import "$RUNNER_TEMP/cert.p12" -k "$KEYCHAIN_PATH" -P "${MACOS_CERT_PASSWORD}" -T /usr/bin/codesign - security list-keychains -d user -s "$KEYCHAIN_PATH" - security find-identity -p codesigning -v + set -euo pipefail + KEYCHAIN="$RUNNER_TEMP/build.keychain-db" - - name: Build macOS archive (signed) + echo "$MACOS_CERT_P12" | base64 --decode > cert.p12 + + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN" + security import cert.p12 -k "$KEYCHAIN" -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign + security list-keychains -d user -s "$KEYCHAIN" + + - name: Build archive env: - ARCHIVE_PATH: ${{ runner.temp }}/NeonVisionEditor.xcarchive TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + ARCHIVE_PATH: ${{ runner.temp }}/NeonVisionEditor.xcarchive run: | + set -euo pipefail xcodebuild \ -project "Neon Vision Editor.xcodeproj" \ -scheme "Neon Vision Editor" \ @@ -85,76 +67,75 @@ jobs: - name: Export app env: + TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} ARCHIVE_PATH: ${{ runner.temp }}/NeonVisionEditor.xcarchive EXPORT_PATH: ${{ runner.temp }}/export - TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: | + set -euo pipefail mkdir -p "$EXPORT_PATH" - cat > "$RUNNER_TEMP/exportOptions.plist" < export.plist < - - method - developer-id - signingStyle - manual - teamID - ${TEAM_ID} - signingCertificate - Developer ID Application + methoddeveloper-id + teamID${TEAM_ID} - PLIST + EOF + xcodebuild -exportArchive \ -archivePath "$ARCHIVE_PATH" \ -exportPath "$EXPORT_PATH" \ - -exportOptionsPlist "$RUNNER_TEMP/exportOptions.plist" + -exportOptionsPlist export.plist - - name: Notarize app + - name: Notarize env: EXPORT_PATH: ${{ runner.temp }}/export APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} run: | - APP_PATH="$EXPORT_PATH/Neon Vision Editor.app" - if [[ ! -d "$APP_PATH" ]]; then - echo "App not found at $APP_PATH" >&2 - exit 1 - fi - ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$RUNNER_TEMP/submit.zip" - xcrun notarytool submit "$RUNNER_TEMP/submit.zip" \ + set -euo pipefail + APP="$EXPORT_PATH/Neon Vision Editor.app" + + ditto -c -k --keepParent "$APP" submit.zip + + xcrun notarytool submit submit.zip \ --apple-id "$APPLE_ID" \ --team-id "$APPLE_TEAM_ID" \ --password "$APPLE_APP_SPECIFIC_PASSWORD" \ --wait - xcrun stapler staple "$APP_PATH" - - name: Zip app (stapled) + xcrun stapler staple "$APP" + + - name: Zip notarized app env: EXPORT_PATH: ${{ runner.temp }}/export run: | - APP_PATH="$EXPORT_PATH/Neon Vision Editor.app" - ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "Neon.Vision.Editor.app.zip" - - - name: Extract changelog section - env: - TAG_NAME: ${{ inputs.tag }} - run: | - ./scripts/extract_changelog_section.sh CHANGELOG.md "$TAG_NAME" > release-notes.md + set -euo pipefail + ditto -c -k --keepParent "$EXPORT_PATH/Neon Vision Editor.app" Neon.Vision.Editor.app.zip - name: Create or Update GitHub Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG_NAME: ${{ inputs.tag }} run: | + set -euo pipefail + if gh release view "$TAG_NAME" >/dev/null 2>&1; then - gh release upload "$TAG_NAME" "Neon.Vision.Editor.app.zip" --clobber - gh release edit "$TAG_NAME" --title "Neon Vision Editor $TAG_NAME" --notes-file release-notes.md + gh release upload "$TAG_NAME" Neon.Vision.Editor.app.zip --clobber else - gh release create "$TAG_NAME" \ - --title "Neon Vision Editor $TAG_NAME" \ - --notes-file release-notes.md \ - "Neon.Vision.Editor.app.zip" - fi \ No newline at end of file + gh release create "$TAG_NAME" Neon.Vision.Editor.app.zip \ + --title "Neon Vision Editor $TAG_NAME" + fi + + - name: Trigger homebrew-tap update + env: + GH_TOKEN: ${{ secrets.TAP_BOT_TOKEN }} + TAG_NAME: ${{ inputs.tag }} + run: | + set -euo pipefail + gh api repos/h3pdesign/homebrew-tap/dispatches \ + -f event_type=notarized_release \ + -f client_payload[tag]="$TAG_NAME"