App Ops Desk · Issue #11

CI vs local archive drift

“Works on my machine” becomes “fails only in CI” becomes a lost week. Drift is usually Xcode version, signing secrets, scheme config, or dependency resolution — not cosmic rays.

Read time: 7 min CI/CD Reproducibility Pairs with Issues #5, #7, and #8
One action this week: Write one sentence: “Production archives come from ___ (local / CI job name) using Xcode ___.” If you cannot finish the sentence, pick a single source of truth this week.

Pick one ship factory

Either:

  • Local ship: you archive on a labeled ship machine; CI is tests only
  • CI ship: CI archives and uploads; local is for development

Hybrid without rules is how two “build 240”s mean different git trees.

Drift checklist

  • Different Xcode major/minor than local
  • Different scheme / configuration (Debug flags sneaking into Release)
  • Resolved package versions not locked
  • Signing cert only on one machine
  • Environment plist values injected only in CI
  • Cached DerivedData vs clean CI workspace

Make archives comparable

Always log:
git SHA
xcodebuild -version
scheme + configuration
TEAM_ID / bundle id
dependency lock hash (Package.resolved / Podfile.lock)
export options / upload destination

If CI and local disagree, compare this block before comparing crash logs.

Practical solo default

If you are truly alone and CI is flaky: ship from local with a written Xcode pin, and keep CI as unit/UI tests. Add CI archives only when the log above is automated.

Bottom line

One ship factory. Same Xcode lane, same locks, same signing inputs. Everything else is debugging two products that share a name.

Resources hub → Reading order and jump-by-symptom links. Join the App Ops Desk waitlist Weekly release ops for people who ship alone.