Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 9 additions & 83 deletions .github/workflows/runway-ota-build-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,88 +202,14 @@ jobs:
checkout_ref: ${{ inputs.source_branch || github.ref_name }}
secrets: inherit

testflight-upload-summary:
name: TestFlight upload summary
needs: [trigger-build]
if: ${{ inputs.platform == 'ios' && inputs.upload_testflight }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.source_branch || github.ref }}
- name: Display TestFlight upload summary
run: |
BUILD_VERSION=$(node -p "require('./package.json').version")
{
echo "### 📲 TestFlight Upload (${{ inputs.ios_testflight_summary_title }})"
echo ""
echo "| Field | Value |"
echo "| --- | --- |"
echo "| **Ref** | ${{ inputs.source_branch || github.ref_name }} |"
echo "| **Build name** | ${{ inputs.build_name }} |"
echo "| **Build version** | ${BUILD_VERSION} |"
echo "| **TestFlight group** | MetaMask BETA & Release Candidates |"
} >> "$GITHUB_STEP_SUMMARY"

upload-ios-testflight:
upload-to-testflight:
name: Upload iOS to TestFlight
needs: [trigger-build, testflight-upload-summary]
needs: [trigger-build]
if: ${{ inputs.platform == 'ios' && inputs.upload_testflight }}
runs-on: ghcr.io/cirruslabs/macos-runner:sequoia-xl
environment: apple
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.source_branch || github.ref }}

- name: Setup Ruby (iOS)
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb #v1
with:
ruby-version: '3.2.9'
working-directory: ios
bundler-cache: true

- name: Download iOS build artifact
uses: actions/download-artifact@v4
with:
name: ios-ipa-${{ inputs.build_name }}

- name: Find IPA path
id: ipa
run: |
IPA=$(find . -name '*.ipa' -type f | head -1)
if [ -z "$IPA" ]; then
echo "::error::No .ipa file found in artifact"
exit 1
fi
case "$IPA" in /*) ABS="$IPA" ;; *) ABS="$PWD/$IPA" ;; esac
echo "path=$ABS" >> "$GITHUB_OUTPUT"

- name: Setup App Store Connect API Key
run: |
bash scripts/setup-app-store-connect-api-key.sh \
"$APP_STORE_CONNECT_API_KEY_ISSUER_ID" \
"$APP_STORE_CONNECT_API_KEY_KEY_ID" \
"$APP_STORE_CONNECT_API_KEY_KEY_CONTENT"
env:
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
APP_STORE_CONNECT_API_KEY_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_CONTENT }}

- name: Upload to TestFlight
run: |
bash scripts/upload-to-testflight.sh \
"github_actions_${{ inputs.build_name }}" \
"${{ inputs.source_branch || github.ref_name }}" \
"${{ steps.ipa.outputs.path }}" \
"" \
"false"

- name: Cleanup API Key
if: always()
run: |
rm -f ios/AuthKey.p8
echo "🧹 Cleaned up API key file"
uses: ./.github/workflows/upload-to-testflight.yml
with:
skip_build: true
build_name: ${{ inputs.build_name }}
source_branch: ${{ inputs.source_branch || github.ref_name }}
summary_title: ${{ inputs.ios_testflight_summary_title }}
secrets: inherit
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing distribute_external: false flips distribution behavior

High Severity

The old inline job explicitly passed "false" for distribute_external when calling upload-to-testflight.sh. The new reusable workflow call omits the distribute_external input, which defaults to true in upload-to-testflight.yml. This silently changes behavior from "upload only" to "distribute to external testers" for iOS RC and Production Runway builds. The workflow input description itself notes that false "avoids App Manager role requirement," so this change may also cause permission failures.

Additional Locations (1)
Fix in Cursor Fix in Web

60 changes: 50 additions & 10 deletions .github/workflows/upload-to-testflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: Upload to TestFlight
# Dedicated workflow to build iOS (via build.yml) and upload to TestFlight.
# All TestFlight logic lives here; build.yml only builds and uploads artifacts.
#
# When skip_build is true, the caller must ensure the IPA artifact
# (named ios-ipa-{build_name}) already exists in the same workflow run.
#
on:
workflow_call:
inputs:
Expand All @@ -11,14 +14,35 @@ on:
required: true
type: string
environment:
description: 'Build environment / track (exp, beta, rc)'
required: true
description: 'Build environment / track (exp, beta, rc). Used to derive build_name when build_name is empty.'
required: false
type: string
default: 'rc'
testflight_group:
description: 'TestFlight external testing group'
required: false
type: string
default: 'MetaMask BETA & Release Candidates'
skip_build:
description: 'Skip branch creation and build (IPA artifact must already exist in this workflow run)'
required: false
type: boolean
default: false
build_name:
description: 'Override build/artifact name (default: main-{environment})'
required: false
type: string
default: ''
summary_title:
description: 'TestFlight upload summary heading'
required: false
type: string
default: 'TestFlight Upload'
distribute_external:
description: 'Whether to distribute the build to external testers (false = upload only, avoids App Manager role requirement)'
required: false
type: boolean
default: true
workflow_dispatch:
inputs:
source_branch:
Expand All @@ -44,6 +68,11 @@ on:
- 'MetaMask BETA & Release Candidates'
- 'MM Card Team'
- 'Ramp Provider Testing'
distribute_external:
description: 'Distribute to external testers (false = upload only)'
required: true
type: boolean
default: true

# contents: write required by build.yml update-build-version job (version bump)
permissions:
Expand All @@ -54,13 +83,15 @@ jobs:
# Create a temporary branch so the version-bump commit can be pushed without
# hitting branch-protection rules on the source branch (e.g. main).
prepare-build-branch:
if: ${{ !inputs.skip_build }}
uses: ./.github/workflows/create-build-branch.yml
with:
source_branch: ${{ inputs.source_branch }}
secrets: inherit

build:
name: Build iOS (${{ inputs.environment || 'rc' }})
if: ${{ !inputs.skip_build }}
needs: [prepare-build-branch]
uses: ./.github/workflows/build.yml
with:
Expand All @@ -73,24 +104,29 @@ jobs:
testflight-upload-summary:
name: TestFlight upload summary
needs: [build, prepare-build-branch]
if: ${{ always() && !failure() && !cancelled() }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ needs.prepare-build-branch.outputs.build_branch }}
ref: ${{ needs.prepare-build-branch.outputs.build_branch || inputs.source_branch }}
- name: Display TestFlight upload summary
env:
EFFECTIVE_BUILD_NAME: ${{ inputs.build_name || format('main-{0}', inputs.environment || 'rc') }}
run: |
BUILD_VERSION=$(node -p "require('./package.json').version")
BUILD_NUMBER=$(awk '/versionCode/{print $2}' android/app/build.gradle)
{
echo "### 📲 TestFlight Upload"
echo "### 📲 ${{ inputs.summary_title || 'TestFlight Upload' }}"
echo ""
echo "| Field | Value |"
echo "| --- | --- |"
echo "| **Source branch** | \`${{ inputs.source_branch }}\` |"
echo "| **Build branch** | \`${{ needs.prepare-build-branch.outputs.build_branch }}\` |"
echo "| **Build name** | \`main-${{ inputs.environment || 'rc' }}\` |"
if [ -n "${{ needs.prepare-build-branch.outputs.build_branch }}" ]; then
echo "| **Build branch** | \`${{ needs.prepare-build-branch.outputs.build_branch }}\` |"
fi
echo "| **Build name** | \`${EFFECTIVE_BUILD_NAME}\` |"
echo "| **Build version** | \`${BUILD_VERSION}\` |"
echo "| **Build number** | \`${BUILD_NUMBER}\` |"
echo "| **TestFlight group** | ${{ inputs.testflight_group || 'MetaMask BETA & Release Candidates' }} |"
Expand All @@ -102,6 +138,7 @@ jobs:
upload-ios-testflight:
name: Upload iOS to TestFlight
needs: [build, testflight-upload-summary]
if: ${{ always() && needs.testflight-upload-summary.result == 'success' }}
runs-on: ghcr.io/cirruslabs/macos-runner:sequoia-xl
steps:
- name: Checkout repository
Expand All @@ -119,7 +156,7 @@ jobs:
- name: Download iOS IPA artifact
uses: actions/download-artifact@v4
with:
name: ios-ipa-main-${{ inputs.environment || 'rc' }}
name: ios-ipa-${{ inputs.build_name || format('main-{0}', inputs.environment || 'rc') }}

- name: Find IPA path
id: ipa
Expand Down Expand Up @@ -185,12 +222,15 @@ jobs:
"$APP_STORE_CONNECT_API_KEY_KEY_CONTENT"

- name: Upload to TestFlight
env:
EFFECTIVE_BUILD_NAME: ${{ inputs.build_name || format('main-{0}', inputs.environment || 'rc') }}
run: |
bash scripts/upload-to-testflight.sh \
"github_actions_main-${{ inputs.environment || 'rc' }}" \
"github_actions_${EFFECTIVE_BUILD_NAME}" \
"${{ inputs.source_branch }}" \
"${{ steps.ipa.outputs.path }}" \
"${{ inputs.testflight_group || 'MetaMask BETA & Release Candidates' }}"
"${{ inputs.testflight_group || 'MetaMask BETA & Release Candidates' }}" \
"${{ inputs.distribute_external }}"

- name: Cleanup API Key
if: always()
Expand All @@ -201,7 +241,7 @@ jobs:
cleanup-build-branch:
name: Cleanup build branch
needs: [prepare-build-branch, upload-ios-testflight]
if: always()
if: ${{ always() && !inputs.skip_build }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
Loading