Skip to content

Build caching: Swift packages, pub cache, Bitrise caches, opt-in ccache - #32

Open
Interlap01 wants to merge 7 commits into
mainfrom
caching
Open

Interlap01 wants to merge 7 commits into
mainfrom
caching

Conversation

@Interlap01

Copy link
Copy Markdown
Collaborator

What

  • Swift packages: every runner clones packages into ~/.ios-builder/SourcePackages (-clonedSourcePackagesDirPath on every xcodebuild that passes -derivedDataPath, and on the apply_build_number calls). GitHub caches it keyed on the workspace/project Package.resolved (excluding DerivedData, node_modules, Pods); Codemagic caches the path. Stale DerivedData/SourcePackages from older runs is deleted before the DerivedData save.
  • Flutter pub cache on GitHub: own step keyed on pubspec.lock with a prefix fallback; flutter-action runs with pub-cache: false (its own pub cache had no fallback key).
  • ios-share: now restores Pods, node_modules, Swift packages, pub cache and ccache, and saves each before the share step (success only, key missed, under cache-primary-key).
  • Bitrise: restore-cache@3/save-cache@1 for DerivedData, Swift packages, Pods, node_modules, pub cache, Gradle and ccache. Keys checksum the snapshot's lockfiles, so the snapshot is checked out in its own step (runner.sh checkout) before the restores. The node_modules BITRISE_CACHE_HIT is aliased so an exact hit skips the install, as on GitHub. Only the per-build DerivedData/ccache saves run after a failed build.
  • ccache, opt-in: "cache": {"ccache": true} in builder.json, React Native and Expo only. A shared shell block (identical in both GitHub templates and runner.sh) installs ccache and sets USE_CCACHE=1/CCACHE_DIR before pod install. ~/.ccache is cached on all three providers.
  • The device DerivedData prefix is now deriveddata-device-: deriveddata- also matched the simulator workflow's deriveddata-sim-* caches.

Why ccache is opt-in

A fresh checkout gives every file a new mtime, so a restored DerivedData still recompiles React Native and its native modules. ccache matches on content, so it helps there. But the Podfile decides whether clang goes through it: React Native's react_native_post_install reads USE_CCACHE, and Expo's generated Podfile reads apple.ccacheEnabled from Podfile.properties.json. A project whose Podfile does neither gains nothing, and installing ccache costs time on every run. Native, Flutter and KMP ignore the switch.

Tests

  • New internal/workflow/cache_test.go:
    • every GitHub cache/restore has a save for the same paths and a key it can find again, and in ios-share that save comes before the share step
    • cache keys and paths per workflow
    • every -derivedDataPath also passes -clonedSourcePackagesDirPath
    • the ccache block is identical across templates and runs before pod install
    • the ccache opt-in runs against a stubbed brew
    • Bitrise YAML structure: restores between checkout and build, each paired with a save, key templates evaluated, saves before the share step
    • Codemagic cache paths
  • Config round-trip test for cache.ccache.
  • go test -race ./..., go vet ./... and gofmt -l . are clean. golangci-lint could not run locally (the installed binary was built with Go 1.25 and the module needs 1.26). actionlint is clean on both GitHub templates. Nothing was run against a real CI provider.

Left out

  • Codemagic Pods and node_modules: Codemagic caches by path with no key, so a stale copy would be restored on every build.
  • -clonedSourcePackagesDirPath on xcodebuild -list, which detects the scheme. I did not confirm that -list accepts the flag, so that call still resolves packages into the default DerivedData.
  • flutter build ios resolves its own Swift packages. Only the signed Flutter archive uses the cached directory.
  • Existing Bitrise users need to rerun builder init --provider bitrise to get the new bitrise.yml.

The runners read the opt-in ccache switch from builder.json in the
snapshot; without a field for it, any command that rewrites the file
would drop it.
Swift packages are cloned into ~/.ios-builder/SourcePackages with
-clonedSourcePackagesDirPath on every xcodebuild that resolves the
package graph, and cached on the workspace/project Package.resolved.
The pub cache gets a step of its own with a fallback key, and ccache is
opt-in for React Native and Expo through cache.ccache.

ios-share now restores Pods, node_modules, Swift packages, the pub cache
and ccache too, and saves them before the share step. The device
DerivedData prefix becomes deriveddata-device-, since deriveddata- also
matched the simulator workflow's caches.
… cache paths

runner.sh clones Swift packages into the same directory as the GitHub
workflows and carries the shared ccache block; Codemagic caches both
paths.
restore-cache/save-cache for DerivedData, Swift packages, Pods,
node_modules, the pub cache, Gradle and ccache. The keys checksum the
snapshot's lockfiles, so the snapshot is checked out in a step of its
own before the restores. An exact node_modules hit skips the install,
and ios-share saves before the share step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant