Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1251,3 +1251,86 @@ jobs:
kill "$VDISPLAY_PERSISTENT_PID" >/dev/null 2>&1 || true
fi
rm -f /tmp/cmux-vdisplay-persistent.ready /tmp/cmux-vdisplay-persistent.id /tmp/cmux-vdisplay-persistent.log

ios-build:
# Deterministic iOS compile gate. The iOS app and the iOS-only CmuxMobile*
# packages are otherwise compiled ONLY in the non-required, flaky
# ios-simulator job (test-ios.yml), so an iOS-only compile break can merge
# green even though every required check passed. That is exactly how the
# @MainActor/nonisolated break in the composer image-decode path
# (TerminalComposerView) reached main. This job compiles the iOS app for the
# simulator WITHOUT running tests or booting a simulator, so it is
# deterministic (no virtual display, no sim boot) and safe to require.
# It runs on every PR and on push to main; make it a required status check.
runs-on: ${{ vars.MACOS_RUNNER_26 || 'warp-macos-26-arm64-6x' }}
timeout-minutes: 35
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive
Comment on lines +1273 to +1276

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify checkout hardening mismatch between ci.yml ios-build and test-ios.yml jobs.
rg -n -C3 'ios-build:|name: Checkout|persist-credentials|submodules:' .github/workflows/ci.yml .github/workflows/test-ios.yml

Repository: manaflow-ai/cmux

Length of output: 9720


Add persist-credentials: false to the ios-build checkout step for credential hardening.

The checkout in this job leaves credentials persisted in the local git config by default, increasing token exposure in subsequent steps. This differs from the hardened pattern used in test-ios.yml. Add persist-credentials: false to align with security best practices.

Suggested patch
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
+         persist-credentials: false
          submodules: recursive
📝 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.

Suggested change
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
submodules: recursive
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 1268-1271: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 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/ci.yml around lines 1268 - 1271, Add `persist-credentials:
false` to the `with:` section of the Checkout step in the ios-build job that
uses `actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd`. This option
prevents git credentials from being persisted in the local git config, reducing
token exposure in subsequent job steps and aligning with the security hardening
pattern used in test-ios.yml.

Source: Linters/SAST tools


- name: Select Xcode
run: |
set -euo pipefail
if [ -d "/Applications/Xcode.app/Contents/Developer" ]; then
XCODE_DIR="/Applications/Xcode.app/Contents/Developer"
else
XCODE_APP="$(find /Applications -maxdepth 1 -name 'Xcode*.app' -print 2>/dev/null | sort | tail -n 1 || true)"
if [ -n "$XCODE_APP" ]; then
XCODE_DIR="$XCODE_APP/Contents/Developer"
else
echo "No Xcode.app found under /Applications" >&2
exit 1
fi
fi
echo "DEVELOPER_DIR=$XCODE_DIR" >> "$GITHUB_ENV"
export DEVELOPER_DIR="$XCODE_DIR"
xcodebuild -version

- name: Provision GhosttyKit
run: |
# The iOS app links GhosttyKit (incl. its iOS + iOS-simulator slices)
# via a local-path binaryTarget, so it must exist before resolve.
# Mirror the ios-simulator job exactly: ensure-ghosttykit.sh manages
# its own $HOME/.cache/cmux/ghosttykit cache and writes the framework
# where the iOS workspace expects it. Do NOT add an actions/cache step
# keyed on repo-root GhosttyKit.xcframework here: ensure-ghosttykit.sh
# does not populate that path, and the shared ghosttykit-<sha> key is
# owned by the macOS jobs that use download-prebuilt (a real dir), so
# caching a symlink/absent path from this job would poison that key.
./scripts/install-zig-ci.sh
./scripts/ensure-ghosttykit.sh

- name: Cache Swift packages
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: .spm-cache-ios
key: spm-ios-${{ hashFiles('ios/cmuxPackage/Package.resolved') }}
restore-keys: spm-ios-
Comment thread
cursor[bot] marked this conversation as resolved.

- name: Resolve packages
run: |
set -euo pipefail
xcodebuild -workspace ios/cmux.xcworkspace \
-scheme cmux-ios \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath /tmp/cmux-ios-build \
-clonedSourcePackagesDirPath .spm-cache-ios \
-resolvePackageDependencies

- name: Build iOS app for simulator (compile only, no tests, no boot)
run: |
set -euo pipefail
# build-for-testing compiles the app and the test targets for the
# simulator using a GENERIC destination, so nothing is booted and the
# result is deterministic. This catches the Swift compile breaks
# (actor isolation, missing await, etc.) that only manifest in the iOS
# build and are invisible to the macOS unit-test job.
xcodebuild -workspace ios/cmux.xcworkspace \
-scheme cmux-ios \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath /tmp/cmux-ios-build \
-clonedSourcePackagesDirPath .spm-cache-ios \
CODE_SIGNING_ALLOWED=NO \
build-for-testing

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify ios-build resolves packages explicitly, then builds without -disableAutomaticPackageResolution.
rg -n -C4 'name: Resolve packages|resolvePackageDependencies|name: Build iOS app for simulator|build-for-testing|disableAutomaticPackageResolution' .github/workflows/ci.yml

Repository: manaflow-ai/cmux

Length of output: 7893


🌐 Web query:

xcodebuild -disableAutomaticPackageResolution flag documentation

💡 Result:

The xcodebuild flag -disableAutomaticPackageResolution is used to prevent the build system from automatically resolving or updating Swift package dependencies to versions other than those explicitly recorded in the Package.resolved file [1][2][3]. By using this flag, you ensure that your CI pipeline or build environment strictly adheres to the state defined in the Package.resolved file [4]. This is a common best practice for CI/CD workflows to prevent unexpected dependency changes and to ensure build reproducibility [4][5]. Key points regarding this flag: - Functionality: It forces xcodebuild to rely on the existing Package.resolved file. If the project's dependencies are out of sync with this file, the build will typically fail rather than attempting to automatically resolve the differences [6][5]. - Usage: It is frequently paired with -onlyUsePackageVersionsFromResolvedFile, which serves a similar purpose [1][2][3]. - CI/CD Context: It is standard to include this flag in CI environments to guarantee that the code being tested uses the exact versions of dependencies that were vetted and committed to source control [4]. If you encounter an error stating that an out-of-date resolved file was detected, this indicates that your Package.resolved file does not match your current project dependency configuration [6][5]. In such cases, you must update the Package.resolved file in your local development environment and commit the changes to your repository before the CI can proceed successfully [4][6].

Citations:


🏁 Script executed:

# Verify line numbers in the snippet match the comment range
sed -n '1328,1342p' .github/workflows/ci.yml

Repository: manaflow-ai/cmux

Length of output: 528


Add -disableAutomaticPackageResolution to prevent implicit package resolution in iOS build step.

Line 1320 explicitly resolves packages, but the subsequent build-for-testing at line 1336 omits -disableAutomaticPackageResolution, creating inconsistency with all other build steps in the workflow and risking non-deterministic behavior.

Suggested patch
           xcodebuild -workspace ios/cmux.xcworkspace \
             -scheme cmux-ios \
             -destination 'generic/platform=iOS Simulator' \
             -derivedDataPath /tmp/cmux-ios-build \
             -clonedSourcePackagesDirPath .spm-cache-ios \
+            -disableAutomaticPackageResolution \
             CODE_SIGNING_ALLOWED=NO \
             build-for-testing
🤖 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/ci.yml around lines 1328 - 1342, The iOS simulator build
step using xcodebuild with the build-for-testing target is missing the
-disableAutomaticPackageResolution flag, creating inconsistency with the package
resolution approach used in other build steps. Add
-disableAutomaticPackageResolution to the xcodebuild command arguments in the
"Build iOS app for simulator" step to ensure deterministic behavior and align
with the explicit package resolution pattern established elsewhere in the
workflow.

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.

P1 test-ios.yml push trigger described but not added

The PR description lists "test-ios.yml also re-runs on push to main (iOS paths) for post-merge detection" as one of the explicit goals of this change. However, test-ios.yml was not modified — its on: block still only contains pull_request (paths-filtered) and workflow_dispatch. A push to main that touches iOS paths therefore still will not trigger the simulator test matrix, leaving the described post-merge detection capability absent despite the PR stating it was included.

Loading