From 9b83511563fa5b40168c990ca3ba38ff417974dd Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Date: Sun, 5 Apr 2026 16:42:39 -0300 Subject: [PATCH 1/2] Use EAS workflows intead --- .eas/workflows/build-release.yml | 118 +++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .eas/workflows/build-release.yml diff --git a/.eas/workflows/build-release.yml b/.eas/workflows/build-release.yml new file mode 100644 index 00000000..5f84bfe8 --- /dev/null +++ b/.eas/workflows/build-release.yml @@ -0,0 +1,118 @@ +name: Build and notarize Orbit + +on: + push: + tags: ["expo-orbit-v*"] + pull_request: + paths: [".eas/workflows/build-release.yml"] + +jobs: + build_and_notarize: + runs_on: macos-large + env: + KEYCHAIN_NAME: orbit-keychain + KEYCHAIN_PASSWORD: orbit-keychain-password + steps: + - uses: eas/checkout + - uses: eas/install_node_modules + + - name: Build packages + working_directory: ./ + run: yarn build + + - name: Configure macOS credentials + working_directory: ./apps/menu-bar + run: | + # Download Apple Developer ID intermediate certificate + curl -o DeveloperIDG2CA.cer https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer + + # Write distribution certificate from environment variable + echo "$ORBIT_DIST_CERT_BASE64" | base64 --decode > dist_cert.p12 + + # Create a new keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" + + # Add new keychain to search list + EXISTING=$(security list-keychains | tr -d '"' | tr '\n' ' ') + security list-keychains -s "$KEYCHAIN_NAME" $EXISTING + + # Import Apple Developer ID intermediate certificate + security import DeveloperIDG2CA.cer -k "$KEYCHAIN_NAME" -T /usr/bin/codesign + + # Import the distribution certificate + if [ -n "$ORBIT_DIST_CERT_PASSWORD" ]; then + security import dist_cert.p12 -P "$ORBIT_DIST_CERT_PASSWORD" -k "$KEYCHAIN_NAME" -T /usr/bin/codesign + else + security import dist_cert.p12 -k "$KEYCHAIN_NAME" -T /usr/bin/codesign + fi + + # Set partition list to avoid interactive prompts + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" + + # Set default keychain and unlock + security default-keychain -s "$KEYCHAIN_NAME" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" + security set-keychain-settings "$KEYCHAIN_NAME" + + # Verify identity is available + echo "Available identities:" + security find-identity -v + + # Install provisioning profile + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles/ + echo "$ORBIT_PROVISIONPROFILE_BASE64" | base64 --decode > "${ORBIT_PROVISIONPROFILE_UUID}.provisionprofile" + cp "${ORBIT_PROVISIONPROFILE_UUID}.provisionprofile" ~/Library/MobileDevice/Provisioning\ Profiles/ + echo "Provisioning profile installed." + + - name: Archive CLI + working_directory: ./apps/cli + run: yarn archive + + - name: Codesign CLI + working_directory: ./apps/cli + run: yarn codesign + + - name: Install menu-bar pods + working_directory: ./apps/menu-bar/macos + run: pod install + + - name: Archive menu-bar + working_directory: ./apps/menu-bar + run: yarn archive + + - name: Export archive menu-bar + working_directory: ./apps/menu-bar + run: yarn export-local-archive + + - name: Verify signatures + working_directory: ./apps/menu-bar + run: | + echo "=== Verify app signature ===" + codesign --verify --deep --strict -vvv build/Release/Expo\ Orbit.app + echo "=== Main binary ===" + codesign -dvv build/Release/Expo\ Orbit.app/Contents/MacOS/Expo\ Orbit + echo "=== Sparkle ===" + codesign -dvv build/Release/Expo\ Orbit.app/Contents/Frameworks/Sparkle.framework + echo "=== Hermes ===" + codesign -dvv build/Release/Expo\ Orbit.app/Contents/Frameworks/hermes.framework + + - name: Zip menu-bar export + working_directory: ./apps/menu-bar + run: | + VERSION=$(node -p "require('./package.json').version") + ZIP_NAME="expo-orbit.v${VERSION}-macos.zip" + ditto -c -k --keepParent build/Release/Expo\ Orbit.app "build/Release/${ZIP_NAME}" + echo "Created ${ZIP_NAME}" + + - name: Notarize menu-bar + working_directory: ./apps/menu-bar + run: | + VERSION=$(node -p "require('./package.json').version") + ZIP_NAME="expo-orbit.v${VERSION}-macos.zip" + xcrun notarytool submit "build/Release/${ZIP_NAME}" --apple-id "$APPLE_ID_NOTARIZATION_EMAIL" --password "$APPLE_ID_NOTARIZATION_PASSWORD" --team-id "C8D8QTF339" --wait 2>&1 | tee notarize_output.txt + SUBMISSION_ID=$(grep "id:" notarize_output.txt | head -1 | awk '{print $2}') + if grep -q "status: Invalid" notarize_output.txt; then + echo "Notarization failed. Fetching log..." + xcrun notarytool log "$SUBMISSION_ID" --apple-id "$APPLE_ID_NOTARIZATION_EMAIL" --password "$APPLE_ID_NOTARIZATION_PASSWORD" --team-id "C8D8QTF339" + exit 1 + fi From 71f7f3ebc293d2b58fc6a5f708486228ff2121b5 Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Date: Sun, 5 Apr 2026 16:46:26 -0300 Subject: [PATCH 2/2] Add changelog entry --- .eas/workflows/build-release.yml | 29 ++++++++- CHANGELOG.md | 2 + .../Assets/{orbit 2.png => main-icon.png} | Bin .../ExpoMenuBar-macOS/AppIcon.icon/icon.json | 56 ++++++++---------- ...Frame 1430102100 (1).svg => main-icon.svg} | 0 .../AppIconDebug.icon/icon.json | 49 +++++++-------- 6 files changed, 74 insertions(+), 62 deletions(-) rename apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/Assets/{orbit 2.png => main-icon.png} (100%) rename apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/Assets/{Frame 1430102100 (1).svg => main-icon.svg} (100%) diff --git a/.eas/workflows/build-release.yml b/.eas/workflows/build-release.yml index 5f84bfe8..c19b587e 100644 --- a/.eas/workflows/build-release.yml +++ b/.eas/workflows/build-release.yml @@ -1,14 +1,19 @@ name: Build and notarize Orbit +defaults: + tools: + node: 20 + on: push: - tags: ["expo-orbit-v*"] + tags: ['expo-orbit-v*'] pull_request: - paths: [".eas/workflows/build-release.yml"] + paths: ['.eas/workflows/build-release.yml'] jobs: build_and_notarize: runs_on: macos-large + image: macos-sequoia-15.6-xcode-16.4 env: KEYCHAIN_NAME: orbit-keychain KEYCHAIN_PASSWORD: orbit-keychain-password @@ -78,7 +83,14 @@ jobs: - name: Archive menu-bar working_directory: ./apps/menu-bar - run: yarn archive + run: | + yarn update-cli && xcodebuild archive \ + -workspace macos/ExpoMenuBar.xcworkspace \ + -scheme ExpoMenuBar-macOS \ + -destination 'generic/platform=macOS,name=Any Mac' \ + -archivePath build/ExpoOrbit.xcarchive \ + ASSETCATALOG_COMPILER_SKIP_APP_STORE_DEPLOYMENT=YES \ + ASSETCATALOG_COMPILER_OPTIMIZATION=nothing - name: Export archive menu-bar working_directory: ./apps/menu-bar @@ -97,11 +109,13 @@ jobs: codesign -dvv build/Release/Expo\ Orbit.app/Contents/Frameworks/hermes.framework - name: Zip menu-bar export + id: zip working_directory: ./apps/menu-bar run: | VERSION=$(node -p "require('./package.json').version") ZIP_NAME="expo-orbit.v${VERSION}-macos.zip" ditto -c -k --keepParent build/Release/Expo\ Orbit.app "build/Release/${ZIP_NAME}" + set-output zip_path "build/Release/${ZIP_NAME}" echo "Created ${ZIP_NAME}" - name: Notarize menu-bar @@ -116,3 +130,12 @@ jobs: xcrun notarytool log "$SUBMISSION_ID" --apple-id "$APPLE_ID_NOTARIZATION_EMAIL" --password "$APPLE_ID_NOTARIZATION_PASSWORD" --team-id "C8D8QTF339" exit 1 fi + + - name: Upload to GitHub Release + working_directory: ./apps/menu-bar + run: | + VERSION=$(node -p "require('./package.json').version") + TAG="expo-orbit-v${VERSION}" + ZIP_NAME="expo-orbit.v${VERSION}-macos.zip" + echo "Uploading ${ZIP_NAME} to GitHub Release ${TAG}..." + gh release upload "$TAG" "build/Release/${ZIP_NAME}" --clobber || echo "No GitHub Release found for ${TAG}, skipping upload." diff --git a/CHANGELOG.md b/CHANGELOG.md index 440c3640..98bf292a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - Use EAS custom builds for macOS releases. ([#330](https://github.com/expo/orbit/pull/330) by [@gabrieldonadel](https://github.com/gabrieldonadel)) +- Migrate EAS custom builds to EAS Workflows. ([#234](https://github.com/expo/orbit/pull/234) by [@gabrieldonadel](https://github.com/gabrieldonadel)) + ## 2.5.0 — 2026-04-02 ### 🎉 New features diff --git a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/Assets/orbit 2.png b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/Assets/main-icon.png similarity index 100% rename from apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/Assets/orbit 2.png rename to apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/Assets/main-icon.png diff --git a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/icon.json b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/icon.json index c32c48dc..6be3e1b0 100644 --- a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/icon.json +++ b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIcon.icon/icon.json @@ -1,44 +1,36 @@ { - "fill" : { - "linear-gradient" : [ - "gray:0.12685,1.00000", - "display-p3:0.60000,0.60000,0.60000,1.00000" - ] + "fill": { + "linear-gradient": ["gray:0.12685,1.00000", "display-p3:0.60000,0.60000,0.60000,1.00000"] }, - "groups" : [ + "groups": [ { - "blur-material" : null, - "layers" : [ + "blur-material": null, + "layers": [ { - "glass" : false, - "hidden" : false, - "image-name" : "orbit 2.png", - "name" : "orbit 2", - "position" : { - "scale" : 0.82, - "translation-in-points" : [ - 14, - 0 - ] + "glass": false, + "hidden": false, + "image-name": "main-icon.png", + "name": "main-icon", + "position": { + "scale": 0.82, + "translation-in-points": [14, 0] } } ], - "lighting" : "individual", - "shadow" : { - "kind" : "neutral", - "opacity" : 0.5 + "lighting": "individual", + "shadow": { + "kind": "neutral", + "opacity": 0.5 }, - "specular" : true, - "translucency" : { - "enabled" : true, - "value" : 0.5 + "specular": true, + "translucency": { + "enabled": true, + "value": 0.5 } } ], - "supported-platforms" : { - "circles" : [ - "watchOS" - ], - "squares" : "shared" + "supported-platforms": { + "circles": ["watchOS"], + "squares": "shared" } -} \ No newline at end of file +} diff --git a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/Assets/Frame 1430102100 (1).svg b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/Assets/main-icon.svg similarity index 100% rename from apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/Assets/Frame 1430102100 (1).svg rename to apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/Assets/main-icon.svg diff --git a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/icon.json b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/icon.json index 071492d7..22b84cd2 100644 --- a/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/icon.json +++ b/apps/menu-bar/macos/ExpoMenuBar-macOS/AppIconDebug.icon/icon.json @@ -1,42 +1,37 @@ { - "fill" : { - "linear-gradient" : [ + "fill": { + "linear-gradient": [ "display-p3:0.11187,0.16816,0.55448,1.00000", "display-p3:0.68792,0.36090,0.70794,1.00000" ] }, - "groups" : [ + "groups": [ { - "hidden" : false, - "layers" : [ + "hidden": false, + "layers": [ { - "hidden" : false, - "image-name" : "Frame 1430102100 (1).svg", - "name" : "Frame 1430102100 (1)", - "position" : { - "scale" : 7.17, - "translation-in-points" : [ - 17, - 25 - ] + "hidden": false, + "image-name": "main-icon.svg", + "name": "main-icon", + "position": { + "scale": 7.17, + "translation-in-points": [17, 25] } } ], - "shadow" : { - "kind" : "neutral", - "opacity" : 0.5 + "shadow": { + "kind": "neutral", + "opacity": 0.5 }, - "specular" : false, - "translucency" : { - "enabled" : true, - "value" : 0.5 + "specular": false, + "translucency": { + "enabled": true, + "value": 0.5 } } ], - "supported-platforms" : { - "circles" : [ - "watchOS" - ], - "squares" : "shared" + "supported-platforms": { + "circles": ["watchOS"], + "squares": "shared" } -} \ No newline at end of file +}