-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
177 lines (161 loc) · 6.3 KB
/
upload-to-testflight.yml
File metadata and controls
177 lines (161 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
name: Upload to TestFlight
# Upload a pre-built iOS IPA (artifact from build.yml) to TestFlight.
# Summary table uses workflow inputs only (no checkout / repo parsing in the summary job).
#
on:
workflow_call:
inputs:
environment:
description: 'Build environment / track (exp, beta, rc)'
required: true
type: string
testflight_group:
description: 'TestFlight external testing group'
required: false
type: string
default: 'MetaMask BETA & Release Candidates'
source_branch:
description: 'Original branch the user asked to build (e.g. main); from caller'
required: true
type: string
build_branch:
description: 'Branch that was built'
required: true
type: string
build_name:
description: 'Must match build.yml build_name (artifact ios-ipa-{build_name})'
required: true
type: string
build_commit_sha:
description: 'Built commit SHA; from build.yml built_commit_sha output'
required: true
type: string
build_version:
description: 'Semantic version at built commit; from build.yml semantic_version output (eg. 7.77.0)'
required: true
type: string
build_number:
description: 'The build number of the app (eg. 4134)'
required: true
type: string
distribute_external:
description: 'Whether to distribute to external testers. Set false for nightly/internal builds to avoid expiring previous TestFlight builds.'
required: false
type: boolean
default: true
runner_provider:
description: Runner provider forwarded from the caller
required: false
type: string
default: current
permissions:
contents: read
id-token: write
jobs:
testflight-upload-summary:
name: TestFlight upload summary
runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }}
steps:
- name: Display TestFlight upload summary
run: |
{
echo "### 📲 TestFlight Upload"
echo ""
echo "| Field | Value |"
echo "| --- | --- |"
echo "| **Source branch** | \`${{ inputs.source_branch }}\` |"
echo "| **Build branch** | \`${{ inputs.build_branch }}\` |"
echo "| **Build name** | \`${{ inputs.build_name }}\` |"
echo "| **Build commit SHA** | \`${{ inputs.build_commit_sha }}\` |"
echo "| **Build version** | \`${{ inputs.build_version }}\` |"
echo "| **Build number** | \`${{ inputs.build_number }}\` |"
echo "| **TestFlight group** | ${{ inputs.testflight_group }} |"
echo "| **Workflow branch ref** | \`${{ github.ref_name }}\` |"
} >> "$GITHUB_STEP_SUMMARY"
upload-ios-testflight:
name: Upload iOS to TestFlight
needs: [testflight-upload-summary]
runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ios-build' || 'ghcr.io/cirruslabs/macos-runner:tahoe-xl' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- 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 IPA 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: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_APPLE_TESTFLIGHT }}
aws-region: 'us-east-2'
- name: Fetch Apple API keys from AWS Secrets Manager
run: |
echo "🔐 Fetching App Store Connect API keys from Secrets Manager..."
secret_id="metamask-mobile-main-apple-api-keys"
secret_json=$(aws secretsmanager get-secret-value \
--region 'us-east-2' \
--secret-id "$secret_id" \
--query SecretString \
--output text)
for key in APP_STORE_CONNECT_API_KEY_ISSUER_ID APP_STORE_CONNECT_API_KEY_KEY_ID; do
value=$(echo "$secret_json" | jq -r --arg k "$key" '.[$k] // empty')
if [ -z "$value" ]; then
echo "::error::Missing key in secret: $key"
exit 1
fi
echo "::add-mask::$value"
echo "${key}=${value}" >> "$GITHUB_ENV"
done
key=APP_STORE_CONNECT_API_KEY_KEY_CONTENT
value=$(echo "$secret_json" | jq -r --arg k "$key" '.[$k] // empty')
if [ -z "$value" ]; then
echo "::error::Missing key in secret: $key"
exit 1
fi
while IFS= read -r line || [ -n "$line" ]; do
[ -n "$line" ] && echo "::add-mask::$line"
done <<< "$(printf '%s\n' "$value")"
delim="APPLEP8$(openssl rand -hex 16)"
{
printf '%s<<%s\n' "$key" "$delim"
printf '%s\n' "$value"
printf '%s\n' "$delim"
} >> "$GITHUB_ENV"
echo "✅ Apple API keys loaded from AWS"
- 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"
- name: Upload to TestFlight
run: |
bash scripts/upload-to-testflight.sh \
"github_actions_main-${{ inputs.environment }}" \
"${{ inputs.source_branch }}" \
"${{ steps.ipa.outputs.path }}" \
"${{ inputs.testflight_group }}" \
"${{ inputs.distribute_external }}"
- name: Cleanup API Key
if: always()
run: |
rm -f ios/AuthKey.p8
echo "🧹 Cleaned up API key file"