Skip to content

ios: fix broken Release archive blocking all TestFlight builds - #6488

Merged
lawrencecchen merged 2 commits into
mainfrom
fix-ios-release-archive
Jun 20, 2026
Merged

lawrencecchen merged 2 commits into
mainfrom
fix-ios-release-archive

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

The bug

CMUXMobileRootView.rootContent references WorkspaceListLayoutPreviewView() directly, but that view is #if canImport(UIKit) && DEBUG-only (a simulator screenshot fixture). PR CI builds Debug (where the symbol exists), so this passed review — but the TestFlight Release archive fails:

CMUXMobileRootView.swift:170: error: cannot find 'WorkspaceListLayoutPreviewView' in scope
** ARCHIVE FAILED **

This has silently blocked every TestFlight build since it landed: last successful upload was 2026-06-18, and both the 2026-06-19 nightly and a 2026-06-20 dispatch failed here. (It's why the merged backspace fix and everything since hasn't reached beta.)

The fix

shouldShowWorkspaceListLayoutPreview is already false in Release, so the branch is dead code there. Route the reference through a workspaceListLayoutPreview @ViewBuilder that compiles to EmptyView in Release — exactly mirroring the existing terminalLayoutPreview. One-file, no behavior change in Debug.

Note

PR CI (Debug) can't catch this class of bug. A companion PR adds an on-iOS-change TestFlight (Release archive) lane so a broken Release archive surfaces immediately instead of silently stranding beta.

🤖 Generated with Claude Code


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


Note

Low Risk
Compile-time gating only; Release behavior was already dead code via shouldShowWorkspaceListLayoutPreview, with no production UI or auth changes.

Overview
Fixes TestFlight Release archive failures caused by rootContent referencing WorkspaceListLayoutPreviewView() directly while that type exists only under #if DEBUG.

Adds a workspaceListLayoutPreview @ViewBuilder (same pattern as terminalLayoutPreview) so Release builds compile the branch to EmptyView, and rootContent now uses that helper instead of the raw type. Debug simulator screenshot fixtures are unchanged when the preview flags are on.

Also updates .github/swift-file-length-budget.tsv for small line-count shifts in CMUXMobileRootView.swift and BrowserAutomation.swift.

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


Summary by cubic

Fix iOS Release archive by gating the DEBUG-only WorkspaceListLayoutPreviewView behind a @ViewBuilder that compiles to EmptyView in Release. This unblocks TestFlight uploads with no Debug behavior change.

  • Bug Fixes
    • Routed WorkspaceListLayoutPreviewView through workspaceListLayoutPreview with #if os(iOS) && DEBUG, mirroring terminalLayoutPreview.
    • Updated rootContent to use the gated view so Release no longer fails with “cannot find ... in scope”.
    • Refreshed .github/swift-file-length-budget.tsv for CMUXMobileRootView.swift to keep CI passing after adding the gate helper.

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

Review in cubic

Summary by CodeRabbit

  • Refactor
    • Improved conditional logic for preview components to ensure correct behavior across different build configurations.

…wView referenced unconditionally)

rootContent referenced WorkspaceListLayoutPreviewView() directly, but that view
is '#if canImport(UIKit) && DEBUG'-only (a simulator screenshot fixture). PR CI
builds Debug (where it exists) so this passed review, but the TestFlight Release
ARCHIVE fails with 'cannot find WorkspaceListLayoutPreviewView in scope' — which
has been silently blocking EVERY TestFlight build since it landed (last
successful upload 2026-06-18; the 6/19 nightly and a 6/20 dispatch both failed
here). shouldShowWorkspaceListLayoutPreview is already false in Release, so the
branch is dead there; gate the reference through a workspaceListLayoutPreview
@ViewBuilder var that compiles to EmptyView in Release, mirroring the existing
terminalLayoutPreview.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 20, 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 20, 2026 7:41am
cmux-staging Building Building Preview, Comment Jun 20, 2026 7:41am

@coderabbitai

coderabbitai Bot commented Jun 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 012a4310-f5e4-45eb-a74c-fffda988876d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

In CMUXMobileRootView, a new private workspaceListLayoutPreview @ViewBuilder property is added that conditionally instantiates WorkspaceListLayoutPreviewView() only under #if os(iOS) && DEBUG, returning EmptyView() otherwise. The rootContent rendering path is updated to call this new property instead of directly referencing WorkspaceListLayoutPreviewView().

Changes

Conditional Preview Gating in CMUXMobileRootView

Layer / File(s) Summary
Gated view builder and render site update
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/CMUXMobileRootView.swift
Adds the workspaceListLayoutPreview private @ViewBuilder guarded by #if os(iOS) && DEBUG (returning EmptyView in Release), and updates the shouldShowWorkspaceListLayoutPreview branch in rootContent to render this new property.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

  • manaflow-ai/cmux#5448: Applies the same DEBUG-gating pattern to terminalLayoutPreview in CMUXMobileRootView, directly analogous to this PR's treatment of WorkspaceListLayoutPreviewView.

Poem

🐇 A preview that slipped through Release's gate,
Now wrapped in a #if to keep things straight.
EmptyView stands guard in the prod-time sun,
While DEBUG lets the layout preview run.
Hop hop — no stray symbols shall sneak through! 🌟

🚥 Pre-merge checks | ✅ 23
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main fix: resolving a broken Release archive that was blocking TestFlight builds by addressing a DEBUG-only symbol reference.
Description check ✅ Passed The description provides a clear bug explanation, fix rationale, and testing context, but lacks structured sections matching the template and is missing Testing and Checklist sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 SwiftUI view types are exempt from actor isolation checks. The new @ViewBuilder property mirrors existing terminalLayoutPreview and doesn't introduce new isolation issues.
Cmux Swift Blocking Runtime ✅ Passed The PR introduces only a conditional compilation pattern through a new @ViewBuilder property that routes DEBUG-only view references. No blocking operations, synchronization primitives, sleeps, sema...
Cmux Expensive Synchronous Load ✅ Passed No expensive synchronous loaders added; PR only wraps DEBUG-only view in @ViewBuilder to fix Release archive build failure.
Cmux Cache Substitution Correctness ✅ Passed PR is not applicable to cache substitution check—it's conditional compilation fixing a DEBUG-only view reference, not a cache/persistence/history/undo/snapshot change involving stale or cold data.
Cmux No Hacky Sleeps ✅ Passed This is a Swift file (.swift), and the custom check explicitly excludes Swift timing code, which is covered by a separate rule. Additionally, the change contains no sleep, delay, timer, or polling...
Cmux Algorithmic Complexity ✅ Passed No algorithmic complexity violations. Change is a conditional compilation fix using simple constant-time property access, mirroring the existing terminalLayoutPreview pattern with zero impact on co...
Cmux Swift Concurrency ✅ Passed PR introduces only a @ViewBuilder property for conditional compilation of a DEBUG-only view, with no async/await, Task, DispatchQueue, Combine, or completion-handler patterns added.
Cmux Swift @Concurrent ✅ Passed The PR adds a new @ViewBuilder private var workspaceListLayoutPreview that is synchronous, performs no I/O, and mirrors the existing terminalLayoutPreview pattern. This change does not violate swif...
Cmux Swift File And Package Boundaries ✅ Passed Small focused bug fix (+13/-1 lines) to 503-line app composition root view, mirroring existing pattern without introducing responsibilities violations or boundary issues.
Cmux Swiftpm Lockfiles ✅ Passed PR includes CmuxMobileShellUI/Package.resolved and cmux.xcodeproj Package.resolved as new files, properly not ignored by .gitignore, complying with SwiftPM lockfile rules.
Cmux Swift Logging ✅ Passed No logging violations detected; PR contains only a compilation fix using @ViewBuilder to gate a DEBUG-only view reference, with no print, debugPrint, dump, NSLog, or Logger changes.
Cmux User-Facing Error Privacy ✅ Passed PR fixes a Release archive build failure by gating a DEBUG-only view reference through a @ViewBuilder. Changes are developer-only code structure with no user-facing error messages, alerts, or sensi...
Cmux Full Internationalization ✅ Passed PR changes only developer comments and structural code with no user-facing text strings or localization catalog modifications. The change gates a DEBUG-only view in a @ViewBuilder, which is explici...
Cmux Swiftui State Layout ✅ Passed PR adds no new state declarations, ObservableObject, @Published, GeometryReader, or render-time mutations. The new @ViewBuilder property mirrors the existing terminalLayoutPreview pattern and uses...
Cmux Architecture Rethink ✅ Passed Small correctness fix using conditional compilation (@ViewBuilder) to gate DEBUG-only WorkspaceListLayoutPreviewView reference, mirroring existing terminalLayoutPreview pattern with clear owner and...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR changes only gate a reference to WorkspaceListLayoutPreviewView—a DEBUG-only SwiftUI View (not NSWindow/NSPanel/Window/WindowGroup), explicitly documented as a test-only screenshot fixture—which...
Cmux Source Artifacts ✅ Passed PR modifies only one intentional source file (CMUXMobileRootView.swift) to fix a Release archive build bug. No artifacts added to source control; pre-existing artifact directories unchanged.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The workspaceListLayoutPreview property is a genuinely debug-only facility (screenshot preview) properly isolated with @ViewBuilder and #if compiler guard, following existing terminalLayoutPreview...

✏️ 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 fix-ios-release-archive

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.

@greptile-apps

greptile-apps Bot commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes a Release archive build failure caused by rootContent referencing WorkspaceListLayoutPreviewView() directly — a #if canImport(UIKit) && DEBUG-only simulator screenshot fixture — which compiled fine in Debug but broke the Release archive with "cannot find ... in scope", silently blocking TestFlight uploads.

  • Adds a workspaceListLayoutPreview @ViewBuilder gated with #if os(iOS) && DEBUG that compiles to EmptyView in Release, exactly mirroring the pre-existing terminalLayoutPreview pattern.
  • Routes rootContent through the new gated property instead of referencing WorkspaceListLayoutPreviewView() directly; Debug behavior and the file-length budget TSV are updated to match the ~12-line addition.

Confidence Score: 5/5

Safe to merge — one-file compile fix with no behavior change in Release or Debug.

The change is a minimal, compile-time-only patch: it adds a @ViewBuilder that is identical in shape to the pre-existing terminalLayoutPreview property, compiles to EmptyView in Release, and leaves Debug UI test preview behavior untouched. The TSV budget update is routine bookkeeping. No logic, state, or auth paths are modified.

No files require special attention.

Important Files Changed

Filename Overview
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/CMUXMobileRootView.swift Adds workspaceListLayoutPreview @ViewBuilder gated with #if os(iOS) && DEBUG to fix Release archive compile failure; mirrors existing terminalLayoutPreview pattern exactly. No logic changes.
.github/swift-file-length-budget.tsv Registers CMUXMobileRootView.swift at 503 lines to accommodate the ~12-line addition; also reflects a 6-line reduction in BrowserAutomation.swift. Both are routine budget bookkeeping.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[rootContent] --> B{shouldShowTerminalLayoutPreview?}
    B -- yes --> C[terminalLayoutPreview
#if os iOS && DEBUG
TerminalLayoutPreviewView
#else EmptyView]
    B -- no --> D{shouldShowWorkspaceListLayoutPreview?}
    D -- yes --> E[workspaceListLayoutPreview
#if os iOS && DEBUG
WorkspaceListLayoutPreviewView
#else EmptyView]
    D -- no --> F{shouldShowRestoringSession?}
    F -- yes --> G[RestoringSessionView]
    F -- no --> H{isAuthenticated?}
    H -- no --> I[SignInView]
    H -- yes --> J[...]

    style E fill:#d4edda,stroke:#28a745
    style C fill:#f0f0f0,stroke:#999
Loading
%%{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[rootContent] --> B{shouldShowTerminalLayoutPreview?}
    B -- yes --> C[terminalLayoutPreview
#if os iOS && DEBUG
TerminalLayoutPreviewView
#else EmptyView]
    B -- no --> D{shouldShowWorkspaceListLayoutPreview?}
    D -- yes --> E[workspaceListLayoutPreview
#if os iOS && DEBUG
WorkspaceListLayoutPreviewView
#else EmptyView]
    D -- no --> F{shouldShowRestoringSession?}
    F -- yes --> G[RestoringSessionView]
    F -- no --> H{isAuthenticated?}
    H -- no --> I[SignInView]
    H -- yes --> J[...]

    style E fill:#d4edda,stroke:#28a745
    style C fill:#f0f0f0,stroke:#999
Loading

Reviews (2): Last reviewed commit: "ci: refresh Swift file-length budget for..." | Re-trigger Greptile

This branch was successfully deployed

1 active deployment
Preview – cmux — 96959211 Deployed Jun 20, 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