Skip to content

fix(ios): stop the companion shipping every build as 1.0 (1) - #231

Merged
arzafran merged 1 commit into
mainfrom
fix/ios-companion-bundle-version
Jul 31, 2026
Merged

fix(ios): stop the companion shipping every build as 1.0 (1)#231
arzafran merged 1 commit into
mainfrom
fix/ios-companion-bundle-version

Conversation

@arzafran

Copy link
Copy Markdown
Member

What this does

The phone companion has been shipping every TestFlight build with the same version and build number, 1.0 (1). That is why there is no way to tell, from a phone, whether the installed app is current. It also quietly blocked the release lane: App Store Connect already recorded build 1 under version 1.0, so the next upload would have bounced as a duplicate. The lane worked once, on 30 July, and has been stuck since.

This makes the build number actually reach the app, adds a check so it cannot silently stop reaching it again, and puts the version on screen in the app so the question is answerable from the phone.

Summary

  1. ios/ProgramaSpike/project.yml declares CFBundleShortVersionString and CFBundleVersion as $(MARKETING_VERSION) / $(CURRENT_PROJECT_VERSION) on both targets. xcodegen's defaults for those keys are the literals 1.0 and 1, and since info.path sets INFOPLIST_FILE, Xcode substitutes only $(...) references. The value build-ios-testflight.sh passes on the archive command line was being discarded.
  2. MARKETING_VERSION goes 0.1 to 1.0. Now that the setting reaches the bundle, leaving it at 0.1 would push the version string backwards against a record that already exists in App Store Connect.
  3. scripts/build-ios-testflight.sh reads CFBundleVersion back out of the signed app and the signed appex and refuses to upload if either does not match the number the run computed. The existing verification covered entitlements only, which is why this shipped.
  4. New AppVersion.swift plus a version row on the pairing screen and the workspace list. The app displayed nothing about itself before. The row is selectable so the build number can be copied and compared against a workflow run.
  5. The widget's generated Info.plist was tracked while the app's was ignored. Untracked for symmetry, since a committed copy of a generated file is what hid this.

Test plan

  • xcodegen generate emits both plists with $(MARKETING_VERSION) / $(CURRENT_PROJECT_VERSION)
  • Build with CURRENT_PROJECT_VERSION=424242, expect app and widget plists to both read 1.0 (424242). Before this change both read 1.
  • Confirmed the bug against the shipped artifact from run 30574301994, which reports 1.0 (1)
  • After merge, the push to main runs ios-testflight.yml; expect the new bundle-version check to pass and the upload to be accepted rather than rejected as a duplicate

Still open

Whether the build appears in your TestFlight app is a separate, portal-side question. This fixes the versioning, not tester-group assignment. Aligning the companion's marketing version with the Mac app's 0.3.0 is deliberately not done here, because it would move the version string backwards.

The TestFlight build number never reached the bundle. xcodegen's default for
CFBundleVersion is the literal "1", and because `info.path` sets INFOPLIST_FILE
Xcode only substitutes $(...) references in that file, so the
CURRENT_PROJECT_VERSION that build-ios-testflight.sh passes on the archive
command line was silently discarded. Confirmed against the one ipa that has
actually shipped (run 30574301994): it reports 1.0 (1), not the run id.

That is worse than a wrong label. App Store Connect recorded build 1 under
version 1.0, so the next upload would have been rejected as a duplicate bundle
version. The lane worked exactly once and was then blocked.

Both plists now reference the build settings, so the injected number reaches
the app and the widget together, which App Store validation requires them to
match on. MARKETING_VERSION moves 0.1 -> 1.0 to match the record that already
exists in App Store Connect rather than pushing the version string backwards.

The pre-upload verification checked entitlements but never the version, which
is why this shipped. It now reads CFBundleVersion back out of the signed app
and the signed appex and refuses to upload when either does not match the
number the run computed.

Also adds a version row to the phone, on both the pairing screen and the
workspace list. The app previously displayed nothing about itself, so there
was no way from the phone to tell which build was installed. The row is
selectable so the build number can be copied and compared against a run.

Verified by building with CURRENT_PROJECT_VERSION=424242: app and widget both
report 1.0 (424242). Before this change both reported 1.
@arzafran
arzafran merged commit 99ea65c into main Jul 31, 2026
11 checks passed
@arzafran
arzafran deleted the fix/ios-companion-bundle-version branch July 31, 2026 14:54
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