Skip to content

ci: cache CI dependencies to reduce PR workflow runtime - #753

Closed
nickolas-dimitrakas wants to merge 7 commits into
mainfrom
ci/cache-ci-dependencies
Closed

ci: cache CI dependencies to reduce PR workflow runtime#753
nickolas-dimitrakas wants to merge 7 commits into
mainfrom
ci/cache-ci-dependencies

Conversation

@nickolas-dimitrakas

@nickolas-dimitrakas nickolas-dimitrakas commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Background

PR workflow jobs in `build-kits` were taking 15-19 minutes each because third-party SDKs (Firebase, Airship, Rokt) were being downloaded and compiled from scratch on every run with no caching.

Profiled from CI run #24418060388:

Job Duration
Pod Lint urbanairship-19 18m 55s
Build firebase-ga4-12 17m 49s
Build firebase-ga4-11 16m 23s
Build firebase-11 15m 59s
Build urbanairship-20 15m 13s
Build rokt 13m 6s

What Has Changed

build-kits.yml

  • Added actions/cache@v5.0.5 for ~/.cocoapods and ~/Library/Caches/CocoaPods in pod-lint-kits, keyed per-kit by podspec hash + weekly window — avoids re-downloading Airship/Firebase on every lint run; weekly window ensures new upstream releases are picked up
  • Added full DerivedData cache in build-kits, key computed via shell find | shasum across kit source files + core SDK source files (mParticle-Apple-SDK/**, mParticle-Apple-SDK-Swift/**) — enables incremental xcodebuild instead of full recompilation on warm runs; busts on any kit or core SDK change
  • Added timeout-minutes: 30 to both pod-lint-kits and build-kits jobs to enforce the target CI runtime
  • Reduced fetch-depth from 01 (full git history not needed for builds)

build-and-lint.yml

  • Added gem cache (~/.gem) for xcodeproj; switched to user-level gem install

cross-platform-tests.yml

  • Added gem cache (~/.gem) for cocoapods + cocoapods-generate, keyed by Podfile.lock

integration-tests.yml

  • Added actions/cache@v5.0.5 for WireMock JAR, keyed by version — skips Maven Central download on cache hit

All actions/cache references pinned to SHA (v5.0.5).

Screenshots/Video

N/A

Checklist

  • Self-review completed
  • Tests added or updated
  • Tested locally

Additional Notes

Cold runs (first PR after a cache miss) remain as today. On warm runs (no source changes), kit builds should drop from 15-18 min to ~2-5 min via incremental xcodebuild. Monitor GitHub Actions cache storage in Settings → Actions → Caches — Firebase DerivedData is large (1-3 GB per kit) and may approach the 10 GB repo limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Apr 14, 2026

Copy link
Copy Markdown

📦 SDK Size Impact Report

Measures how much the SDK adds to an app's size (with-SDK minus without-SDK).

Metric Target Branch This PR Change
App Bundle Impact 1.77 MB 1.77 MB +N/A
Executable Impact 848 bytes 848 bytes +N/A
XCFramework Size 6.46 MB 6.46 MB +N/A

➡️ SDK size impact change is minimal.

Raw measurements

Target branch (main):

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1900,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":1816,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6616}

This PR:

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1900,"with_sdk_executable_size_bytes":76312,"sdk_impact_kb":1816,"sdk_executable_impact_bytes":848,"xcframework_size_kb":6616}

@nickolas-dimitrakas nickolas-dimitrakas self-assigned this Apr 14, 2026
nickolas-dimitrakas and others added 6 commits April 14, 2026 16:55
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rmat() limitation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nickolas-dimitrakas

Copy link
Copy Markdown
Contributor Author

Superseded by #981 — this PR predates the SPM-resolve watchdog/retry logic added in #867, and merging it as-is would have silently reverted that fix. #981 covers the same caching goal without touching that step, and deliberately avoids caching compiled DerivedData (the riskier part of this PR) in favor of caching only raw dependency sources.

nickolas-dimitrakas added a commit that referenced this pull request Sep 9, 2026
build-kits Build jobs still routinely take 10-18 min per kit (largely
re-fetching multi-GB transitive SPM deps like stripe-ios from scratch
on every run); pod-lint, build-and-lint, cross-platform-tests, and
integration-tests all re-download CocoaPods/gem/WireMock sources the
same way. None of this is cached today.

Cache only immutable, pre-compile inputs, never compiled build
products:
- build-kits: weekly-keyed CocoaPods source cache (pod-lint-kits) and
  a per-kit SwiftPM source cache at ~/Library/Caches/org.swift.swiftpm
  (build-kits) — shared across the kit's main/example/test builds,
  restored before dependency resolution
- build-and-lint, cross-platform-tests: Ruby gem caches for
  xcodeproj/cocoapods (switched to --user-install so the cache path is
  writable without sudo)
- integration-tests: WireMock JAR cache keyed by version

Deliberately does not cache DerivedData/compiled build products: the
existing hash-based cache key can't capture Xcode/toolchain drift, and
20 kits x 1-3GB of DerivedData would blow past the 10GB per-repo cache
limit and evict constantly. Caching only sources means every build
still recompiles from scratch and can't go stale — the "Resolve SPM
dependencies" watchdog step (added since to bound hung fetches) is
untouched.

Supersedes #753, which predates that watchdog step and would have
silently dropped it on merge.
nickolas-dimitrakas added a commit that referenced this pull request Sep 10, 2026
* ci: cache raw dependency sources to cut PR/build-kits runtime

build-kits Build jobs still routinely take 10-18 min per kit (largely
re-fetching multi-GB transitive SPM deps like stripe-ios from scratch
on every run); pod-lint, build-and-lint, cross-platform-tests, and
integration-tests all re-download CocoaPods/gem/WireMock sources the
same way. None of this is cached today.

Cache only immutable, pre-compile inputs, never compiled build
products:
- build-kits: weekly-keyed CocoaPods source cache (pod-lint-kits) and
  a per-kit SwiftPM source cache at ~/Library/Caches/org.swift.swiftpm
  (build-kits) — shared across the kit's main/example/test builds,
  restored before dependency resolution
- build-and-lint, cross-platform-tests: Ruby gem caches for
  xcodeproj/cocoapods (switched to --user-install so the cache path is
  writable without sudo)
- integration-tests: WireMock JAR cache keyed by version

Deliberately does not cache DerivedData/compiled build products: the
existing hash-based cache key can't capture Xcode/toolchain drift, and
20 kits x 1-3GB of DerivedData would blow past the 10GB per-repo cache
limit and evict constantly. Caching only sources means every build
still recompiles from scratch and can't go stale — the "Resolve SPM
dependencies" watchdog step (added since to bound hung fetches) is
untouched.

Supersedes #753, which predates that watchdog step and would have
silently dropped it on merge.

* ci: fix gem cache path and quote GITHUB_ENV/PATH redirects

Cursor Bugbot: --user-install only lands in ~/.gem when that directory
already exists; a fresh runner has neither, so RubyGems' XDG fallback
(~/.local/share/gem) is used instead, and the ~/.gem cache silently
never populates. Cache both candidate paths.

CodeRabbit/actionlint: quote the $GITHUB_ENV/$GITHUB_PATH redirect
targets (SC2086).

* ci: use ISO week-based year for cache week key

%Y is the calendar year, %V is the ISO week number — they disagree
near year boundaries (e.g. Dec 31 2026 falls in ISO week 2027-W01),
splitting one ISO week across two cache keys. %G is the matching
ISO week-based year.

* ci: disambiguate cache restore-key kit-name boundaries

restore-keys is a plain string-prefix match. Kit names share hyphens
(rokt is a literal prefix of rokt-sdk-plus-ios), so a "kit-name-"
boundary let a small kit's cache miss restore a much bigger kit's
multi-GB cache instead. "::" can't appear in a kit name, so it can't
collide with any current or future kit.
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