feat(cli): default credentials manage export to a combined .env file#2280
Conversation
When both iOS and Android are configured, `build credentials manage` now writes a single `.env.capgo.<appId>` file containing both platforms' secrets under `# === IOS ===` / `# === ANDROID ===` sections. iOS and Android env-var names are disjoint, so combining them is conflict-free and removes the need to run `gh secret set -f` (or equivalent) twice. Add `--per-platform` to opt back into the old behaviour: one file per platform, with the TUI prompting for which platform to export. If only one platform is configured (or only one has any values), the combined path degrades to the existing per-platform name to avoid surprising users with a generic file name.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughExport flow auto-detects multi-platform credential entries and writes a single combined ChangesCombined Multi-Platform Export
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cli/src/build/credentials-manage.ts (1)
1232-1248: 💤 Low valueConsider extracting shared export-and-log logic.
The single-platform fallback path (lines 1233–1247) duplicates the write-file, chmod, log pattern from
exportToEnvFile(lines 1195–1214). A small helper could reduce this, but the current code is correct and self-contained.🤖 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 `@cli/src/build/credentials-manage.ts` around lines 1232 - 1248, The single-platform branch duplicates the write/chmod/log sequence found in exportToEnvFile; extract a small helper (e.g., exportEnvFile or performEnvExport) that accepts the resolved target (from resolveExportTarget), the rendered content (from renderEnvFile), and the creds (to compute fieldCount), then performs writeFile(..., {mode: 0o600}), chmod(..., 0o600), and the pLog.success/pLog.info messages; replace the duplicated block in this branch with a call to that helper and reuse it from exportToEnvFile to remove duplication while keeping behavior identical.
🤖 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.
Nitpick comments:
In `@cli/src/build/credentials-manage.ts`:
- Around line 1232-1248: The single-platform branch duplicates the
write/chmod/log sequence found in exportToEnvFile; extract a small helper (e.g.,
exportEnvFile or performEnvExport) that accepts the resolved target (from
resolveExportTarget), the rendered content (from renderEnvFile), and the creds
(to compute fieldCount), then performs writeFile(..., {mode: 0o600}), chmod(...,
0o600), and the pLog.success/pLog.info messages; replace the duplicated block in
this branch with a call to that helper and reuse it from exportToEnvFile to
remove duplication while keeping behavior identical.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a32a081-309f-4de4-af05-b79887dd7ab9
📒 Files selected for processing (2)
cli/src/build/credentials-manage.tscli/src/index.ts
The new flag was redundant with the existing --platform option: - Want both platforms in one file? → manage (no flag) - Want only one platform? → manage --platform ios - Want both as separate files? → manage --platform ios, then --platform android Combined export is now the only behaviour when both platforms are in scope; --platform narrows scope upstream so the export naturally becomes single-platform.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d10614d3a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (const [key, value] of Object.entries(creds)) { | ||
| if (typeof value !== 'string' || value.length === 0) | ||
| continue | ||
| if (key === 'CAPGO_IOS_PROVISIONING_MAP') | ||
| continue | ||
| lines.push(`${key}=${escapeDotenvValue(value)}`) |
There was a problem hiding this comment.
Deduplicate shared keys in combined env export
When both platforms are exported together, this loop writes every key from each platform verbatim, so shared settings like BUILD_OUTPUT_UPLOAD_ENABLED, BUILD_OUTPUT_RETENTION_SECONDS, or SKIP_BUILD_NUMBER_BUMP can appear twice in the same dotenv file. The manager explicitly allows shared keys to exist (and even drift) per platform, so combined export can silently emit conflicting assignments where one value overwrites the other during dotenv ingestion (e.g., gh secret set -f/shell sourcing), producing incorrect CI secrets for at least one platform.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
cli/src/build/credentials-manage.ts (2)
1369-1409: ⚡ Quick winConsider extracting the provisioning-map rendering logic into a helper.
The provisioning-map handling (lines 1390-1404) duplicates the logic from
renderEnvFile(lines 1348-1363): extract the raw value, skip it in the main loop, then append base64 and commented raw forms. Extracting this into a helper function would eliminate the duplication and keep both renderers DRY.🤖 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 `@cli/src/build/credentials-manage.ts` around lines 1369 - 1409, The provisioning-map handling is duplicated between renderEnvFileCombined and renderEnvFile: both extract creds.CAPGO_IOS_PROVISIONING_MAP, skip it in the main loop, then append a base64 entry and a commented raw entry. Extract that logic into a small helper (e.g., renderProvisioningMapEntries or formatProvisioningMapLines) that accepts the raw provisioningMap string and escapeDotenvValue and returns the array/string lines for the base64 and commented raw forms (including the comment header). Replace the duplicated block in renderEnvFileCombined and the block in renderEnvFile to call this helper and append its returned lines, keeping existing symbols CAPGO_IOS_PROVISIONING_MAP, CAPGO_IOS_PROVISIONING_MAP_BASE64, and escapeDotenvValue unchanged.
1215-1268: ⚡ Quick winConsider extracting the single-platform export logic into a shared helper.
The fallback path (lines 1230-1246) duplicates the main single-platform export logic from
exportToEnvFile(lines 1193-1212). Both resolve the target, render content, write the file, chmod, and log the same success messages. Extracting this into a helper likeexportSinglePlatformEnvFilewould reduce duplication and make future changes easier to maintain.🤖 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 `@cli/src/build/credentials-manage.ts` around lines 1215 - 1268, The single-platform export block in exportCombinedEnvFile duplicates the same steps found in exportToEnvFile (resolveExportTarget, renderEnvFile, writeFile, chmod and pLog messages); extract that repeated logic into a helper function (e.g. exportSinglePlatformEnvFile) that accepts (entry, platform, creds, defaultName) and performs resolveExportTarget, renders via renderEnvFile, writes/chmods the file and emits the same pLog.info/pLog.success messages, then replace both the fallback block in exportCombinedEnvFile and the code in exportToEnvFile to call this new helper to remove duplication.
🤖 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.
Nitpick comments:
In `@cli/src/build/credentials-manage.ts`:
- Around line 1369-1409: The provisioning-map handling is duplicated between
renderEnvFileCombined and renderEnvFile: both extract
creds.CAPGO_IOS_PROVISIONING_MAP, skip it in the main loop, then append a base64
entry and a commented raw entry. Extract that logic into a small helper (e.g.,
renderProvisioningMapEntries or formatProvisioningMapLines) that accepts the raw
provisioningMap string and escapeDotenvValue and returns the array/string lines
for the base64 and commented raw forms (including the comment header). Replace
the duplicated block in renderEnvFileCombined and the block in renderEnvFile to
call this helper and append its returned lines, keeping existing symbols
CAPGO_IOS_PROVISIONING_MAP, CAPGO_IOS_PROVISIONING_MAP_BASE64, and
escapeDotenvValue unchanged.
- Around line 1215-1268: The single-platform export block in
exportCombinedEnvFile duplicates the same steps found in exportToEnvFile
(resolveExportTarget, renderEnvFile, writeFile, chmod and pLog messages);
extract that repeated logic into a helper function (e.g.
exportSinglePlatformEnvFile) that accepts (entry, platform, creds, defaultName)
and performs resolveExportTarget, renders via renderEnvFile, writes/chmods the
file and emits the same pLog.info/pLog.success messages, then replace both the
fallback block in exportCombinedEnvFile and the code in exportToEnvFile to call
this new helper to remove duplication.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d6adb3e9-3029-46da-a811-aaba9b4e883c
📒 Files selected for processing (1)
cli/src/build/credentials-manage.ts
The combined export emits every key from each platform verbatim, so a
shared config toggle stored under both platforms (e.g.
BUILD_OUTPUT_UPLOAD_ENABLED, BUILD_OUTPUT_RETENTION_SECONDS,
SKIP_BUILD_NUMBER_BUMP, CAPGO_IOS_DISTRIBUTION) that has drifted out of
sync would silently appear twice in the file. Dotenv ingestion (gh
secret set -f, shell sourcing) keeps only the LAST occurrence per key,
so one platform would get the wrong value with no signal.
Detect conflicts before writing:
- print each conflicting key with both values (long values masked as
"(N chars)" to avoid leaking accidental shared secrets);
- require explicit confirmation before writing the file;
- embed the conflict list as a comment block at the top of the file
so future readers and audit tooling can spot it without rerunning
the manager.
Same-value duplicates remain harmless and pass through silently.
|



Summary
build credentials manage→ Export to .env now writes a single.env.capgo.<appId>file containing both iOS and Android secrets when both platforms are configured.gh secret set -f(or equivalent) twice in CI setup.--platform ios(or--platform android) to narrow the manage scope upstream — the export naturally becomes per-platform.BUILD_OUTPUT_UPLOAD_ENABLED,BUILD_OUTPUT_RETENTION_SECONDS,SKIP_BUILD_NUMBER_BUMP,CAPGO_IOS_DISTRIBUTION, etc.) can be stored under both platforms and are allowed to diverge. Before writing the combined file, the manager detects any such conflicts, prints them, requires explicit confirmation, and embeds the conflict list as a comment block at the top of the file so future readers can spot it.Why
The previous behaviour forced users to pick Export to .env twice (once per platform) when configuring CI/CD secrets for an app with both iOS and Android builds. That extra step is invisible from the docs side and confusing in the TUI ("why do I have to do this twice?"). Combining into one file matches the natural
gh secret set -f <env-file>workflow and gets users from "I have credentials configured locally" to "GitHub Actions can build" in fewer steps.File format
Behaviour matrix
manage.env.capgo.<appId>(warns + confirms on shared-key drift).env.capgo.<appId>.<platform>manage --platform ios.env.capgo.<appId>.ios.env.capgo.<appId>.iosmanage --platform android.env.capgo.<appId>.android.env.capgo.<appId>.androidTest plan
bun run typecheckcleanbun run lintcleanbun run buildsucceedsbun run test:credentials— 17/17 passbun run test:credentials-validation— 13/13 passnode dist/index.js build credentials manage --helpshows expected flags--platform ioson a two-platform app → per-platform pathFollow-up
Docs page at
website/src/content/docs/docs/cli/cloud-build/github-actions.mdxwill be updated to match in a separate PR onCap-go/websiteafter this ships in@capgo/cli@latest.Summary by CodeRabbit