Skip to content

Fix Swift 6 main-actor isolation in RunApp; scan Swift via CodeQL - #23

Merged
glslang merged 2 commits into
mainfrom
fix/swift-codeql-mainactor
Jul 1, 2026
Merged

glslang merged 2 commits into
mainfrom
fix/swift-codeql-mainactor

Conversation

@glslang

@glslang glslang commented Jul 1, 2026 •

Copy link
Copy Markdown
Owner

Why

CodeQL's Swift analysis (default setup, autobuild) was failing on the code-scanning status page:

autobuild failed to run the build command: /usr/bin/swift build --package-path .../macos

Root cause: swift build fails under Swift 6 strict concurrency. RunApp calls @MainActor AppKit APIs (NSApplication.shared, setActivationPolicy, delegate, run(), reply(toApplicationShouldTerminate:), terminate) from nonisolated methods (start(), cleanupAndTerminate()). Newer local toolchains only warn, so it built locally but the stricter CI toolchain treated them as errors and the build (and thus the CodeQL Swift extraction) failed.

What

Code fix (macos/Sources/vmctl/main.swift)

  • Mark RunApp @MainActor — it is the NSApplicationDelegate, drives the AppKit run loop, and its VZVirtualMachine is created on / only used from the main queue.
  • The two VZVirtualMachineDelegate callbacks (guestDidStop, didStopWithError) implement a non-isolated protocol but fire on the VM's main delegate queue, so keep them nonisolated and hop via MainActor.assumeIsolated.
  • Build/start RunApp on the main actor from the synchronous @main run command.

Scanning (.github/workflows/codeql.yml)

  • New advanced CodeQL workflow scanning actions + swift, using an explicit swift build --package-path macos (manual build mode) instead of the unreliable autobuild — the "manual build command" GitHub recommends.
  • Least-privilege permissions (contents: read default; job elevates security-events: write).
  • Default setup (actions-only) has been disabled in repo settings in favour of this workflow.

Verification

  • swift build — succeeds, 0 errors, 0 warnings for the RunApp concurrency issues (only a pre-existing, non-fatal @Sendable capture warning in the install path remains).
  • scripts/Build-vmctl.sh (release + ad-hoc codesign) — Build complete!, binary signs and runs (vmctl help exit 0).
  • CodeQL Swift + actions runs on this PR validate the fix end to end.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added automated code scanning on push, pull requests, and a weekly schedule to help catch issues earlier.
  • Bug Fixes

    • Improved macOS VM start-up and shutdown handling for more reliable execution on the main thread.

CodeQL's Swift analysis (autobuild) failed because `swift build` errors
under Swift 6 strict concurrency: RunApp calls @mainactor AppKit APIs
(NSApplication.shared / setActivationPolicy / delegate / run() /
reply(toApplicationShouldTerminate:) / terminate) from nonisolated
methods. Newer toolchains only warn, so it built locally but broke CI.

RunApp is the NSApplicationDelegate and drives the AppKit run loop, and
its VM is created on and only used from the main queue, so mark the class
@mainactor. The two VZVirtualMachineDelegate callbacks (a non-isolated
protocol) fire on the VM's main delegate queue, so keep them nonisolated
and hop via MainActor.assumeIsolated. Build/start RunApp on the main
actor from the synchronous @main run command.

Add an advanced CodeQL workflow scanning actions + swift with an explicit
`swift build --package-path macos` (manual build mode) instead of the
unreliable autobuild. Default setup (actions-only) is disabled in repo
settings in favour of this workflow.

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

coderabbitai Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@glslang, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1b45e481-43a0-4f62-af3f-5fa0d18304df

📥 Commits

Reviewing files that changed from the base of the PR and between 12ca49b and 18edcb1.

📒 Files selected for processing (1)
  • .github/workflows/codeql.yml
📝 Walkthrough

Walkthrough

Adds a CodeQL GitHub Actions workflow analysing actions and swift languages on push, pull request, and schedule. Separately, adjusts macos/Sources/vmctl/main.swift so RunApp creation/start and VZVirtualMachineDelegate teardown callbacks explicitly execute on the main actor.

Changes

CodeQL Workflow

Layer / File(s) Summary
Workflow triggers, permissions, matrix, and steps
.github/workflows/codeql.yml
New workflow defines push/PR/schedule triggers, least-privilege permissions, concurrency cancellation, a language matrix (actions, swift), and steps for checkout, CodeQL init, conditional Swift build, and analysis.

Main-Actor Isolation Fix

Layer / File(s) Summary
RunApp creation and startup on main actor
macos/Sources/vmctl/main.swift
runVM now creates and starts RunApp inside MainActor.assumeIsolated, with updated @MainActor documentation on RunApp and its start() method.
Delegate teardown main-actor hop
macos/Sources/vmctl/main.swift
guestDidStop and virtualMachine(_:didStopWithError:) are now nonisolated and hop to the main actor via MainActor.assumeIsolated before calling cleanupAndTerminate().

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RunCommand as run command
  participant MainActor as Main Actor
  participant RunApp
  participant VM as VZVirtualMachine

  RunCommand->>MainActor: MainActor.assumeIsolated
  MainActor->>RunApp: create RunApp
  MainActor->>RunApp: start()
  RunApp->>VM: run VM
  VM-->>RunApp: guestDidStop / didStopWithError (nonisolated)
  RunApp->>MainActor: MainActor.assumeIsolated
  MainActor->>RunApp: cleanupAndTerminate()
Loading

Poem

A rabbit hops upon the main actor's thread,
CodeQL scans while VMs settle to bed,
No race, no fright, just isolation tight,
🐇✨ code sleeps soundly through the night.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the two main changes: Swift 6 main-actor isolation fixes in RunApp and adding CodeQL Swift scanning.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/swift-codeql-mainactor

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.

@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: 3

🤖 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/codeql.yml:
- Around line 42-43: The Checkout step in the CodeQL workflow is leaving the
default persisted GitHub credentials enabled, which is unnecessary for this job.
Update the actions/checkout usage in the checkout step to set
persist-credentials to false so the GITHUB_TOKEN is not retained for later steps
or nested tool invocations.
- Around line 23-26: Add a brief explanatory comment for the job-level
permissions override in the CodeQL workflow, since the `permissions` block
granting `security-events: write` is undocumented. Update the workflow near the
`permissions` section in the CodeQL job to explain why the elevated access is
required, matching the style of the top-level permissions comment.
- Line 43: Update the CodeQL workflow so the `actions/checkout` step is pinned
to a full commit SHA instead of `@v4`, while leaving the
`github/codeql-action/init` and `github/codeql-action/analyze` steps on `@v4`.
Use the existing workflow step identifiers in `.github/workflows/codeql.yml` to
locate the checkout action and replace only that reference.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b7efb555-afcd-4b1c-b891-398f20572f27

📥 Commits

Reviewing files that changed from the base of the PR and between 390737d and 12ca49b.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml
  • macos/Sources/vmctl/main.swift

Comment thread .github/workflows/codeql.yml
Comment thread .github/workflows/codeql.yml Outdated
Comment thread .github/workflows/codeql.yml Outdated
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

- Document the job-level security-events: write permission.
- Set persist-credentials: false on checkout (no step pushes).
- Pin actions/checkout to a commit SHA (v4.3.1); CodeQL actions stay on @v4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@glslang
glslang merged commit c9abc19 into main Jul 1, 2026
4 checks passed
@glslang
glslang deleted the fix/swift-codeql-mainactor branch July 1, 2026 16:18
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.

2 participants