Repository navigation
Fix iOS framework MinimumOSVersion packaging - #8131
azooz2003-bit wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe iOS TestFlight upload script now resolves, stamps, signs, and validates embedded frameworks’ ChangesiOS framework metadata handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant ExportedApp
participant UploadScript
participant NestedFramework
participant Codesign
participant AppStoreConnect
UploadScript->>ExportedApp: resolve MinimumOSVersion
UploadScript->>NestedFramework: stamp missing MinimumOSVersion
UploadScript->>Codesign: re-sign nested framework
UploadScript->>UploadScript: verify IPA framework metadata
UploadScript->>AppStoreConnect: upload validated IPA
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error)
✅ Passed checks (24 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR fixes an Apple rejection caused by embedded iOS frameworks (
Confidence Score: 4/5Safe to merge; the stamp-then-resign ordering is correct, the post-zip gate runs on both signing paths, and the test exercises the full manual-resign flow end-to-end. The logic for resolving, stamping, re-signing, and verifying MinimumOSVersion is sound and the function ordering (stamp → sign nested → sign app → verify → re-zip → gate) is correct. The only gap is in verify_ipa_framework_minimum_os_versions: with set -euo pipefail active, a non-zero exit from the inline python3 call terminates the function before the rm -rf cleanup, leaving extracted IPA contents on disk. Every other verification function in the file guards cleanup explicitly. This is not a correctness issue for the business logic but is an inconsistency worth fixing. The verify_ipa_framework_minimum_os_versions function in ios/scripts/upload-testflight.sh warrants a close look at its cleanup path when python3 exits non-zero. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Export IPA via xcodebuild -exportArchive] --> B{SIGNING mode?}
B -->|manual| C[Extract IPA to resign dir]
C --> D[resolve_ios_minimum_os_version\nfrom app Info.plist or Shared.xcconfig]
D --> E[stamp_ios_framework_minimum_os_versions\npatch missing MinimumOSVersion in each *.framework/Info.plist]
E --> F[Merge entitlements\nbaseline + profile + Release]
F --> G[Re-sign nested frameworks\ncodesign --force --sign RESIGN_IDENTITY]
G --> H[Re-sign top-level .app\ncodesign --force --sign + entitlements]
H --> I[verify codesign --verify --strict]
I --> J[Re-zip into resigned IPA]
J --> K
B -->|automatic| K[verify_ipa_framework_minimum_os_versions\nunzip IPA, check all *.framework/Info.plist for MinimumOSVersion]
K -->|missing key| L[exit 1 — refuse upload]
K -->|all present| M[verify_ipa_bundle_identity\nupload to App Store Connect]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Export IPA via xcodebuild -exportArchive] --> B{SIGNING mode?}
B -->|manual| C[Extract IPA to resign dir]
C --> D[resolve_ios_minimum_os_version\nfrom app Info.plist or Shared.xcconfig]
D --> E[stamp_ios_framework_minimum_os_versions\npatch missing MinimumOSVersion in each *.framework/Info.plist]
E --> F[Merge entitlements\nbaseline + profile + Release]
F --> G[Re-sign nested frameworks\ncodesign --force --sign RESIGN_IDENTITY]
G --> H[Re-sign top-level .app\ncodesign --force --sign + entitlements]
H --> I[verify codesign --verify --strict]
I --> J[Re-zip into resigned IPA]
J --> K
B -->|automatic| K[verify_ipa_framework_minimum_os_versions\nunzip IPA, check all *.framework/Info.plist for MinimumOSVersion]
K -->|missing key| L[exit 1 — refuse upload]
K -->|all present| M[verify_ipa_bundle_identity\nupload to App Store Connect]
Reviews (1): Last reviewed commit: "Fix iOS framework minimum OS packaging" | Re-trigger Greptile |
| python3 - "$app" <<'PY' | ||
| import plistlib | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| app = Path(sys.argv[1]) | ||
| frameworks = app / "Frameworks" | ||
| bad = [] | ||
|
|
||
| if frameworks.is_dir(): | ||
| for plist_path in sorted(frameworks.glob("*.framework/Info.plist")): | ||
| try: | ||
| info = plistlib.loads(plist_path.read_bytes()) | ||
| except Exception as exc: | ||
| bad.append(f"{plist_path.relative_to(app)}: unreadable Info.plist ({exc})") | ||
| continue | ||
| value = info.get("MinimumOSVersion") | ||
| if not isinstance(value, str) or not value.strip(): | ||
| bad.append(f"{plist_path.relative_to(app)}: MinimumOSVersion is missing or empty") | ||
|
|
||
| if bad: | ||
| print( | ||
| "error: iOS framework metadata is incomplete; App Store Connect rejects embedded frameworks without MinimumOSVersion", | ||
| file=sys.stderr, | ||
| ) | ||
| for item in bad: | ||
| print(f"error: {item}", file=sys.stderr) | ||
| raise SystemExit(1) | ||
| PY | ||
| status=$? | ||
| rm -rf "$workdir" | ||
| return "$status" |
There was a problem hiding this comment.
Temp dir leaked when Python MinimumOSVersion check fails
With set -euo pipefail active, if python3 exits 1 (missing MinimumOSVersion detected), Bash's set -e terminates the function immediately. The status=$? and rm -rf "$workdir" lines are never reached, leaving the extracted IPA contents in a temp dir. Every other verification function in this file (e.g. verify_ipa_aps_environment_production, verify_ipa_bundle_identity) explicitly guards cleanup in every error branch rather than relying on the status=$? pattern after a bare command that can fail. When the gate fires on a bad IPA, the leaked dir can hold tens of MB of decompressed app payload on the runner's disk.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ios/scripts/upload-testflight.sh`:
- Line 179: Update the parameter expansion in the nested framework logging
statement to quote the app-path variable used for prefix removal, ensuring
pattern characters in its value are treated literally while preserving the
existing displayed relative path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: fd483dbe-4327-45a4-b64b-c7a753631124
📒 Files selected for processing (2)
ios/scripts/upload-testflight.shtests/test_ios_appstore_lane_identity.py
| PY | ||
| )" | ||
| if [[ "$changed" == "1" ]]; then | ||
| echo "stamped MinimumOSVersion=$minimum_os on nested framework: ${framework_info#$app/}" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Quote the variable inside the parameter expansion.
Expansions inside ${...} should be quoted so they are treated as literal strings rather than glob patterns. If the $app path happens to contain pattern characters like * or ?, leaving it unquoted can result in incorrect string truncation.
💻 Proposed fix
- echo "stamped MinimumOSVersion=$minimum_os on nested framework: ${framework_info#$app/}"
+ echo "stamped MinimumOSVersion=$minimum_os on nested framework: ${framework_info#"$app/"}"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| echo "stamped MinimumOSVersion=$minimum_os on nested framework: ${framework_info#$app/}" | |
| echo "stamped MinimumOSVersion=$minimum_os on nested framework: ${framework_info#"$app/"}" |
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 179-179: Expansions inside ${..} need to be quoted separately, otherwise they match as patterns.
(SC2295)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ios/scripts/upload-testflight.sh` at line 179, Update the parameter expansion
in the nested framework logging statement to quote the app-path variable used
for prefix removal, ensuring pattern characters in its value are treated
literally while preserving the existing displayed relative path.
Source: Linters/SAST tools
|
Closing because the implementation is architecturally superseded by current main at 22f9e5e; merging this old head would restore obsolete transport code, and no unique required capability remains. |
Summary
MinimumOSVersionon embedded iOS frameworks during the manual TestFlight/App Store re-sign pathMinimumOSVersionfails before App Store ConnectIroh.frameworkembedded in the IPAFailure Evidence
Archive, export, and upload to TestFlight267ed6ceea9d396e1d1d55770295f59fc3ebd5f4Invalid MinimumOSVersion/Missing Info.plist valueforcmux.app/Frameworks/Iroh.frameworkTesting
bash -n ios/scripts/upload-testflight.shgit diff --check origin/main...HEADpython3 tests/test_ios_appstore_lane_identity.pyNo runtime app reload: this only changes CI/CD packaging scripts and tests.
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Fixes App Store/TestFlight rejection by stamping MinimumOSVersion on embedded iOS frameworks and re-signing nested frameworks before the app in the manual signing path. Adds a pre-upload check to fail CI early; packaging scripts and tests only, no runtime impact.
Shared.xcconfig).Written for commit a7e8212. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
Tests