From 587bd01f78bf4185f065f2866db12d77e9211e06 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira Date: Wed, 23 Sep 2026 09:59:22 +0100 Subject: [PATCH 1/2] ci: build and upload example app --- .github/workflows/build-example-apps.yml | 143 +++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 .github/workflows/build-example-apps.yml diff --git a/.github/workflows/build-example-apps.yml b/.github/workflows/build-example-apps.yml new file mode 100644 index 0000000000..e4e383c701 --- /dev/null +++ b/.github/workflows/build-example-apps.yml @@ -0,0 +1,143 @@ +name: Build example apps + +on: + push: + branches: + - main + paths-ignore: + - docs/** + - '**/*.md' + pull_request: + paths-ignore: + - docs/** + - '**/*.md' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + android: + name: Android + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup + uses: ./.github/actions/setup + + - name: Calculate fingerprint + id: fingerprint + working-directory: example + run: | + fingerprint=$(yarn expo-updates fingerprint:generate --platform android | jq -er .hash) + echo "fingerprint=$fingerprint" >> "$GITHUB_OUTPUT" + + - name: Cache release build + id: cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: react-native-paper-example.apk + key: android-${{ steps.fingerprint.outputs.fingerprint }} + + # Repacking shells out to `apktool`, so this cannot be gated on the cache. + - name: Setup JDK + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 + with: + distribution: temurin + java-version: 17 + + # KSP in `expo-updates` runs out of the 512m metaspace that `expo prebuild` sets. + - name: Build Android app + if: steps.cache.outputs.cache-hit != 'true' + working-directory: example + run: | + yarn expo prebuild --platform android --no-install + cd android + ./gradlew :app:assembleRelease -Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=1g -PreactNativeArchitectures=arm64-v8a,x86_64 + mv app/build/outputs/apk/release/app-release.apk ../../react-native-paper-example.apk + + - name: Repack cached build + if: steps.cache.outputs.cache-hit == 'true' + working-directory: example + run: | + yarn dlx @expo/repack-app@0.10.3 \ + --platform android \ + --source-app ../react-native-paper-example.apk \ + --output ../react-native-paper-example.apk + + - name: Upload APK + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + path: react-native-paper-example.apk + archive: false + retention-days: 30 + + ios: + name: iOS + runs-on: macos-latest + timeout-minutes: 60 + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup + uses: ./.github/actions/setup + + - name: Calculate fingerprint + id: fingerprint + working-directory: example + run: | + fingerprint=$(yarn expo-updates fingerprint:generate --platform ios | jq -er .hash) + echo "fingerprint=$fingerprint" >> "$GITHUB_OUTPUT" + + - name: Cache release build + id: cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: react-native-paper-example.app + key: ios-${{ steps.fingerprint.outputs.fingerprint }} + + - name: Build iOS app + if: steps.cache.outputs.cache-hit != 'true' + working-directory: example + run: | + yarn expo prebuild --platform ios --no-install + cd ios + pod install + xcodebuild build \ + -workspace ReactNativePaperExample.xcworkspace \ + -scheme ReactNativePaperExample \ + -configuration Release \ + -destination 'generic/platform=iOS Simulator' \ + -derivedDataPath build \ + ARCHS=arm64 + mv build/Build/Products/Release-iphonesimulator/ReactNativePaperExample.app ../../react-native-paper-example.app + + # Repacking in place fails with ENOTEMPTY on an existing app directory. + - name: Repack cached build + if: steps.cache.outputs.cache-hit == 'true' + working-directory: example + run: | + mv ../react-native-paper-example.app "$RUNNER_TEMP/cached.app" + yarn dlx @expo/repack-app@0.10.3 \ + --platform ios \ + --source-app "$RUNNER_TEMP/cached.app" \ + --output ../react-native-paper-example.app + + # `ditto` keeps the symlinks and executable bits a plain upload drops. + - name: Archive app + run: ditto -c -k --keepParent react-native-paper-example.app react-native-paper-example.app.zip + + - name: Upload app + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + path: react-native-paper-example.app.zip + archive: false + retention-days: 30 From 66c85778dc98bd26c16a7ddfdbdacf7c1309bb04 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira Date: Tue, 29 Sep 2026 10:51:00 +0100 Subject: [PATCH 2/2] ci: address review feedback on example app builds --- .github/workflows/build-example-apps.yml | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-example-apps.yml b/.github/workflows/build-example-apps.yml index e4e383c701..64bc9fc819 100644 --- a/.github/workflows/build-example-apps.yml +++ b/.github/workflows/build-example-apps.yml @@ -4,13 +4,23 @@ on: push: branches: - main - paths-ignore: - - docs/** - - '**/*.md' + paths: + - '**' + - '!docs/**' + - '!**/*.md' + - '!**/__tests__/**' + - '!jest/**' + - '!.github/workflows/**' + - '.github/workflows/build-example-apps.yml' pull_request: - paths-ignore: - - docs/** - - '**/*.md' + paths: + - '**' + - '!docs/**' + - '!**/*.md' + - '!**/__tests__/**' + - '!jest/**' + - '!.github/workflows/**' + - '.github/workflows/build-example-apps.yml' workflow_dispatch: permissions: @@ -21,8 +31,8 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - android: - name: Android + build-android: + name: Build Android runs-on: ubuntu-latest timeout-minutes: 60 steps: @@ -44,16 +54,14 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: react-native-paper-example.apk - key: android-${{ steps.fingerprint.outputs.fingerprint }} + key: android-${{ steps.fingerprint.outputs.fingerprint }}-${{ hashFiles('.github/workflows/build-example-apps.yml') }} - # Repacking shells out to `apktool`, so this cannot be gated on the cache. - name: Setup JDK uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: temurin java-version: 17 - # KSP in `expo-updates` runs out of the 512m metaspace that `expo prebuild` sets. - name: Build Android app if: steps.cache.outputs.cache-hit != 'true' working-directory: example @@ -79,8 +87,8 @@ jobs: archive: false retention-days: 30 - ios: - name: iOS + build-ios: + name: Build iOS runs-on: macos-latest timeout-minutes: 60 steps: @@ -102,7 +110,7 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: react-native-paper-example.app - key: ios-${{ steps.fingerprint.outputs.fingerprint }} + key: ios-${{ steps.fingerprint.outputs.fingerprint }}-${{ hashFiles('.github/workflows/build-example-apps.yml') }} - name: Build iOS app if: steps.cache.outputs.cache-hit != 'true' @@ -120,7 +128,6 @@ jobs: ARCHS=arm64 mv build/Build/Products/Release-iphonesimulator/ReactNativePaperExample.app ../../react-native-paper-example.app - # Repacking in place fails with ENOTEMPTY on an existing app directory. - name: Repack cached build if: steps.cache.outputs.cache-hit == 'true' working-directory: example @@ -131,7 +138,6 @@ jobs: --source-app "$RUNNER_TEMP/cached.app" \ --output ../react-native-paper-example.app - # `ditto` keeps the symlinks and executable bits a plain upload drops. - name: Archive app run: ditto -c -k --keepParent react-native-paper-example.app react-native-paper-example.app.zip