feat: make App Store Connect API key optional for iOS builds#527
Conversation
Users who want to build an IPA for download via Capgo output upload link no longer need to provide APPLE_KEY_ID, APPLE_ISSUER_ID, and APPLE_KEY_CONTENT. These are now only required for TestFlight upload. Mirrors the pattern from PR #520 which made PLAY_CONFIG_JSON optional for Android builds.
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR makes App Store Connect API key credentials optional by introducing conditional validation logic. When credentials are absent, it prompts users to either provide Apple key parameters for auto-upload or enable alternative upload mechanisms via BUILD_OUTPUT_UPLOAD_ENABLED or SKIP_BUILD_NUMBER_BUMP flags. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
Makes App Store Connect API key credentials optional for iOS build flows when the user is only generating an IPA for download (via output upload), aligning iOS behavior with the earlier Android “optional store upload config” change.
Changes:
- Updates iOS build request validation to allow missing
APPLE_*API key fields when output upload is enabled and build-number bumping is skipped. - Updates
build credentials save --platform iosvalidation to warn (instead of hard-fail) when the App Store Connect API key is omitted and output upload is enabled. - Adjusts iOS credential-save example output to reflect that App Store Connect API key flags are optional.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/build/request.ts | Conditional iOS build validation: App Store Connect API key is optional depending on output upload + skip-build-number-bump. |
| src/build/credentials-command.ts | Conditional iOS credential-save validation and updated CLI guidance when API key is omitted. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| missingCreds.push('--apple-key/--apple-key-id/--apple-issuer-id OR --output-upload (Build has no output destination - enable either TestFlight upload or Capgo download link)') | ||
| } | ||
| else { | ||
| log.warn('⚠️ App Store Connect API key not provided - builds will succeed but cannot auto-upload to TestFlight') |
There was a problem hiding this comment.
When the App Store Connect API key is omitted but --output-upload is enabled, this warns only about TestFlight upload. Builds will also fail later unless build-number auto-increment is disabled (per request validation requiring --skip-build-number-bump). Consider warning here that the user must set --skip-build-number-bump (either when saving or when running the build) when no API key is provided.
| log.warn('⚠️ App Store Connect API key not provided - builds will succeed but cannot auto-upload to TestFlight') | |
| log.warn('⚠️ App Store Connect API key not provided - builds will succeed but cannot auto-upload to TestFlight') | |
| log.warn(' If you continue without an API key, you must also set --skip-build-number-bump when saving credentials or running the build, otherwise builds will fail during App Store Connect validation.') |
| const hasAppleApiKey = mergedCredentials.APPLE_KEY_ID && mergedCredentials.APPLE_ISSUER_ID && mergedCredentials.APPLE_KEY_CONTENT | ||
| if (!hasAppleApiKey) { | ||
| if (mergedCredentials.BUILD_OUTPUT_UPLOAD_ENABLED !== 'true') { | ||
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (build has no output destination - enable either TestFlight upload or Capgo download link)') |
There was a problem hiding this comment.
The new combined missing-credentials message for iOS output destination doesn't mention the CLI flag users can actually set. Consider including --output-upload (and/or BUILD_OUTPUT_UPLOAD_ENABLED) so the error is actionable from the command line, similar to other messages in this block that include their --... equivalents.
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (build has no output destination - enable either TestFlight upload or Capgo download link)') | |
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (or --output-upload) (build has no output destination - enable either TestFlight upload or Capgo download link)') |
There was a problem hiding this comment.
✅ Already addressed in 99ce905 — the message now includes (or --output-upload):
APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (or --output-upload) (build has no output destination - ...)
| const hasAppleApiKey = mergedCredentials.APPLE_KEY_ID && mergedCredentials.APPLE_ISSUER_ID && mergedCredentials.APPLE_KEY_CONTENT | ||
| if (!hasAppleApiKey) { | ||
| if (mergedCredentials.BUILD_OUTPUT_UPLOAD_ENABLED !== 'true') { | ||
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (build has no output destination - enable either TestFlight upload or Capgo download link)') | ||
| } | ||
| else if (mergedCredentials.SKIP_BUILD_NUMBER_BUMP !== 'true') { | ||
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or --skip-build-number-bump (App Store Connect API key not provided - build numbers cannot be auto-incremented without it)') | ||
| } | ||
| else if (!silent) { | ||
| log.warn('⚠️ App Store Connect API key not provided - build will succeed but cannot auto-upload to TestFlight') | ||
| } |
There was a problem hiding this comment.
Grouping the App Store Connect API key fields into a single "APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT" requirement makes it hard to diagnose partial configuration (e.g., key id + issuer set but missing key content). Consider detecting partial presence and reporting which specific field(s) are missing, while still allowing the fully-missing-key optional path when --output-upload is enabled and build number bump is skipped.
| const hasAppleApiKey = mergedCredentials.APPLE_KEY_ID && mergedCredentials.APPLE_ISSUER_ID && mergedCredentials.APPLE_KEY_CONTENT | |
| if (!hasAppleApiKey) { | |
| if (mergedCredentials.BUILD_OUTPUT_UPLOAD_ENABLED !== 'true') { | |
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (build has no output destination - enable either TestFlight upload or Capgo download link)') | |
| } | |
| else if (mergedCredentials.SKIP_BUILD_NUMBER_BUMP !== 'true') { | |
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or --skip-build-number-bump (App Store Connect API key not provided - build numbers cannot be auto-incremented without it)') | |
| } | |
| else if (!silent) { | |
| log.warn('⚠️ App Store Connect API key not provided - build will succeed but cannot auto-upload to TestFlight') | |
| } | |
| const hasAppleKeyId = !!mergedCredentials.APPLE_KEY_ID | |
| const hasAppleIssuerId = !!mergedCredentials.APPLE_ISSUER_ID | |
| const hasAppleKeyContent = !!mergedCredentials.APPLE_KEY_CONTENT | |
| const anyAppleApiField = hasAppleKeyId || hasAppleIssuerId || hasAppleKeyContent | |
| const hasCompleteAppleApiKey = hasAppleKeyId && hasAppleIssuerId && hasAppleKeyContent | |
| if (!hasCompleteAppleApiKey) { | |
| if (anyAppleApiField) { | |
| const missingAppleFields: string[] = [] | |
| if (!hasAppleKeyId) | |
| missingAppleFields.push('APPLE_KEY_ID (or --apple-key-id)') | |
| if (!hasAppleIssuerId) | |
| missingAppleFields.push('APPLE_ISSUER_ID (or --apple-issuer-id)') | |
| if (!hasAppleKeyContent) | |
| missingAppleFields.push('APPLE_KEY_CONTENT (or --apple-key-content)') | |
| missingCreds.push(`Incomplete App Store Connect API key configuration – missing: ${missingAppleFields.join(', ')}`) | |
| } | |
| else { | |
| // No App Store Connect API key fields provided at all | |
| if (mergedCredentials.BUILD_OUTPUT_UPLOAD_ENABLED !== 'true') { | |
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or BUILD_OUTPUT_UPLOAD_ENABLED=true (build has no output destination - enable either TestFlight upload or Capgo download link)') | |
| } | |
| else if (mergedCredentials.SKIP_BUILD_NUMBER_BUMP !== 'true') { | |
| missingCreds.push('APPLE_KEY_ID/APPLE_ISSUER_ID/APPLE_KEY_CONTENT or --skip-build-number-bump (App Store Connect API key not provided - build numbers cannot be auto-incremented without it)') | |
| } | |
| else if (!silent) { | |
| log.warn('⚠️ App Store Connect API key not provided - build will succeed but cannot auto-upload to TestFlight') | |
| } | |
| } |
There was a problem hiding this comment.
Fixed in 067038a — the validation now distinguishes between "no API key fields" (optional path) and "partial API key" (always an error with specific missing fields listed). Added test coverage for both scenarios (2 of 3 fields present, 1 of 3 fields present).
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/build/credentials-command.ts`:
- Around line 290-292: Update the iOS example printed by the credentials command
so it includes the required --output-upload destination flag instead of implying
--apple-key alone is sufficient; modify the log.error messages around the iOS
example (the two log.error calls shown) to include a full example invocation
that contains --output-upload along with the optional --apple-key,
--apple-key-id, and --apple-issuer-id flags so copy-pasting will not trigger the
“no output destination” error.
- Around line 243-245: The warning emitted via log.warn that says builds will
succeed but cannot auto-upload to TestFlight is misleading because build
validation later requires skipping the build-number bump when no App Store
Connect API key is provided; update the log.warn messages (the two calls
currently emitting the API-key absence and the suggested --apple-key flags) to
also instruct users to skip the build-number bump when they do not provide an
API key (e.g., "and add --skip-build-number-bump when not using an Apple API
key") so the next validation step won't fail; modify the message strings in the
existing log.warn calls to include this constraint while preserving the existing
guidance about --apple-key, --apple-key-id and --apple-issuer-id.
Updates credential validation tests to cover the new conditional paths: - No API key + no output upload → error (no destination) - No API key + output upload + no skip-build-number-bump → error - No API key + output upload + skip-build-number-bump → allow - Partial API key (2 of 3 fields) + no output upload → error Extracts shared validateIosCredentials() helper matching request.ts logic.
- Warning now mentions --skip-build-number-bump requirement when no API key - Example includes --output-upload so copy-paste works without errors - Error message in request.ts mentions --output-upload CLI flag
| await test('iOS validation errors when no API key with output upload but no skip-build-number-bump', () => { | ||
| const credentials = { | ||
| BUILD_CERTIFICATE_BASE64: 'cert', | ||
| P12_PASSWORD: 'pass', |
Check failure
Code scanning / SonarCloud
Credentials should not be hard-coded High test
| await test('iOS validation allows no API key when output upload and skip-build-number-bump are set', () => { | ||
| const credentials = { | ||
| BUILD_CERTIFICATE_BASE64: 'cert', | ||
| P12_PASSWORD: 'pass', |
Check failure
Code scanning / SonarCloud
Credentials should not be hard-coded High test
When users provide some but not all API key fields (e.g. key ID + issuer but no key content), the validation now reports exactly which fields are missing instead of suggesting output-upload as an alternative. Adds 2 test cases for partial API key detection scenarios.
|




Summary
APPLE_KEY_ID,APPLE_ISSUER_ID, andAPPLE_KEY_CONTENToptional for iOS builds--output-upload) no longer need App Store Connect API key credentialsPLAY_CONFIG_JSONoptional for Android buildsValidation rules
--output-upload→ error (no output destination)--skip-build-number-bump→ error (can't auto-increment without API key)What stays required
APP_STORE_CONNECT_TEAM_ID(Xcode project config)APPLE_PROFILE_NAME(Xcode project config)Companion PR
Test plan
build credentials save --platform ioswithout API key +--output-upload→ should succeed with warningbuild credentials save --platform ioswithout API key and without--output-upload→ should error--output-upload+--skip-build-number-bump→ should build IPA and skip TestFlight uploadSummary by CodeRabbit