1.8 KiB
id, date, status, scope, evidence, destination, review_after
| id | date | status | scope | evidence | destination | review_after |
|---|---|---|---|---|---|---|
| 2026-08-30-ios-extension-version-verification | 2026-08-30 | promoted | iOS release artifact verification | v1.0.6 exported IPA inspection and reproduced v1.0.7 Xcode build-setting mismatch | apps/mobile/scripts/release-preflight.mjs and .codex/skills/release-mobile/SKILL.md | 2027-02-28 |
Symptom
The signed iOS build logged that the widget extension build number 44 did not match the containing app build number 45, even though export completed.
Reproduction
Build iOS version 1.0.6 with EAS auto-increment from build 44 to 45 and retain the
archive log. Extract the resulting IPA with ditto, then read the containing app
and every packaged extension Info.plist with PlistBuddy.
Cause
The v1.0.6 archive warning described an intermediate state and was not
authoritative for that exported package. The later v1.0.7 reproduction found a
separate real hazard: CURRENT_PROJECT_VERSION in both LiveDrawWidget
configurations can override the widget plist and package an older build number.
Remediation
Before every iOS release, require public-version parity across app config, both
plists, and Xcode marketing settings. Require the widget Debug and Release
CURRENT_PROJECT_VERSION values to equal both plists. Then inspect the exported
app and all packaged extensions. Reject or rebuild only when the final IPA values
differ; do not accept or reject a release from archive warnings alone.
Evidence
PlistBuddy read CFBundleShortVersionString 1.0.6 and CFBundleVersion 45 from
both v1.0.6 packaged plists. The v1.0.7 build later proved a stale widget Xcode
setting can survive plist-only review. release-preflight.mjs and its node test
now reject that mismatch before EAS allocation; exported IPA inspection remains
the final authority.