-
Notifications
You must be signed in to change notification settings - Fork 221
177 lines (159 loc) · 6.33 KB
/
ios-e2e.yml
File metadata and controls
177 lines (159 loc) · 6.33 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
# =============================================================================
# iOS E2E - integration tests (pre-publish)
# =============================================================================
#
# Stage: RC-E2E in the RC release pipeline.
#
# Runs the .af-e2e/test-plan.json scenarios against the plugin source
# (example linked to the plugin via path). Drives
# the unified scripts/af-scenario-runner.sh on an iOS simulator.
#
# Triggers:
# - workflow_call from release.yml (the gate before publish-to-npm)
# - workflow_dispatch for manual reruns and ad-hoc validation
# - Weekly cron (Sunday 02:00 UTC) to catch SDK / RN drift
#
# Reports land in .af-e2e/reports/ and are uploaded as ios-e2e-<run> artifacts.
# =============================================================================
name: iOS E2E
on:
workflow_call:
inputs:
ref:
description: 'Branch, tag, or SHA to check out. Defaults to the calling workflow''s ref.'
required: false
type: string
default: ''
workflow_dispatch:
inputs:
ref:
description: 'Branch, tag, or SHA to check out (default: workflow ref)'
required: false
type: string
default: ''
schedule:
- cron: '0 2 * * 0'
concurrency:
group: e2e-ios-${{ github.ref }}
cancel-in-progress: true
jobs:
e2e-ios:
name: E2E Tests (iOS)
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ inputs.ref != '' && inputs.ref || github.ref }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Select Xcode version
run: |
XCODE=$(ls /Applications | grep -E "^Xcode_[0-9]" | sort -V | tail -1)
sudo xcode-select -s "/Applications/$XCODE"
xcodebuild -version
- name: Boot iOS simulator (newest iOS runtime)
run: |
# Pick a plain iPhone (15/16/17) from the newest available iOS 17/18
# runtime. macos-15 ships iOS 18.x simulators; we filter to iOS 17/18
# for deep-link phases. iOS 17.4+ and iOS 18.x deliver URLs straight
# to application:openURL:options: without a confirmation prompt.
DEVICES_JSON=$(xcrun simctl list -j devices available)
UDID=$(echo "$DEVICES_JSON" | jq -r '
.devices
| to_entries
| map(select(.key | test("iOS-1[78]")))
| sort_by(.key) | reverse
| map(
. as $rt
| $rt.value
| map(select(.name | test("^iPhone 1[5-7]$")))
| first
| (if . then {udid, runtime: $rt.key, name} else empty end)
)
| first // empty
| .udid // empty
')
if [[ -z "$UDID" ]]; then
echo "No iPhone 15/16/17 on iOS 17/18 found; falling back to first available iPhone."
UDID=$(echo "$DEVICES_JSON" | jq -r '.devices[][] | select(.name | test("^iPhone")) | .udid' | head -1)
fi
[[ -z "$UDID" ]] && { echo "::error::No iOS simulator available"; exit 1; }
echo "Selected simulator UDID: $UDID"
echo "$DEVICES_JSON" | jq -r --arg u "$UDID" '
.devices | to_entries[] | . as $rt
| $rt.value[] | select(.udid == $u)
| "Runtime: \($rt.key) Device: \(.name)"
'
xcrun simctl boot "$UDID"
xcrun simctl bootstatus "$UDID" -b
echo "IOS_SIMULATOR_UDID=$UDID" >> "$GITHUB_ENV"
- name: Cache CocoaPods
uses: actions/cache@v5
with:
path: example/ios/Pods
key: pods-${{ hashFiles('example/ios/Podfile', 'react-native-appsflyer.podspec') }}
restore-keys: pods-
- name: Install example app dependencies
working-directory: example
run: npm install
- name: Install CocoaPods
working-directory: example/ios
run: pod install
- name: Write example app .env
env:
ENV_FILE: ${{ secrets.ENV_FILE }}
run: |
echo "$ENV_FILE" | base64 -d > example/.env
echo "::group::.env keys (values redacted)"
sed 's/=.*/=***/' example/.env
echo "::endgroup::"
- name: Cache iOS build output
uses: actions/cache@v5
with:
path: example/ios/build
key: ios-build-${{ hashFiles('ios/**', 'index.js', 'example/ios/**', 'example/.env') }}
restore-keys: ios-build-
- name: Build iOS simulator app (debug)
working-directory: example/ios
env:
FORCE_BUNDLING: "1"
run: |
xcodebuild build \
-workspace example.xcworkspace \
-scheme example \
-configuration Debug \
-destination "platform=iOS Simulator,id=$IOS_SIMULATOR_UDID" \
-derivedDataPath build \
| xcpretty
- name: Run E2E (af-scenario-runner against .af-e2e/test-plan.json)
run: ./scripts/af-scenario-runner.sh --platform ios --plan .af-e2e/test-plan.json
- name: Dump iOS QA log file (debug)
if: always()
run: |
SIM_DATA="$HOME/Library/Developer/CoreSimulator/Devices/$IOS_SIMULATOR_UDID/data"
LOG=$(find "$SIM_DATA/Containers/Data/Application" -name "af_qa_logs.txt" 2>/dev/null | head -1)
echo "=== QA log: ${LOG:-not found} ==="
cat "$LOG" 2>/dev/null | head -200 || echo "(empty)"
- name: Dump simulator state and deep-link events (debug)
if: failure()
run: |
echo "=== Booted simulators ==="
xcrun simctl list devices booted || true
echo "=== Installed apps for $IOS_SIMULATOR_UDID ==="
xcrun simctl listapps "$IOS_SIMULATOR_UDID" 2>/dev/null \
| grep -E "com.appsflyer|CFBundleURLSchemes|example" || true
echo "=== Last 90s of simctl URL/launchservices events ==="
xcrun simctl spawn "$IOS_SIMULATOR_UDID" log show \
--last 90s --style compact 2>/dev/null \
| grep -E "Opening URL|openURL|launchservices|com.appsflyer|FrontBoard:Process" \
| tail -200 || true
- name: Upload E2E reports
if: always()
uses: actions/upload-artifact@v5
with:
name: ios-e2e-${{ github.run_number }}
path: .af-e2e/reports/
retention-days: 30