xref: /expo/.github/workflows/updates-e2e.yml (revision 732ac684)
1name: Updates e2e
2
3on:
4  workflow_dispatch: {}
5  pull_request:
6    paths:
7      - .github/workflows/updates-e2e.yml
8      - packages/expo-json-utils/**
9      - packages/expo-manifests/**
10      - packages/expo-modules-core/**
11      - packages/expo-structured-headers/**
12      - packages/expo-updates-interface/**
13      - packages/expo-updates/**
14      - packages/expo/android/**
15      - packages/expo/ios/**
16      - templates/expo-template-bare-minimum/**
17  push:
18    branches: [main, 'sdk-*']
19    paths:
20      - .github/workflows/updates-e2e.yml
21      - packages/expo-json-utils/**
22      - packages/expo-manifests/**
23      - packages/expo-modules-core/**
24      - packages/expo-structured-headers/**
25      - packages/expo-updates-interface/**
26      - packages/expo-updates/**
27      - packages/expo/android/**
28      - packages/expo/ios/**
29      - templates/expo-template-bare-minimum/**
30
31concurrency:
32  group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
33  cancel-in-progress: true
34
35jobs:
36  android:
37    runs-on: macos-11
38    timeout-minutes: 60
39    env:
40      UPDATES_HOST: 10.0.2.2 # special IP that Android emulators map to host machine's localhost
41      UPDATES_PORT: 4747
42    strategy:
43      matrix:
44        api-level: [31]
45    steps:
46      - name: �� Checkout
47        uses: actions/checkout@v3
48      - name: ⬢ Setup Node
49        uses: actions/setup-node@v3
50        with:
51          node-version: '14.17'
52      - name: �� Use JDK 11
53        uses: actions/setup-java@v3
54        with:
55          distribution: 'temurin'
56          java-version: '11'
57      - name: ➕ Add `bin` to GITHUB_PATH
58        run: echo "$(yarn global bin)" >> $GITHUB_PATH
59      - name: ♻️ Restore caches
60        uses: ./.github/actions/expo-caches
61        id: expo-caches
62        with:
63          yarn-workspace: 'true'
64          avd: 'true'
65          avd-api: ${{ matrix.api-level }}
66      - name: �� Yarn install
67        if: steps.expo-caches.outputs.yarn-workspace-hit != 'true'
68        run: yarn install --frozen-lockfile
69      - name: Build expo-updates CLI
70        working-directory: packages/expo-updates
71        run: yarn build:cli
72      - name: �� Install Expo CLI
73        run: yarn global add expo-cli
74      - name: Init new expo app
75        working-directory: ../
76        run: expo-cli init updates-e2e --yes
77      - name: Add yarn resolutions for local dependencies
78        working-directory: ../updates-e2e
79        run: |
80          # A jq filter to add a "resolutions" field
81          JQ_FILTER=$(cat << EOF
82            . + {
83              resolutions: {
84                "expo-application": "file:../expo/packages/expo-application",
85                "expo-constants": "file:../expo/packages/expo-constants",
86                "expo-eas-client": "file:../expo/packages/expo-eas-client",
87                "expo-error-recovery": "file:../expo/packages/expo-error-recovery",
88                "expo-file-system": "file:../expo/packages/expo-file-system",
89                "expo-font": "file:../expo/packages/expo-font",
90                "expo-json-utils": "file:../expo/packages/expo-json-utils",
91                "expo-keep-awake": "file:../expo/packages/expo-keep-awake",
92                "expo-manifests": "file:../expo/packages/expo-manifests",
93                "expo-modules-core": "file:../expo/packages/expo-modules-core",
94                "expo-structured-headers": "file:../expo/packages/expo-structured-headers",
95                "expo-updates-interface": "file:../expo/packages/expo-updates-interface"
96              }
97            }
98          EOF
99          )
100          jq "$JQ_FILTER" < package.json > new-package.json
101          mv new-package.json package.json
102      - name: Add local expo packages
103        working-directory: ../updates-e2e
104        run: yarn add file:../expo/packages/expo-updates file:../expo/packages/expo file:../expo/packages/expo-splash-screen file:../expo/packages/expo-status-bar
105      - name: Setup app.config.json
106        working-directory: ../updates-e2e
107        run: echo "{\"name\":\"updates-e2e\",\"runtimeVersion\":\"1.0.0\",\"plugins\":[\"expo-updates\"],\"android\":{\"package\":\"dev.expo.updatese2e\"},\"ios\":{\"bundleIdentifier\":\"dev.expo.updatese2e\"},\"updates\":{\"url\":\"http://$UPDATES_HOST:$UPDATES_PORT/update\"}}" > app.config.json
108      - name: Generate code signing
109        working-directory: ../updates-e2e
110        run: yarn expo-updates codesigning:generate --key-output-directory keys --certificate-output-directory certs --certificate-validity-duration-years 1 --certificate-common-name "E2E Test App"
111      - name: Configure code signing
112        working-directory: ../updates-e2e
113        run: yarn expo-updates codesigning:configure --certificate-input-directory certs --key-input-directory keys
114      - name: Pack latest bare-minimum template as tarball for expo prebuild
115        working-directory: templates/expo-template-bare-minimum
116        run: echo "$PWD" && npm pack --pack-destination ../../../updates-e2e/
117      - name: Prebuild
118        working-directory: ../updates-e2e
119        run: expo-cli prebuild --template expo-template-bare-minimum-*.tgz
120      - name: Copy App.js from test fixtures
121        working-directory: ../updates-e2e
122        run: cp ../expo/packages/expo-updates/e2e/__tests__/fixtures/App.js .
123      - name: Set host and port in App.js
124        working-directory: ../updates-e2e
125        run: sed -i -e "s/UPDATES_HOST/$UPDATES_HOST/" ./App.js && sed -i -e "s/UPDATES_PORT/$UPDATES_PORT/" ./App.js
126      - name: Assemble release APK
127        working-directory: ../updates-e2e/android
128        run: ./gradlew assembleRelease --stacktrace
129      - name: Copy APK to working directory
130        run: cp -R ../updates-e2e/android/app/build/outputs/apk artifact
131      - name: Upload test APK artifact
132        uses: actions/upload-artifact@v3
133        with:
134          name: updates-e2e-android-apk
135          path: artifact
136      - name: Get test APK path
137        id: test-apk-path
138        working-directory: ../updates-e2e/android/app/build/outputs/apk/release
139        run: echo "::set-output name=dir::$(pwd)"
140      - name: Export update for test server to host
141        working-directory: ../updates-e2e
142        run: expo export --public-url https://u.expo.dev/dummy-url --platform android
143      - name: Get test update dist path
144        id: test-update-dist-path
145        working-directory: ../updates-e2e/dist
146        run: echo "::set-output name=dir::$(pwd)"
147      - name: Get test code signing private key path
148        id: test-code-signing-private-key-path
149        working-directory: ../updates-e2e/keys
150        run: echo "::set-output name=dir::$(pwd)/private-key.pem"
151      - name: �� Run tests
152        env:
153          TEST_APK_PATH: '${{ steps.test-apk-path.outputs.dir }}/app-release.apk'
154          TEST_UPDATE_DIST_PATH: '${{ steps.test-update-dist-path.outputs.dir }}'
155          TEST_PRIVATE_KEY_PATH: '${{ steps.test-code-signing-private-key-path.outputs.dir }}'
156        timeout-minutes: 30
157        uses: reactivecircus/android-emulator-runner@v2
158        with:
159          api-level: ${{ matrix.api-level }}
160          avd-name: avd-${{ matrix.api-level }}
161          arch: x86_64
162          force-avd-creation: false
163          script: yarn test --config e2e/jest.config.android.js
164          working-directory: packages/expo-updates
165
166  ios:
167    runs-on: macos-11
168    timeout-minutes: 60
169    env:
170      UPDATES_HOST: localhost
171      UPDATES_PORT: 4747
172    steps:
173      - name: �� Checkout
174        uses: actions/checkout@v3
175      - name: �� Switch to Xcode 13.2.1
176        run: sudo xcode-select --switch /Applications/Xcode_13.2.1.app
177      - name: ➕ Add `bin` to GITHUB_PATH
178        run: echo "$(yarn global bin)" >> $GITHUB_PATH
179      - name: ♻️ Restore caches
180        uses: ./.github/actions/expo-caches
181        id: expo-caches
182        with:
183          yarn-workspace: 'true'
184      - name: �� Yarn install
185        if: steps.expo-caches.outputs.yarn-workspace-hit != 'true'
186        run: yarn install --frozen-lockfile
187      - name: Build expo-updates CLI
188        working-directory: packages/expo-updates
189        run: yarn build:cli
190      - name: �� Install Expo CLI
191        run: yarn global add expo-cli
192      - name: Init new expo app
193        working-directory: ../
194        run: expo-cli init updates-e2e --yes
195      - name: Add yarn resolutions for local dependencies
196        working-directory: ../updates-e2e
197        run: |
198          # A jq filter to add a "resolutions" field
199          JQ_FILTER=$(cat << EOF
200            . + {
201              resolutions: {
202                "expo-application": "file:../expo/packages/expo-application",
203                "expo-constants": "file:../expo/packages/expo-constants",
204                "expo-eas-client": "file:../expo/packages/expo-eas-client",
205                "expo-error-recovery": "file:../expo/packages/expo-error-recovery",
206                "expo-file-system": "file:../expo/packages/expo-file-system",
207                "expo-font": "file:../expo/packages/expo-font",
208                "expo-json-utils": "file:../expo/packages/expo-json-utils",
209                "expo-keep-awake": "file:../expo/packages/expo-keep-awake",
210                "expo-manifests": "file:../expo/packages/expo-manifests",
211                "expo-modules-core": "file:../expo/packages/expo-modules-core",
212                "expo-structured-headers": "file:../expo/packages/expo-structured-headers",
213                "expo-updates-interface": "file:../expo/packages/expo-updates-interface"
214              }
215            }
216          EOF
217          )
218          jq "$JQ_FILTER" < package.json > new-package.json
219          mv new-package.json package.json
220      - name: Add local expo packages
221        working-directory: ../updates-e2e
222        run: yarn add file:../expo/packages/expo-updates file:../expo/packages/expo file:../expo/packages/expo-splash-screen file:../expo/packages/expo-status-bar
223      - name: Setup app.config.json
224        working-directory: ../updates-e2e
225        run: echo "{\"name\":\"updates-e2e\",\"runtimeVersion\":\"1.0.0\",\"plugins\":[\"expo-updates\"],\"android\":{\"package\":\"dev.expo.updatese2e\"},\"ios\":{\"bundleIdentifier\":\"dev.expo.updatese2e\"},\"updates\":{\"url\":\"http://$UPDATES_HOST:$UPDATES_PORT/update\"}}" > app.config.json
226      - name: Generate code signing
227        working-directory: ../updates-e2e
228        run: yarn expo-updates codesigning:generate --key-output-directory keys --certificate-output-directory certs --certificate-validity-duration-years 1 --certificate-common-name "E2E Test App"
229      - name: Configure code signing
230        working-directory: ../updates-e2e
231        run: yarn expo-updates codesigning:configure --certificate-input-directory certs --key-input-directory keys
232      - name: Pack latest bare-minimum template as tarball for expo prebuild
233        working-directory: templates/expo-template-bare-minimum
234        run: npm pack --pack-destination ../../../updates-e2e/
235      - name: Prebuild --no-install
236        working-directory: ../updates-e2e
237        run: expo-cli prebuild --template expo-template-bare-minimum-*.tgz --no-install && yarn
238      # TODO: not caching pods for now as we don't have a lockfile with which to use in the key
239      #       and as this is a minimal project, time savings is not much anyway (~3.5 mins at most)
240      # - name: Restore updates-e2e/ios/Pods from cache
241      #   uses: actions/cache@v2
242      #   id: pods-cache
243      #   with:
244      #     path: '../updates-e2e/ios/Pods'
245      #     key: ${{ runner.os }}-pods-updatese2e-${{ hashFiles('../updates-e2e/ios/Podfile.lock') }}
246      #     # restore-keys: |
247      #     #   ${{ runner.os }}-pods-updatese2e-
248      - name: �� Install CocoaPods in `updates-e2e/ios`
249        run: pod install
250        working-directory: ../updates-e2e/ios
251      - name: Copy App.js from test fixtures
252        working-directory: ../updates-e2e
253        run: cp ../expo/packages/expo-updates/e2e/__tests__/fixtures/App.js .
254      - name: Set host and port in App.js
255        working-directory: ../updates-e2e
256        run: sed -i -e "s/UPDATES_HOST/$UPDATES_HOST/" ./App.js && sed -i -e "s/UPDATES_PORT/$UPDATES_PORT/" ./App.js
257      - name: Build release app
258        working-directory: ../updates-e2e/ios
259        run: xcodebuild -workspace updatese2e.xcworkspace -scheme updatese2e -configuration Release -destination "generic/platform=iOS Simulator" -derivedDataPath ./build build
260      - name: Copy app to working directory
261        run: cp -R ../updates-e2e/ios/build/Build/Products/Release-iphonesimulator/updatese2e.app artifact
262      - name: Upload test app artifact
263        uses: actions/upload-artifact@v3
264        with:
265          name: updates-e2e-ios-app
266          path: artifact
267      - name: Get test app path
268        id: test-app-path
269        working-directory: ../updates-e2e/ios/build/Build/Products/Release-iphonesimulator/
270        run: echo "::set-output name=dir::$(pwd)"
271      - name: Export update for test server to host
272        working-directory: ../updates-e2e
273        run: expo export --public-url https://u.expo.dev/dummy-url --platform ios
274      - name: Get test update dist path
275        id: test-update-dist-path
276        working-directory: ../updates-e2e/dist
277        run: echo "::set-output name=dir::$(pwd)"
278      - name: Get test code signing private key path
279        id: test-code-signing-private-key-path
280        working-directory: ../updates-e2e/keys
281        run: echo "::set-output name=dir::$(pwd)/private-key.pem"
282      - name: Start simulator
283        run: |
284          xcrun simctl list devices -j \
285          | jq -rc '[ .[] | .[] | .[] | select( .name | contains( "iPhone" ) ) | select( .isAvailable == true ) ] | last.udid ' \
286          | xargs open -a Simulator --args -CurrentDeviceUDID
287      - name: �� Run tests
288        env:
289          TEST_APP_PATH: '${{ steps.test-app-path.outputs.dir }}/updatese2e.app'
290          TEST_UPDATE_DIST_PATH: '${{ steps.test-update-dist-path.outputs.dir }}'
291          TEST_PRIVATE_KEY_PATH: '${{ steps.test-code-signing-private-key-path.outputs.dir }}'
292        timeout-minutes: 30
293        working-directory: packages/expo-updates
294        run: yarn test --config e2e/jest.config.ios.js
295