Repository navigation
Add iOS App Store production lane - #7644
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds iOS App Store production submission tooling and documentation, updates iOS upload scripts for an ChangesiOS App Store production lane
Web billing/pricing App Store gating
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 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 SummaryAdds a production iOS App Store lane (
Confidence Score: 5/5Safe to merge. App Store compliance gating is correctly implemented and validated by new tests across both the billing checkout redirect and the pricing page CTA surfaces. The App Store detection function is centralized in billing.ts and consistently consumed by both the checkout route and the pricing page. The upload script correctly gates --external and --auto-version for the appstore lane, fixes a pre-existing set -e edge case in entitlement verification, and adds an IPA scan for founders-edition strings. The CI workflow is manual-only, serialized, and validates provisioning profile entitlements before any upload. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant iOS as iOS App
participant WEB as /api/billing/checkout
participant Pricing as /app-pricing
participant Stack as Stack/Stripe
iOS->>WEB: "GET ?plan=pro&cmux_distribution=appstore"
WEB->>WEB: isAppStoreDistributionMode() true
WEB-->>iOS: "307 redirect to /app-pricing?billing=unavailable"
Note over Stack: Stack/Stripe never called
iOS->>Pricing: "GET ?cmux_app=1&cmux_distribution=appstore"
Pricing->>Pricing: "appStorePaymentGated = true"
Pricing-->>iOS: DisabledButton for all CTAs
iOS->>Pricing: "GET ?cmux_app=1"
Pricing->>Pricing: "appStorePaymentGated = false"
Pricing-->>iOS: PrimaryLink to checkout
iOS->>WEB: "GET ?plan=pro"
WEB->>Stack: checkoutStackServerApp() proceed
%%{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"}}}%%
sequenceDiagram
participant iOS as iOS App
participant WEB as /api/billing/checkout
participant Pricing as /app-pricing
participant Stack as Stack/Stripe
iOS->>WEB: "GET ?plan=pro&cmux_distribution=appstore"
WEB->>WEB: isAppStoreDistributionMode() true
WEB-->>iOS: "307 redirect to /app-pricing?billing=unavailable"
Note over Stack: Stack/Stripe never called
iOS->>Pricing: "GET ?cmux_app=1&cmux_distribution=appstore"
Pricing->>Pricing: "appStorePaymentGated = true"
Pricing-->>iOS: DisabledButton for all CTAs
iOS->>Pricing: "GET ?cmux_app=1"
Pricing->>Pricing: "appStorePaymentGated = false"
Pricing-->>iOS: PrimaryLink to checkout
iOS->>WEB: "GET ?plan=pro"
WEB->>Stack: checkoutStackServerApp() proceed
Reviews (7): Last reviewed commit: "Localize App Store billing unavailable c..." | Re-trigger Greptile |
| SCREENSHOTS_DIR="${IOS_APPSTORE_SCREENSHOTS_DIR:-$IOS_DIR/AppStoreReview/screenshots}" | ||
| REVIEW_NOTES="$IOS_DIR/AppStoreReview/review-notes.md" | ||
| CHECKLIST="$IOS_DIR/AppStoreReview/metadata-screenshots-checklist.md" | ||
| SCREENSHOT_DEVICE_TYPES=(IPHONE_65 IPAD_PRO_3GEN_129) |
There was a problem hiding this comment.
--screenshot-device-type appends to the pre-populated default list rather than replacing it. If either default device type (IPHONE_65 or IPAD_PRO_3GEN_129) is passed explicitly, that device type gets validated twice, producing duplicate output. Clearing the defaults on first explicit use would match expected CLI behaviour.
| SCREENSHOT_DEVICE_TYPES=(IPHONE_65 IPAD_PRO_3GEN_129) | |
| SCREENSHOT_DEVICE_TYPES=(IPHONE_65 IPAD_PRO_3GEN_129) | |
| _SCREENSHOT_DEVICE_TYPES_EXPLICIT=0 |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| --wait-build) WAIT_BUILD=1; shift ;; | ||
| --metadata-dir) METADATA_DIR="${2:-}"; shift 2 ;; | ||
| --screenshots-dir) SCREENSHOTS_DIR="${2:-}"; shift 2 ;; | ||
| --screenshot-device-type) SCREENSHOT_DEVICE_TYPES+=("${2:-}"); shift 2 ;; |
There was a problem hiding this comment.
With the companion initialisation above, reset the defaults on the first explicit
--screenshot-device-type argument so that passing a specific type doesn't duplicate validation of any pre-populated default.
| --screenshot-device-type) SCREENSHOT_DEVICE_TYPES+=("${2:-}"); shift 2 ;; | |
| --screenshot-device-type) [[ "$_SCREENSHOT_DEVICE_TYPES_EXPLICIT" -eq 0 ]] && SCREENSHOT_DEVICE_TYPES=(); _SCREENSHOT_DEVICE_TYPES_EXPLICIT=1; SCREENSHOT_DEVICE_TYPES+=("${2:-}"); shift 2 ;; |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
df37eef to
bdc7b60
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 @.asc/workflow.json:
- Around line 11-13: The readiness workflow step is missing the wait-for-build
behavior, which can race App Store Connect ingestion. Update the `readiness`
command in the workflow to pass `--wait-build` to
`ios/scripts/validate-app-store-release.sh`, matching the usage in the README
and `ios-app-store.yml`. Keep the existing `--app`, `--version`,
`--build-number`, and `--strict` arguments intact while adding the new flag.
In @.github/workflows/ios-app-store.yml:
- Line 40: The job-level env entry for CMUX_BUILD_NUMBER_OUT_FILE uses
runner.temp, but the runner context is not available there. Move this variable
out of the top-level env and define it on the upload step instead, where
runner.temp is valid, so the build-number handoff used by the upload flow
resolves correctly.
In `@web/app/api/billing/checkout/route.ts`:
- Around line 311-333: The app-store distribution check is duplicated between
appStoreDistributionMode in the checkout route and the pricing page, so extract
the shared detection logic into a common helper under web/lib/billing. Refactor
the core condition to accept a generic key lookup function (instead of
NextRequest or Record directly), then have both appStoreDistributionMode call
sites delegate to that helper so the cmux_distribution and cmux_ios_app_store
rules stay in sync.
🪄 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: 19eaf8a8-2776-4f85-962f-dce1caba4261
📒 Files selected for processing (13)
.asc/workflow.json.github/workflows/ios-app-store.ymlios/AppStoreReview/README.mdios/AppStoreReview/metadata-screenshots-checklist.mdios/AppStoreReview/review-notes.mdios/README.mdios/scripts/upload-app-store.shios/scripts/upload-testflight.shios/scripts/validate-app-store-release.shweb/app/api/billing/checkout/route.tsweb/app/app-pricing/page.tsxweb/tests/app-pricing-page.test.tsxweb/tests/billing-checkout-route.test.ts
bdc7b60 to
985aa87
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/app/app-pricing/page.tsx (1)
118-132: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
billingExternalmessage is misleading for App Store users with Stripe-managed billing.When
snapshot.isProis true,billingManagement === "stripe", andappStorePaymentGatedis true, the conditionsnapshot.billingManagement === "stripe" && !appStorePaymentGatedevaluates to false, so the UI falls through topricing.billingExternal("Your subscription is managed by our previous billing system. Contact support to make changes."). For a Pro user whose subscription is actively managed by Stripe, this is factually incorrect — it implies a legacy/external system they don't use.Consider adding a dedicated App Store billing-management message (e.g., "Billing management is not available in this mode. Contact support to make changes.") with entries in all supported locales, or reusing
billingUnavailableif the "try again later" phrasing is acceptable.💡 Suggested approach
Add a new key to
web/messages/en.jsonandweb/messages/ja.json:"billingAppStoreManaged": "Billing management is not available in this mode. Contact support to make changes."Then update the Pro card condition:
{snapshot.billingManagement === "stripe" && !appStorePaymentGated ? ( <SecondaryLink href="/api/billing/portal"> {pricing.manageBilling} </SecondaryLink> ) : appStorePaymentGated ? ( - <p className="text-sm leading-6 text-muted"> - {pricing.billingExternal} - </p> + <p className="text-sm leading-6 text-muted"> + {pricing.billingAppStoreManaged} + </p> ) : ( <p className="text-sm leading-6 text-muted"> {pricing.billingExternal} </p> )}🤖 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 `@web/app/app-pricing/page.tsx` around lines 118 - 132, The Pro billing state in the pricing page is falling through to the legacy `pricing.billingExternal` copy when `snapshot.isPro`, `snapshot.billingManagement === "stripe"`, and `appStorePaymentGated` are all true, which misstates the user’s billing setup. Update the conditional in `app-pricing/page.tsx` so App Store-gated Stripe-managed users render a dedicated App Store billing message instead of `billingExternal`, and add the new localized message key to the message files used by `pricing` (for example `en.json` and `ja.json`). Keep the existing `manageBilling` and `billingUnavailable` paths unchanged for their current cases.
♻️ Duplicate comments (1)
.github/workflows/ios-app-store.yml (1)
40-40: 🩺 Stability & Availability | 🔴 CriticalFix:
runnercontext is not available in job-levelenvblocks.
${{ runner.temp }}on line 40 is evaluated in the job-levelenvblock, where therunnercontext is not available (onlygithub,inputs,matrix,needs,secrets,strategy,varsare). This causesCMUX_BUILD_NUMBER_OUT_FILEto resolve to an incorrect path, breaking the upload step's build-number handoff. Move it to the step-levelenvof the upload step whererunner.tempis valid.🔧 Proposed fix: move env var to step level
ASC_APP_ID: ${{ vars.IOS_APPSTORE_APP_ID }} INPUT_BUILD_NUMBER: ${{ github.event.inputs.build_number }} INPUT_COPY_METADATA_FROM: ${{ github.event.inputs.copy_metadata_from }} INPUT_SUBMIT_FOR_REVIEW: ${{ github.event.inputs.submit_for_review }} - CMUX_BUILD_NUMBER_OUT_FILE: ${{ runner.temp }}/cmux-final-appstore-build-number.txt steps:And add step-level
envto the upload step:- name: Archive, export, and upload production build id: upload + env: + CMUX_BUILD_NUMBER_OUT_FILE: ${{ runner.temp }}/cmux-final-appstore-build-number.txt run: | set -euo pipefail ARGS=(--signing manual)🤖 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 @.github/workflows/ios-app-store.yml at line 40, The job-level env in ios-app-store workflow is using runner.temp for CMUX_BUILD_NUMBER_OUT_FILE, but the runner context is not available there. Move CMUX_BUILD_NUMBER_OUT_FILE out of the job-wide env block and set it on the specific upload step’s step-level env instead, where runner.temp is valid, so the build-number handoff path resolves correctly.Source: Linters/SAST tools
🤖 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.
Outside diff comments:
In `@web/app/app-pricing/page.tsx`:
- Around line 118-132: The Pro billing state in the pricing page is falling
through to the legacy `pricing.billingExternal` copy when `snapshot.isPro`,
`snapshot.billingManagement === "stripe"`, and `appStorePaymentGated` are all
true, which misstates the user’s billing setup. Update the conditional in
`app-pricing/page.tsx` so App Store-gated Stripe-managed users render a
dedicated App Store billing message instead of `billingExternal`, and add the
new localized message key to the message files used by `pricing` (for example
`en.json` and `ja.json`). Keep the existing `manageBilling` and
`billingUnavailable` paths unchanged for their current cases.
---
Duplicate comments:
In @.github/workflows/ios-app-store.yml:
- Line 40: The job-level env in ios-app-store workflow is using runner.temp for
CMUX_BUILD_NUMBER_OUT_FILE, but the runner context is not available there. Move
CMUX_BUILD_NUMBER_OUT_FILE out of the job-wide env block and set it on the
specific upload step’s step-level env instead, where runner.temp is valid, so
the build-number handoff path resolves correctly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 41776c9d-5b59-4b0f-aa79-23409ac7cfcd
📒 Files selected for processing (14)
.asc/workflow.json.github/workflows/ios-app-store.ymlios/AppStoreReview/README.mdios/AppStoreReview/metadata-screenshots-checklist.mdios/AppStoreReview/review-notes.mdios/README.mdios/scripts/upload-app-store.shios/scripts/upload-testflight.shios/scripts/validate-app-store-release.shweb/app/api/billing/checkout/route.tsweb/app/app-pricing/page.tsxweb/app/lib/billing.tsweb/tests/app-pricing-page.test.tsxweb/tests/billing-checkout-route.test.ts
There was a problem hiding this comment.
♻️ Duplicate comments (1)
.asc/workflow.json (1)
11-13: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
--wait-buildis missing from all three workflow stepsThe readiness step (Line 12) was previously flagged for missing
--wait-buildand marked as addressed in commit bdc7b60, but the current code does not include it. Thestage-dry-run(Line 24) andsubmit-dry-run(Line 36) steps also lack it.When
--build-numberis provided,validate-app-store-release.shcallsasc builds infoto resolve the build ID. Without--wait-build, this skipsasc builds waitand can race ASC ingestion — causing intermittent failures if the build hasn't finished processing. The README andios-app-store.ymlreportedly already use--wait-build; these workflow definitions should match.🔧 Proposed fix: add conditional --wait-build to readiness step
{ "name": "readiness", - "run": "set -- --app \"$APP_ID\" --version \"$VERSION\"; if [ -n \"${BUILD_NUMBER:-}\" ]; then set -- \"$@\" --build-number \"$BUILD_NUMBER\"; fi; if [ -n \"${STRICT_VALIDATE:-}\" ]; then set -- \"$@\" --strict; fi; ios/scripts/validate-app-store-release.sh \"$@\"" + "run": "set -- --app \"$APP_ID\" --version \"$VERSION\"; if [ -n \"${BUILD_NUMBER:-}\" ]; then set -- \"$@\" --build-number \"$BUILD_NUMBER\" --wait-build; fi; if [ -n \"${STRICT_VALIDATE:-}\" ]; then set -- \"$@\" --strict; fi; ios/scripts/validate-app-store-release.sh \"$@\"" }For the
stage-dry-runandsubmit-dry-runsteps, add--wait-buildalongside--build-number:- "run": "ios/scripts/validate-app-store-release.sh --app \"$APP_ID\" --version \"$VERSION\" --build-number \"$BUILD_NUMBER\" --copy-metadata-from \"$COPY_METADATA_FROM\" --stage-dry-run ${STRICT_VALIDATE:+--strict}" + "run": "ios/scripts/validate-app-store-release.sh --app \"$APP_ID\" --version \"$VERSION\" --build-number \"$BUILD_NUMBER\" --wait-build --copy-metadata-from \"$COPY_METADATA_FROM\" --stage-dry-run ${STRICT_VALIDATE:+--strict}"- "run": "ios/scripts/validate-app-store-release.sh --app \"$APP_ID\" --version \"$VERSION\" --build-number \"$BUILD_NUMBER\" --submit-dry-run ${STRICT_VALIDATE:+--strict}" + "run": "ios/scripts/validate-app-store-release.sh --app \"$APP_ID\" --version \"$VERSION\" --build-number \"$BUILD_NUMBER\" --wait-build --submit-dry-run ${STRICT_VALIDATE:+--strict}"Run the following script to verify
--wait-buildusage across the codebase:#!/bin/bash # Description: Verify --wait-build usage in README, ios-app-store.yml, and workflow.json rg -n --context 2 'wait-build|wait_build|WAIT_BUILD' ios/AppStoreReview/README.md .github/workflows/ios-app-store.yml .asc/workflow.json ios/scripts/validate-app-store-release.shAlso applies to: 23-24, 35-36
🤖 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 @.asc/workflow.json around lines 11 - 13, The workflow step commands for readiness, stage-dry-run, and submit-dry-run are missing the conditional --wait-build flag, so update each step’s run command in workflow.json to pass --wait-build whenever --build-number is set. Keep the existing argument-building pattern in place, and align these steps with the behavior already used by ios/scripts/validate-app-store-release.sh and the documented ios-app-store workflow so build ingestion is waited on before resolving the build ID.
🤖 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.
Duplicate comments:
In @.asc/workflow.json:
- Around line 11-13: The workflow step commands for readiness, stage-dry-run,
and submit-dry-run are missing the conditional --wait-build flag, so update each
step’s run command in workflow.json to pass --wait-build whenever --build-number
is set. Keep the existing argument-building pattern in place, and align these
steps with the behavior already used by
ios/scripts/validate-app-store-release.sh and the documented ios-app-store
workflow so build ingestion is waited on before resolving the build ID.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 613fd351-7e6b-41be-954b-ddff45fc84ed
📒 Files selected for processing (1)
.asc/workflow.json
|
@codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
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 `@web/messages/de.json`:
- Around line 3465-3467: The German pricing copy in billingUnavailable uses
informal address, which deviates from the established tone in de.json. Update
the translation in the pricing.billingUnavailable entry to use formal Sie-form
wording, and keep the phrasing consistent with the existing locale convention
used throughout de.json.
🪄 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: 627f06e9-8971-4a02-a373-d429230968ee
📒 Files selected for processing (24)
.asc/workflow.json.github/workflows/ios-app-store.ymlPackages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/SetupHelpGateContent.swiftPackages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/SetupHelpGateContentTests.swiftios/scripts/upload-testflight.shios/scripts/validate-app-store-release.shweb/messages/ar.jsonweb/messages/bs.jsonweb/messages/da.jsonweb/messages/de.jsonweb/messages/es.jsonweb/messages/fr.jsonweb/messages/it.jsonweb/messages/km.jsonweb/messages/ko.jsonweb/messages/no.jsonweb/messages/pl.jsonweb/messages/pt-BR.jsonweb/messages/ru.jsonweb/messages/th.jsonweb/messages/tr.jsonweb/messages/uk.jsonweb/messages/zh-CN.jsonweb/messages/zh-TW.json
| "pricing": { | ||
| "billingUnavailable": "Die Abrechnung ist derzeit nicht verfügbar. Bitte versuche es später erneut." | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use formal address in de.json per the locale's established convention.
The string "Bitte versuche es später erneut" uses the informal du imperative ("versuche"). Per the repo's locale tone convention, de.json should use formal address (Sie form). The formal imperative would be "Bitte versuchen Sie es später erneut."
Based on learnings, de.json should use formal address; only flag when a given locale file deviates from its own established tone/addressing convention.
🛡️ Proposed fix for formal address
- "billingUnavailable": "Die Abrechnung ist derzeit nicht verfügbar. Bitte versuche es später erneut."
+ "billingUnavailable": "Die Abrechnung ist derzeit nicht verfügbar. Bitte versuchen Sie es später erneut."📝 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.
| "pricing": { | |
| "billingUnavailable": "Die Abrechnung ist derzeit nicht verfügbar. Bitte versuche es später erneut." | |
| }, | |
| "pricing": { | |
| "billingUnavailable": "Die Abrechnung ist derzeit nicht verfügbar. Bitte versuchen Sie es später erneut." | |
| }, |
🤖 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 `@web/messages/de.json` around lines 3465 - 3467, The German pricing copy in
billingUnavailable uses informal address, which deviates from the established
tone in de.json. Update the translation in the pricing.billingUnavailable entry
to use formal Sie-form wording, and keep the phrasing consistent with the
existing locale convention used throughout de.json.
Source: Learnings
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 411ff15. Configure here.
| plutil -p "$ent" >&2 || true | ||
| rm -rf "$workdir" | ||
| return 1 | ||
| fi |
There was a problem hiding this comment.
Beta IPA Apple Sign-In gate
Medium Severity
verify_ipa_aps_environment_production now requires com.apple.developer.applesignin to be Default for every lane, but the TestFlight workflow only validates aps-environment on the beta provisioning profile. If the beta profile does not authorize Sign in with Apple, re-sign can drop that entitlement and uploads that previously passed will start failing at the new check.
Reviewed by Cursor Bugbot for commit 411ff15. Configure here.
| enterprise: ( | ||
| enterprise: appStorePaymentGated ? ( | ||
| <DisabledButton size="compact">{pricing.billingUnavailable}</DisabledButton> | ||
| ) : ( |
There was a problem hiding this comment.
App Store pending banner link
Low Severity
App Store distribution mode disables checkout and portal links on the pricing cards, but appPricingBanner still returns a welcome=pending action pointing at /api/billing/confirm without checking isAppStoreDistributionMode. A pending-checkout banner in an App Store webview can still expose a billing-management URL.
Reviewed by Cursor Bugbot for commit 411ff15. Configure here.


Summary
Testing
Issues
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
Medium Risk
Touches release automation (signing, upload, optional App Review submit) and billing/checkout behavior for App Store distribution; mistakes could block releases or affect payment flows in the iOS webview.
Overview
Adds a production iOS App Store path for
com.cmuxterm.appalongside the existing TestFlight beta lane:--lane appstore(viaupload-app-store.sh), stricter IPA checks (aps-environment, Sign in with Apple, no Founders Edition links), manual CI workflow with optional metadata staging and guarded review submit, plusvalidate-app-store-release.sh,.ascworkflows, andios/AppStoreReview/notes/checklists.App Store compliance removes the Mac setup help “Download cmux” external link (with tests), gates embedded web billing when
cmux_distribution=appstore(disabled CTAs on/app-pricing, checkout redirect before Stripe/Stack), and adds localizedbillingUnavailablecopy.Reviewed by Cursor Bugbot for commit 411ff15. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds a production iOS App Store lane for
com.cmuxterm.appwith end-to-end App Store Connect validation and optional submission. Also blocks external purchase links for App Store builds across the app and embedded web, with CI/IPA checks to enforce it.New Features
--lane appstoreinios/scripts/upload-testflight.sh(viaios/scripts/upload-app-store.sh) sets bundle id/display name/profile, verifies the archive’s bundle id, enforcesaps-environment=productionandcom.apple.developer.applesignin=Defaultduring re-sign, disables--external/--auto-version, skips TestFlight notes/group assignment, and scans the IPA for “Founders Edition” links.main, serialized, validates secrets and provisioning profile, and outputs the final build number..asc/workflow.jsonandios/scripts/validate-app-store-release.shrun readiness checks (asc validate), validate metadata/screenshots, support--wait-build,--stage-dry-run,--submit-dry-run, and guarded submit with--confirm.ios/AppStoreReview/with reviewer notes and a metadata/screenshots checklist./app-pricing, and/api/billing/checkoutredirects whencmux_distribution=appstore(orcmux_ios_app_store=1); tests cover both surfaces. Localized the “billing unavailable” message across supported languages.Migration
IOS_APPSTORE_APP_IDand secretIOS_APPSTORE_PROVISIONING_PROFILE_BASE64(profile forcom.cmuxterm.app, withaps-environment=productionandcom.apple.developer.applesignin=Default).cmux_app=1&cmux_distribution=appstoreto enforce billing gating.Written for commit 411ff15. Summary will update on new commits.
Summary by CodeRabbit