Skip to content

Fix iOS TestFlight build: remove hardcoded signing identity, clean up plist injection#411

Merged
PureWeen merged 3 commits intomainfrom
fix/ios-signing-identity
Mar 20, 2026
Merged

Fix iOS TestFlight build: remove hardcoded signing identity, clean up plist injection#411
PureWeen merged 3 commits intomainfrom
fix/ios-signing-identity

Conversation

@jfversluis
Copy link
Copy Markdown
Collaborator

@jfversluis jfversluis commented Mar 20, 2026

Problem

The iOS build has been failing on TestFlight CI (run #23331578098) with:

Apple Development: Jakub Florkowski (8MT3Q77PP8): no identity found
error MSB3073: codesign --force --sign "Apple Development: Jakub Florkowski (8MT3Q77PP8)" ... exited with code 1.

Root Cause

The csproj had a post-build target (InjectIOSPrivacyKeys) with a hardcoded codesign exec using Jakub Florkowski's signing identity. This was part of a workaround that re-injected NS*UsageDescription privacy keys into Info.plist after build, then re-signed the app.

Fix

Removed the entire PlistBuddy injection mechanism (both InjectMacCatalystPrivacyKeys and InjectIOSPrivacyKeys targets + the hardcoded codesign).

The injection was a workaround for an old MAUI behavior that stripped NS*UsageDescription keys from the output Info.plist. This is no longer the case — verified with a fully clean build (rm -rf bin/ obj/) on .NET 10 that the CompileAppManifest task in dotnet/macios now preserves all source plist keys.

The privacy keys (NSMicrophoneUsageDescription, NSSpeechRecognitionUsageDescription) are already defined in both Platforms/iOS/Info.plist and Platforms/MacCatalyst/Info.plist and survive the build pipeline untouched.

Verification

  • ✅ Full clean build (bin/ + obj/ nuked) on Mac Catalyst — 0 errors
  • ✅ Privacy keys present in output .app/Contents/Info.plist without any injection
  • ✅ Confirmed CompileAppManifest source code reads full source plist and doesn't strip NS* keys

jfversluis and others added 3 commits March 20, 2026 14:05
…ean up plist targets

The iOS build was failing because InjectIOSPrivacyKeys had a hardcoded
codesign exec using 'Apple Development: Jakub Florkowski (8MT3Q77PP8)',
which doesn't exist in the CI keychain (should be Gerald Versluis). The
manual codesign is unnecessary — dotnet publish re-signs after Build
targets complete.

Changes:
- Remove the hardcoded codesign --force --sign exec from csproj
- Merge duplicate InjectMacCatalystPrivacyKeys + InjectIOSPrivacyKeys
  into a single _InjectPrivacyKeys target with conditional plist path
- Extract privacy description strings into shared properties (DRY)
- Extract plist path into a property to reduce line length

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… plist targets

The iOS build was failing because InjectIOSPrivacyKeys had a hardcoded
codesign exec using 'Apple Development: Jakub Florkowski (8MT3Q77PP8)',
which doesn't exist in the CI keychain (should be Gerald Versluis's
identity passed via -p:CodesignKey). The manual codesign is unnecessary
because dotnet publish re-signs the app after Build targets complete.

Note: the PlistBuddy injection IS still required — verified that MAUI
still strips NS*UsageDescription keys from the output Info.plist in
.NET 10, even though they exist in the source Platforms/*/Info.plist.

Changes:
- Remove the hardcoded codesign --force --sign exec from csproj
- Merge duplicate InjectMacCatalystPrivacyKeys + InjectIOSPrivacyKeys
  into a single _InjectPrivacyKeys target with conditional plist path
- Extract privacy description strings into shared properties (DRY)
- Extract plist path into a property to reduce line length
- Update comment to clarify why injection is still needed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The _InjectPrivacyKeys target (and the earlier InjectMacCatalystPrivacyKeys
+ InjectIOSPrivacyKeys targets) was a workaround for an old MAUI behavior
that stripped NS*UsageDescription keys from Info.plist during build.

Verified with a fully clean build (rm -rf bin/ obj/) on .NET 10 that the
CompileAppManifest task in dotnet/macios now preserves all keys from the
source Platforms/*/Info.plist — the post-build PlistBuddy injection is
no longer needed.

The privacy keys (NSMicrophoneUsageDescription, NSSpeechRecognitionUsageDescription)
are already defined in both Platforms/iOS/Info.plist and
Platforms/MacCatalyst/Info.plist and survive the build pipeline.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen
Copy link
Copy Markdown
Owner

PR #411 Review — Fix iOS TestFlight build: remove hardcoded signing identity, clean up plist injection

CI: ⚠️ No checks configured on this branch
Prior reviews: None
Models: claude-opus-4.6 ×2, claude-sonnet-4.6, gemini-3-pro-preview, gpt-5.3-codex (5/5 completed)


Summary

Pure deletion PR (22 lines removed, 0 added) — removes two MSBuild post-build targets from PolyPilot.csproj:

  • InjectMacCatalystPrivacyKeys — PlistBuddy injection of NSMicrophoneUsageDescription + NSSpeechRecognitionUsageDescription into the Mac Catalyst output Contents/Info.plist
  • InjectIOSPrivacyKeys — same injection for iOS output Info.plist, plus a codesign --force --sign "Apple Development: Jakub Florkowski (8MT3Q77PP8)" re-sign step

Findings (Consensus Filter: 2+ models required)

None. 5/5 models confirmed the change is correct and safe.


Analysis

Hardcoded codesign removal — correct. The codesign --force --sign "Apple Development: Jakub Florkowski (8MT3Q77PP8)" was the direct cause of the CI failure (no identity found). Developer-specific signing identities must never be hardcoded in a shared csproj. Normal MAUI builds handle code signing via MSBuild properties (CodesignKey, automatic signing) or the Xcode provisioning profile. Additionally, this command hardcoded obj/Debug/$(TargetFramework)/ios-arm64/Entitlements.xcent — meaning it would attempt to read Debug entitlements even during Release/TestFlight builds where that path doesn't exist.

PlistBuddy injection removal — correct. Verified that both privacy keys are present in the source files:

  • Platforms/iOS/Info.plist:35,37NSSpeechRecognitionUsageDescription + NSMicrophoneUsageDescription
  • Platforms/MacCatalyst/Info.plist:41,43 — same ✅

The injection was a workaround for an older MAUI behavior where CompileAppManifest stripped NS*UsageDescription keys. This is no longer the case on .NET 10 / MAUI 10.0.41 — CompileAppManifest merges all source Info.plist keys into the output bundle. The privacy strings will appear correctly in the output IPA/app without post-build injection.

App Store compliance risk: None — the strings remain in the source plists and will flow through the standard build pipeline.


Test Coverage

This PR modifies only the build system (MSBuild targets). No source code changed; no unit tests needed.


Verdict: ✅ Approve

The change correctly removes a developer-specific signing identity that was blocking CI for all non-Jakub developers, along with the now-redundant plist injection workaround it required. Clean deletion with no regressions.

Co-reviewed by: Copilot 223556219+Copilot@users.noreply.github.com

@PureWeen PureWeen merged commit 865aa44 into main Mar 20, 2026
@PureWeen PureWeen deleted the fix/ios-signing-identity branch March 20, 2026 14:42
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.

2 participants