Skip to content

iOS TestFlight CI/CD + fix Release-archive build (DEBUG-gating from #5079) - #5448

Merged
lawrencecchen merged 5 commits into
mainfrom
feat-ios-testflight-cicd
Jun 5, 2026
Merged

lawrencecchen merged 5 commits into
mainfrom
feat-ios-testflight-cicd

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Adds GitHub Actions CI/CD that ships the cmux iOS app to TestFlight, and fixes the iOS Release-archive build regression that building it in Release exposed.

TestFlight workflow (.github/workflows/ios-testflight.yml)

  • Triggers: workflow_dispatch (optional build_number / force) + a nightly cron that skips when main has had no new commits in the last 24h (a cheap ubuntu decide job), so it doesn't burn build numbers on unchanged code.
  • Build: macos-26, Xcode select + submodules: recursive + install-zig-ci.sh + ensure-ghosttykit.sh (mirrors test-ios.yml), then ios/scripts/upload-testflight.sh --lane beta --signing automatic (bundle id dev.cmux.app.beta, internal TestFlight).
  • Signing: cloud-managed (automatic) via -allowProvisioningUpdates + the App Store Connect API key, so the runner needs no iOS distribution cert/profile in its keychain — only the three ASC secrets (ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64). upload-testflight.sh gains a --signing manual|automatic flag (default manual, preserving local-keychain exports).

Validated end-to-end on the branch (temp push trigger, since removed): real archive → cloud-signed export → altool UPLOAD SUCCEEDED with no errors, Delivery UUID 39be114b-d1df-4392-8dcb-32f9708f3f16, ~3.5 min.

iOS Release-archive fix (⚠️ this was also breaking main's nightly/release iOS)

test-ios.yml only builds Debug/simulator, so two DEBUG-only-used-from-non-DEBUG leaks from the #5079 iOS-mobile merge went unnoticed and broke the Release archive:

  • GhosttySurfaceView.surfaceText was #if DEBUG but the non-DEBUG public visibleTerminalSnapshot() (Copy Debug Logs, ships in betas) calls it → un-gated the helper.
  • TerminalLayoutPreviewView (UITest screenshot scaffolding, mounted only when CMUX_UITEST_TERMINAL_PREVIEW=1) was gated only by #if canImport(UIKit) and called DEBUG-only debug*ForLayoutPreview seams → DEBUG-gated the file + its CMUXMobileRootView mount points.

cmux-ios now compiles in Release (verified BUILD SUCCEEDED + the real upload above). Debug behavior is unchanged.

Notes

  • The ios-testflight workflow doesn't run on PRs (dispatch + nightly only); it's validated above.
  • The Release-archive fix is bundled here because building iOS in Release is exactly what this PR adds, but it independently unbreaks main's nightly/release iOS — worth merging promptly.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Medium Risk
Touches release signing/export and CI secrets for App Store Connect; Swift changes are compile-gating only with no intended runtime behavior change in Release beyond fixing the broken archive.

Overview
Adds automated TestFlight delivery for the iOS beta (dev.cmux.app.beta) via a new GitHub Actions workflow: manual dispatch or a nightly cron, with a lightweight decide job that skips scheduled uploads when main has no commits in the last 24h. The macOS job provisions GhosttyKit, materializes App Store Connect API keys, and runs upload-testflight.sh with --signing automatic so CI can export without a distribution cert in the keychain.

upload-testflight.sh gains --signing manual|automatic (default manual): automatic export omits manual cert/profile plist entries and relies on cloud-managed signing with -allowProvisioningUpdates.

Release archive fixes exposed by shipping Release builds: GhosttySurfaceView.surfaceText is no longer #if DEBUG-only so release Copy Debug Logs / visibleTerminalSnapshot() compiles; UITest terminal layout preview (TerminalLayoutPreviewView and its mount in CMUXMobileRootView) is restricted to DEBUG so Release does not pull DEBUG-only preview seams.

Reviewed by Cursor Bugbot for commit 458d100. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Automates TestFlight uploads for the cmux iOS beta and fixes Release-archive failures from DEBUG-only code. Manual and nightly uploads use cloud-managed signing; nightly skips only when the current main HEAD was already uploaded. Release/TestFlight builds compile again.

  • New Features

    • Added iOS TestFlight (beta) workflow at .github/workflows/ios-testflight.yml to archive, export, and upload the beta lane (dev.cmux.app.beta).
    • Triggers: manual (workflow_dispatch with optional build_number) and nightly; gate uses the last successful run’s head_sha so missed/failed runs retry. Adds actions: read to query run history.
    • Uses cloud-managed signing via App Store Connect; requires ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64. No distribution cert/profile on the runner.
    • ios/scripts/upload-testflight.sh supports --signing automatic (CI) in addition to manual (default).
    • Labeled jobs with human-readable names for clearer Actions UI.
  • Bug Fixes

    • Ungated GhosttySurfaceView.surfaceText so visibleTerminalSnapshot() works in Release; fixes Release/TestFlight archive failures.
    • DEBUG-gated TerminalLayoutPreviewView and its mounts in CMUXMobileRootView to avoid DEBUG-only seams in Release.
    • cmux-ios now compiles in Release; nightly/release iOS and TestFlight builds succeed.

Written for commit 1711183. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added an iOS TestFlight CI pipeline to automate conditional beta uploads with manual trigger and nightly scheduling.
  • Improvements

    • Terminal layout preview is now enabled only in debug iOS builds.
    • Terminal snapshot / “copy logs” functionality remains available in release builds for diagnostics.
    • TestFlight upload tooling now supports selectable signing modes (manual or automatic) for exports.

lawrencecchen and others added 3 commits June 5, 2026 01:16
New .github/workflows/ios-testflight.yml archives, exports, and uploads the
cmux-ios beta lane (bundle id dev.cmux.app.beta) to TestFlight. Triggers:
workflow_dispatch (optional build_number/force) and a nightly cron that skips
when main has had no new commits in the last 24h.

Auth uses the App Store Connect API key from the ASC_API_KEY_ID /
ASC_API_ISSUER_ID / ASC_API_KEY_P8_BASE64 secrets, materialized to
~/.appstoreconnect/private_keys. Signing is cloud-managed (automatic) via
-allowProvisioningUpdates, so the runner needs no iOS distribution
cert/profile in its keychain. upload-testflight.sh gains a
--signing manual|automatic flag (default manual; automatic drops the manual
signingCertificate/provisioningProfiles and sets signingStyle=automatic).

Validated end-to-end: real TestFlight upload succeeded (altool "UPLOAD
SUCCEEDED with no errors", Delivery UUID 39be114b-d1df-4392-8dcb-32f9708f3f16).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`visibleTerminalSnapshot()` (Copy Debug Logs) is non-DEBUG and public (called
from WorkspaceDetailView), but `surfaceText` was inside `#if DEBUG`, so the iOS
app compiled in Debug (simulator CI, reload) yet failed the Release archive
with "cannot find 'surfaceText' in scope". A latent main regression from #5079
that only a Release archive exercises. Move `surfaceText` (pure libghostty
read) out of the DEBUG block; the DEBUG-only accessibility helpers still call
it. Keeps Copy Debug Logs working in TestFlight betas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…chive

TerminalLayoutPreviewView is a DEBUG-only screenshot harness (mounted only when
CMUX_UITEST_TERMINAL_PREVIEW=1) that calls the DEBUG-only test seams
debugSetKeyboardHeightForLayoutPreview / debugShowZoomControlOverlayForPreview,
but it was gated only by `#if canImport(UIKit)`, so it shipped in Release and
failed the archive ("no member ...ForLayoutPreview"). Gate the file and its
CMUXMobileRootView mount points (shouldShowTerminalLayoutPreview /
terminalLayoutPreview) with `&& DEBUG`; Release already had the `#else`
false/EmptyView fallbacks. Debug behavior unchanged. With the surfaceText
un-gate, cmux-ios now compiles in Release (verified BUILD SUCCEEDED + a real
TestFlight upload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 5, 2026 8:57am
cmux-staging Building Building Preview, Comment Jun 5, 2026 8:57am

@coderabbitai

coderabbitai Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 602424f9-d47e-491d-809e-adaee6394e6e

📥 Commits

Reviewing files that changed from the base of the PR and between e44b49d and 1711183.

📒 Files selected for processing (1)
  • .github/workflows/ios-testflight.yml

📝 Walkthrough

Walkthrough

Adds a scheduled/manual TestFlight upload workflow, extends the upload script with manual/automatic signing support, and makes terminal preview UI compile only in DEBUG while keeping the release snapshot helper available.

Changes

iOS TestFlight & Release Build Pipeline

Layer / File(s) Summary
Upload script signing mode support
ios/scripts/upload-testflight.sh
Adds --signing <mode> (manual
TestFlight CI automation pipeline
.github/workflows/ios-testflight.yml
New workflow with workflow_dispatch and nightly schedule; decide job computes should_build (always for dispatch, compares SHAs for schedule); upload job provisions Xcode/GhosttyKit, materializes App Store Connect API key, resolves CFBundleVersion, runs ./ios/scripts/upload-testflight.sh --lane beta --signing automatic --build-number, and appends a step summary.
Debug-only terminal preview UI components
Packages/CmuxMobileShellUI/.../CMUXMobileRootView.swift, .../TerminalLayoutPreviewView.swift, Packages/CmuxMobileTerminal/.../GhosttySurfaceView.swift
Gates terminal layout preview UI to DEBUG builds on iOS; TerminalLayoutPreviewView is now #if canImport(UIKit) && DEBUG, CMUXMobileRootView uses #if os(iOS) && DEBUG, and surfaceText(...) in GhosttySurfaceView is moved out of the DEBUG block so release builds retain the snapshot helper.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I hopped a build into the night,
Signed with care, then took to flight,
Debug vistas hide their view,
But logs and snapshots still come through,
A tiny rabbit cheers the deploy delight!

🚥 Pre-merge checks | ✅ 18 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly identifies the two main changes: iOS TestFlight CI/CD workflow and Release-archive build fixes from DEBUG-gating.
Description check ✅ Passed Description covers Summary (what/why), Testing (end-to-end validation), and explains technical details; missing explicit Testing section, Demo Video, and Review Trigger/Checklist but core content is comprehensive.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed PR changes do not introduce actor isolation issues. SwiftUI Views remain implicitly @MainActor, and nonisolated static surfaceText is correctly marked to run off-main.
Cmux Swift Blocking Runtime ✅ Passed PR introduces no new blocking synchronization; changes only adjust compilation conditions and remove DEBUG gating from a pure-C libghostty function call.
Cmux No Hacky Sleeps ✅ Passed No hacky sleeps found. The shell script contains no sleep(), polling loops, or fixed delays hiding timing races. GitHub Actions workflow timeout-minutes are CI orchestration (allowed per rule).
Cmux Algorithmic Complexity ✅ Passed PR changes only modify compilation gating and ungating (no logic changes). No algorithmic complexity violations found in the five changed files.
Cmux Swift Concurrency ✅ Passed PR contains no new legacy async patterns: only DEBUG-gating changes and compilation flag adjustments to fix Release builds. Existing Tasks in SwiftUI callbacks are within allowed boundaries.
Cmux Swift @Concurrent ✅ Passed PR changes do not introduce or modify @concurrent annotations or nonisolated async functions; un-gating synchronous surfaceText from DEBUG guard doesn't violate concurrent annotation rules.
Cmux Swift File And Package Boundaries ✅ Passed All Swift changes are small, focused bug fixes (2-6 lines) to UI scaffolding and Ghostty glue, with no new oversized files, large additions, or mixed responsibilities.
Cmux Swift Logging ✅ Passed No Swift logging violations found: no print/debugPrint/dump/NSLog added to production code, no ad hoc logging, no secret exposure, and existing Loggers properly scoped.
Cmux User-Facing Error Privacy ✅ Passed Environment variable names in errors are only in CI workflows, build scripts, and DEBUG-only code—not shown to app end-users, covered by allowed 'developer-only and operational runbooks' exception.
Cmux Full Internationalization ✅ Passed PR contains only CI/CD, debug-only code gating, and build scripts—no new user-facing text requiring localization. All exceptions apply.
Cmux Swiftui State Layout ✅ Passed PR DEBUG-gates preview UI and ungates helper for Release's Copy Logs feature—no new SwiftUI state violations or problematic patterns introduced.
Cmux Architecture Rethink ✅ Passed Small correctness fixes for Release archive: proper DEBUG-gating of preview UI; un-gating safe surfaceText for Copy Debug Logs. Clear owners, no problematic patterns.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR contains only iOS Views/UIViews, not NSWindow/NSPanel/Window/WindowGroup types. Rule targeting standalone window declarations is inapplicable.
Cmux Source Artifacts ✅ Passed All changed files are intentional hand-written source code, configurations, or automation scripts. No generated artifacts, build output, logs, or scratch directories detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-ios-testflight-cicd

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 458d1001bc

ℹ️ 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".

Comment on lines +53 to +60
if (!forceBuild && context.eventName === 'schedule') {
const since = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const commits = await github.rest.repos.listCommits({
owner,
repo,
sha: 'main',
since,
per_page: 1,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Widen the scheduled commit window

For scheduled runs, this checks only commits newer than exactly 24 hours before the job actually starts. GitHub documents that schedule workflows can be delayed or even dropped under load, so a commit that lands just after yesterday's 09:10 run can be older than 24 hours by the time today's delayed run executes, causing the nightly TestFlight upload to be skipped even though that commit was never uploaded. Consider using a wider overlap window or comparing against the last successful upload/run instead of Date.now() - 24h.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an automated TestFlight delivery pipeline for the cmux iOS beta and fixes two #if DEBUG guard mistakes introduced in #5079 that broke the Release/TestFlight archive build.

  • New ios-testflight.yml workflow: nightly (09:10 UTC) + manual dispatch; a lightweight decide job compares the current HEAD SHA against the last successful run's SHA to avoid burning build numbers on unchanged code. The upload job runs on macos-26, provisions GhosttyKit, materializes the ASC API key, and calls upload-testflight.sh --signing automatic so CI needs no distribution cert in the keychain.
  • upload-testflight.sh --signing flag: automatic mode omits signingCertificate/provisioningProfiles from the export plist and relies on cloud-managed signing via -allowProvisioningUpdates; manual (default) preserves the original local-keychain path for developer exports.
  • Release archive fixes: GhosttySurfaceView.surfaceText is moved outside #if DEBUG so the release-shipping visibleTerminalSnapshot() compiles; TerminalLayoutPreviewView and its mount points in CMUXMobileRootView are tightened to #if os(iOS) && DEBUG / #if canImport(UIKit) && DEBUG so UITest scaffold seams never reach Release.

Confidence Score: 5/5

Safe to merge. The Swift compilation fixes are correct and narrowly scoped; the new workflow has been validated end-to-end per the PR description.

The Swift changes are compile-gating only with no runtime behavior change in Release beyond fixing the broken archive. The workflow is dispatch + nightly only, not PR-triggered, so merging carries no risk of accidental TestFlight submissions.

.github/workflows/ios-testflight.yml — the decide job listWorkflowRuns call would benefit from a branch filter to avoid spurious nightly uploads after manual feature-branch dispatches.

Important Files Changed

Filename Overview
.github/workflows/ios-testflight.yml New workflow wiring TestFlight uploads (nightly + dispatch). SHA-based skip logic works correctly for the common case but the listWorkflowRuns call lacks a branch filter, which can cause unnecessary nightly uploads after feature-branch dispatches.
ios/scripts/upload-testflight.sh Adds `--signing manual
Packages/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceView.swift Moves surfaceText outside the #if DEBUG block so the release-shipping visibleTerminalSnapshot() can call it without a compile error in Release/TestFlight builds. accessibilitySurfaceText (still inside the DEBUG block) calls surfaceText correctly after the move.
Packages/CmuxMobileShellUI/Sources/CmuxMobileShellUI/CMUXMobileRootView.swift Tightens shouldShowTerminalLayoutPreview and terminalLayoutPreview guards from #if os(iOS) to #if os(iOS) && DEBUG, preventing UITest-only preview scaffolding from reaching Release builds.
Packages/CmuxMobileShellUI/Sources/CmuxMobileShellUI/TerminalLayoutPreviewView.swift Whole file is now gated with #if canImport(UIKit) && DEBUG, preventing DEBUG-only preview seams from entering the Release archive.

Reviews (3): Last reviewed commit: "ci: add human-readable job names to the ..." | Re-trigger Greptile

Comment thread .github/workflows/ios-testflight.yml Outdated
Comment on lines +55 to +63
const commits = await github.rest.repos.listCommits({
owner,
repo,
sha: 'main',
since,
per_page: 1,
});
recentCount = commits.data.length;
hasRecentCommits = recentCount > 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Commit check hardcodes sha: 'main'

listCommits is called with sha: 'main' unconditionally. If the repository's default branch is ever renamed, the nightly skip logic silently breaks — listCommits for an unknown branch returns an empty array, so hasRecentCommits is always false and the nightly build never fires. Using context.payload.repository.default_branch (available in github-script) keeps this resilient to a branch rename.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 @.github/workflows/ios-testflight.yml:
- Around line 78-92: Add a human-readable name field to the upload job by
inserting a "name: Upload" (or a more descriptive title like "Upload to
TestFlight") directly under the upload job key so the GitHub Actions UI shows a
clear label for the job; target the upload job block (the job named upload) and
add the name property at the top of that block alongside the existing
needs/if/runs-on entries.
- Around line 32-77: The job with id "decide" is missing a human-readable name
for GitHub Actions UI; add a name field to that job (for example "Decide whether
a TestFlight upload is needed") directly under the "decide:" job header so the
workflow shows a descriptive title in the Actions UI—update the job definition
where "decide" is declared (the job that runs actions/github-script@... and sets
output should_build) to include the name property.
🪄 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: ac1213ee-1d36-44ab-82df-69bada82e58c

📥 Commits

Reviewing files that changed from the base of the PR and between e11fd58 and 458d100.

📒 Files selected for processing (5)
  • .github/workflows/ios-testflight.yml
  • Packages/CmuxMobileShellUI/Sources/CmuxMobileShellUI/CMUXMobileRootView.swift
  • Packages/CmuxMobileShellUI/Sources/CmuxMobileShellUI/TerminalLayoutPreviewView.swift
  • Packages/CmuxMobileTerminal/Sources/CmuxMobileTerminal/GhosttySurfaceView.swift
  • ios/scripts/upload-testflight.sh

Comment thread .github/workflows/ios-testflight.yml
Comment thread .github/workflows/ios-testflight.yml
The scheduled gate compared commit dates against a moving 24h wall-clock
window, so a failed or missed nightly could permanently strand the latest
commit: the next run would see zero commits in the window and skip a SHA that
was never uploaded. Gate instead on whether the current main HEAD already
matches the head_sha of the most recent successful run of this workflow. A
successful run either uploaded HEAD or correctly skipped an already-uploaded
HEAD, so its head_sha is always an uploaded commit; a failed run is not
"success", so the last-success SHA stays older and the next run retries.
Adds actions: read so decide can query run history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e44b49d. Configure here.

per_page: 1,
});
lastUploadedSha = runs.data.workflow_runs[0]?.head_sha ?? null;
needsBuild = lastUploadedSha !== context.sha;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skip logic ignores branch

Medium Severity

The scheduled skip check compares main’s HEAD to the latest successful run’s head_sha across all branches. After main is uploaded, a later successful manual run from another branch makes nightly jobs think main is new and re-upload the same commit, contradicting the “skip when HEAD already uploaded” behavior and wasting CI and build numbers.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e44b49d. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e44b49de6a

ℹ️ 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".

concurrency:
group: ios-testflight-${{ github.ref_name }}
# Queue concurrent runs instead of canceling them so no upload is lost.
cancel-in-progress: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Queue all pending TestFlight uploads

In this workflow, cancel-in-progress: false does not actually queue every requested upload: GitHub Actions concurrency groups still keep only one pending run by default, and a third run for the same ref cancels the older pending run unless the new queue setting is enabled. If a TestFlight upload is running and two manual dispatches or delayed scheduled runs for main arrive, the middle requested upload can be dropped despite the comment's "no upload is lost" guarantee; add an explicit multi-run queue (for example queue: max) or remove the workflow-level concurrency if every dispatch must upload.

Useful? React with 👍 / 👎.

Addresses CodeRabbit: label the decide/upload jobs so the Actions UI shows
descriptive titles instead of the raw job ids.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – cmux — 17111835 Deployed Jun 5, 2026 by vercel[bot]
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.

1 participant