From 512e55f0ad659663dcbde43008f05697882965b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Roz=CC=87niata?= <56474758+krozniata@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:58:18 +0100 Subject: [PATCH] feat(ios): cache Swift compiles with Xcode compilation cache --- .github/workflows/ios.yml | 45 ++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 0fffeedb..580d9cb2 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -23,6 +23,7 @@ jobs: # Runner image updates touch clang even when it hasn't changed, so # compare its contents instead of its mtime. CCACHE_COMPILERCHECK: content + XCODE_CAS_DIR: ${{ github.workspace }}/.xcode-cas AGENT_DEVICE_RUNNER_PATHS: | ~/.agent-device/apple-runner/derived/ios-simulator/*/Build/Products/* ~/.agent-device/apple-runner/derived/ios-simulator/*/.agent-device-runner-cache.json @@ -50,13 +51,29 @@ jobs: - name: Install ccache run: brew install ccache - - name: Cache ccache - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + - name: Resolve Xcode version + id: xcode + run: echo "build=$(xcodebuild -version | awk '/Build version/ { print $3 }')" >> "$GITHUB_OUTPUT" + + - name: Restore ccache + id: ccache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: .ccache key: ccache-ios${{ inputs.spm && '-spm' || '' }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: ccache-ios${{ inputs.spm && '-spm' || '' }}- + # Xcode's compilation cache handles the Swift side (ccache can't). Nothing + # prunes it, so the key starts it over whenever Xcode or the native + # dependencies (Podfile.lock) change. + - name: Restore Xcode CAS + id: xcode-cas + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ env.XCODE_CAS_DIR }} + key: xcode-cas-ios${{ inputs.spm && '-spm' || '' }}-xcode-${{ steps.xcode.outputs.build }}-${{ hashFiles('example/ios/Podfile.lock') }}-${{ github.run_id }}-${{ github.run_attempt }} + restore-keys: xcode-cas-ios${{ inputs.spm && '-spm' || '' }}-xcode-${{ steps.xcode.outputs.build }}-${{ hashFiles('example/ios/Podfile.lock') }}- + - name: Install example Pods if: ${{ !inputs.spm }} run: bun pods @@ -81,13 +98,30 @@ jobs: run: defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool false - name: Build iOS App + id: build # RN's USE_CCACHE wrapper silently skips ccache on Xcode 26 # (facebook/react-native#56612), so use Xcode's compiler launcher. run: | ccache --zero-stats - bun example:ios:release --extra-params "C_COMPILER_LAUNCHER=$(command -v ccache) CLANG_ENABLE_EXPLICIT_MODULES_WITH_COMPILER_LAUNCHER=YES ONLY_ACTIVE_ARCH=YES" + bun example:ios:release --extra-params "C_COMPILER_LAUNCHER=$(command -v ccache) CLANG_ENABLE_EXPLICIT_MODULES_WITH_COMPILER_LAUNCHER=YES ONLY_ACTIVE_ARCH=YES CLANG_ENABLE_COMPILE_CACHE=NO SWIFT_ENABLE_COMPILE_CACHE=YES COMPILATION_CACHE_CAS_PATH=$XCODE_CAS_DIR" ccache --show-stats -v + # Save right after the build, so a failing e2e test doesn't throw away + # fresh compiler cache entries. + - name: Save ccache + if: ${{ !cancelled() && steps.build.outcome != 'skipped' }} + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: .ccache + key: ${{ steps.ccache.outputs.cache-primary-key }} + + - name: Save Xcode CAS + if: ${{ !cancelled() && steps.build.outcome != 'skipped' }} + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ env.XCODE_CAS_DIR }} + key: ${{ steps.xcode-cas.outputs.cache-primary-key }} + # The runner depends only on agent-device and Xcode, not on bun.lock. - name: Resolve agent-device runner cache key id: agent-device @@ -95,8 +129,9 @@ jobs: pkg=e2e/node_modules/agent-device/package.json [ -f "$pkg" ] || pkg=node_modules/agent-device/package.json version=$(jq -r .version "$pkg") - xcode=$(xcodebuild -version | awk '/Build version/ { print $3 }') - echo "key=agent-device-runner-${RUNNER_OS}-${RUNNER_ARCH}-${version}-xcode-${xcode}" >> "$GITHUB_OUTPUT" + echo "key=agent-device-runner-${RUNNER_OS}-${RUNNER_ARCH}-${version}-xcode-${XCODE_BUILD}" >> "$GITHUB_OUTPUT" + env: + XCODE_BUILD: ${{ steps.xcode.outputs.build }} - name: Restore agent-device runner id: agent-device-cache