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