Skip to content

feat(provider): add Apple container driver#749

Merged
skevetter merged 1 commit into
mainfrom
lethal-cobra
Jul 26, 2026
Merged

feat(provider): add Apple container driver#749
skevetter merged 1 commit into
mainfrom
lethal-cobra

Conversation

@skevetter

@skevetter skevetter commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a first-class Apple container provider — Apple's tool for running Linux containers as lightweight VMs on Apple silicon Macs (macOS 26+) — as a peer of the Docker, Podman, and Kubernetes providers. Along the way, the driver abstraction is refactored into small capability interfaces (the database/sql/driver idiom).

Two commits, reviewable in order:

  1. refactor(driver) — capability interfaces + context threading (behavior-preserving for docker/kubernetes/custom).
  2. feat(provider) — the Apple driver, provider YAML, wiring, and tests.

Driver design

  • Driver — core lifecycle only.
  • ImageDriver (renamed from DockerDriver) — build/run a local OCI image; Docker and Apple.
  • RunOptionsDriver — run from RunOptions; Kubernetes, Custom.
  • ComposeDriver / DockerHelperProvider — Docker-only capabilities, detected by type assertion (no more error-returning stubs).

Apple driver

  • pkg/appleAppleHelper translates to the container CLI (grouped subcommands, JSON parsing rather than Go-template --format) and maps Apple's inspect JSON onto the Docker-shaped config structs.
  • pkg/driver/apple — implements ImageDriver behind an appleClient interface (unit-testable with a mock). Supports ROSETTA, warns on unsupported GPU requirements, UID/GID remap is a no-op (VM + virtio-fs).
  • providers/apple/provider.yaml — declarative agent.driver: apple, embedded + registered.
  • Agent delivery is shell-based — the correct mechanism for Apple's VM model (a single container exec that installs and launches the agent, which keeps the container alive).
  • Guards: darwin/arm64 only; verifies the container system service is running.

Verification

Verified end-to-end on macOS 26.5 / container 1.1.0: up, exec, Dockerfile build, --recreate, stop/restart, delete. Build/vet/lint clean.

Notes for reviewers

  • CI cannot exercise this — Apple container needs macOS 26 + Apple silicon (no such runner). Unit tests are cross-platform; integration is gated behind DEVSY_APPLE_E2E=1.
  • docker-compose is intentionally unsupported on this driver (returns a clear error).
  • Two suite failures (pkg/compose/TestHelperSuite, e2e/TestRunE2ETests) are pre-existing and unrelated — confirmed identical on a clean tree (git stash).
  • Known follow-up (pre-existing, not introduced here): the shared deliverPostStart → legacyInject fallback in pkg/devcontainer/setup.go can mask a native-delivery failure when the legacy path opportunistically succeeds (affects Kubernetes/remote-Docker too). Worth a separate issue.

Cosmetic TODO before "ready for review"

  • Add the apple.svg icon to the asset host (referenced by provider.yaml).
  • Optional: a user-facing docs page under sites/docs-devsy-sh.

Summary by CodeRabbit

  • New Features

    • Added Apple container support on Apple silicon, including a built-in Apple provider and Apple-specific runtime behavior.
    • Added Apple lifecycle, image build/pull/push/tag, execution, logs, and inspection capabilities.
    • Extended configuration options for the Apple container command, environment, and optional Rosetta.
  • Improvements

    • Runner and workspace operations now consistently honor request cancellation context.
    • Updated container execution to use a unified, image-based runtime interface.
    • Added Apple provider visuals/preset in the desktop UI.
  • Tests

    • Added unit, integration (E2E-gated), and shared exec-behavior test coverage.

@netlify

netlify Bot commented Jul 25, 2026

Copy link
Copy Markdown

Deploy Preview for devsydev canceled.

Name Link
🔨 Latest commit bd6ca1c
🔍 Latest deploy log https://app.netlify.com/projects/devsydev/deploys/6a658ce3f8b53c00084ccf34

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds Apple container-provider support, including configuration, CLI helpers, image and lifecycle drivers, runtime selection, and tests. It also generalizes Docker-specific driver capabilities, propagates contexts through runner creation, and routes workspace commands through the selected container runtime.

Changes

Apple container support

Layer / File(s) Summary
Driver contracts and capability routing
pkg/driver/*, pkg/provider/*, pkg/options/*, pkg/agent/delivery/*
Adds Apple and image-driver interfaces, separates run-option capabilities, updates driver creation and delivery routing, and resolves Apple configuration values.
Apple CLI helper and inspect mapping
pkg/apple/*
Adds Apple container CLI execution, lifecycle and image operations, inspection conversion, state normalization, and related unit/integration tests.
Apple driver build and lifecycle
pkg/driver/apple/*
Adds Apple image building, run-argument construction, container lifecycle operations, image handling, and driver capability tests.
Workspace runtime abstraction
pkg/workspace/*
Adds Apple runtime selection and command/environment resolution, and shares exec and environment-probing behavior across runtimes.
Context and command wiring
cmd/internal/*, cmd/workspace/*, providers/*, desktop/src/renderer/src/lib/components/provider/*
Propagates contexts into runner creation, uses runtime-provided commands for execution, embeds the Apple provider configuration, and adds Apple provider UI metadata.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WorkspaceCommand
  participant NewContainerRuntime
  participant NewAppleDriver
  participant AppleHelper
  participant ContainerCLI
  WorkspaceCommand->>NewContainerRuntime: Select runtime from provider configuration
  NewContainerRuntime->>NewAppleDriver: Create Apple-backed runtime
  NewAppleDriver->>AppleHelper: Ensure container system is running
  AppleHelper->>ContainerCLI: Execute system status/start
  WorkspaceCommand->>AppleHelper: Execute container lifecycle or exec command
  AppleHelper->>ContainerCLI: Run container command
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a first-class Apple container driver/provider.
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.

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.

@netlify

netlify Bot commented Jul 25, 2026

Copy link
Copy Markdown

Deploy Preview for images-devsy-sh canceled.

Name Link
🔨 Latest commit bd6ca1c
🔍 Latest deploy log https://app.netlify.com/projects/images-devsy-sh/deploys/6a658ce3158ec400083e14b5

@skevetter
skevetter force-pushed the lethal-cobra branch 4 times, most recently from 6323cbf to bcee7a8 Compare July 25, 2026 04:55
@skevetter
skevetter marked this pull request as ready for review July 25, 2026 16:26

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

🤖 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 `@cmd/workspace/exec.go`:
- Around line 182-183: Preserve the selected runtime environment in the raw exec
path: update execOpts and execInContainer to carry and apply AppleRuntime’s
agent.apple.env alongside DockerCommand when creating the helper. Ensure the
runtime environment configured by runtime is not discarded for workspace exec
commands.

In `@pkg/apple/helper.go`:
- Around line 300-309: Update parseImageTag to detect an @ digest separator in
the final image path segment and return no tag for digest references before
applying strings.Cut on ":". Preserve the existing tag extraction behavior for
non-digest references, including registry ports.
- Around line 153-164: Update AppleHelper.WaitContainerRunning to distinguish
transient inspection failures and startup states from terminal container states.
After InspectContainers succeeds, return a non-nil error immediately when the
container status indicates it has exited or otherwise cannot become
stateRunning; retain polling for valid non-terminal states and preserve the
existing running success condition.

In `@pkg/workspace/exec_apple.go`:
- Around line 29-36: Change the provider-config error path in
NewContainerRuntime so it returns the load error instead of logging and
returning false, and propagate that error through every caller of
NewContainerRuntime. Preserve normal runtime selection while ensuring Apple
workspace configuration failures cannot fall back to Docker.

In `@pkg/workspace/exec.go`:
- Around line 205-208: Update pkg/workspace/exec.go at lines 205-208 to expose a
runtime invocation specification containing both the container command and host
environment, rather than only Command(). Update cmd/internal/runusercommands.go
at lines 395-398 to apply that environment to lifecycle helper execution, or
route it through the runtime, ensuring agent.apple.env is preserved for all
bypass paths.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 347712ae-c20b-48e8-adfb-f59f05823429

📥 Commits

Reviewing files that changed from the base of the PR and between 1b3d8d3 and bcee7a8.

📒 Files selected for processing (51)
  • cmd/internal/agentworkspace/build.go
  • cmd/internal/agentworkspace/delete.go
  • cmd/internal/agentworkspace/logs.go
  • cmd/internal/agentworkspace/status.go
  • cmd/internal/agentworkspace/stop.go
  • cmd/internal/agentworkspace/up.go
  • cmd/internal/container_tunnel.go
  • cmd/internal/runusercommands.go
  • cmd/workspace/exec.go
  • pkg/agent/delivery/factory.go
  • pkg/agent/delivery/factory_test.go
  • pkg/apple/helper.go
  • pkg/apple/helper_test.go
  • pkg/apple/integration_test.go
  • pkg/apple/types.go
  • pkg/apple/types_test.go
  • pkg/devcontainer/build.go
  • pkg/devcontainer/compose.go
  • pkg/devcontainer/inspect.go
  • pkg/devcontainer/prebuild.go
  • pkg/devcontainer/run.go
  • pkg/devcontainer/setup.go
  • pkg/devcontainer/single.go
  • pkg/driver/apple/build.go
  • pkg/driver/apple/build_test.go
  • pkg/driver/apple/capability_test.go
  • pkg/driver/apple/client.go
  • pkg/driver/apple/driver.go
  • pkg/driver/apple/lifecycle.go
  • pkg/driver/apple/lifecycle_test.go
  • pkg/driver/apple/runargs.go
  • pkg/driver/apple/runargs_test.go
  • pkg/driver/docker.go
  • pkg/driver/docker/docker.go
  • pkg/driver/docker/lifecycle.go
  • pkg/driver/docker/runargs.go
  • pkg/driver/docker/runargs_test.go
  • pkg/driver/drivercreate/create.go
  • pkg/driver/kubernetes/driver.go
  • pkg/driver/types.go
  • pkg/options/resolve.go
  • pkg/options/resolve_test.go
  • pkg/provider/parse.go
  • pkg/provider/provider.go
  • pkg/workspace/exec.go
  • pkg/workspace/exec_apple.go
  • pkg/workspace/exec_shared_test.go
  • pkg/workspace/exec_test.go
  • providers/apple/provider.yaml
  • providers/providers.go
  • providers/providers_test.go

Comment thread cmd/workspace/exec.go
Comment thread pkg/apple/helper.go
Comment thread pkg/apple/helper.go Outdated
Comment thread pkg/workspace/exec_apple.go Outdated
Comment thread pkg/workspace/exec.go
Add a first-class "apple" driver for Apple's `container` CLI, alongside
Docker/Podman/Kubernetes/Custom.

Driver interface refactor (idiomatic capability interfaces):
- rename DockerDriver -> ImageDriver (image build/run/inspect), implemented
  by both Docker and Apple
- split RunDevContainer off the base Driver into a RunOptionsDriver capability
- add ComposeDriver and DockerHelperProvider capability interfaces so
  compose/docker-helper support is expressed in the type system rather than
  runtime-error stubs
- thread context through driver construction

Apple driver:
- pkg/apple: AppleHelper (container CLI translation + JSON parsing) and a
  Streams-based Run API
- pkg/driver/apple: ImageDriver implementation, run-arg builder, build via
  `container build`, appleClient interface for unit-testable orchestration
- per-driver option resolution (agent.apple.path/rosetta/env)
- native shell agent delivery
- workspace exec routes through an AppleRuntime
- providers/apple/provider.yaml + registration
- desktop: apple provider preset and official Apple icon

Verified end-to-end on macOS 26 / container 1.1.0: up, exec, build, recreate,
stop/start, delete.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
desktop/src/renderer/src/lib/components/provider/ProviderWizard.svelte (1)

419-430: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Associate the switch with its label.

Add id="single-machine" to <Switch> and for="single-machine" to <Label>. This gives the Bits UI switch an explicit label and lets the label text activate the toggle.

🤖 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 `@desktop/src/renderer/src/lib/components/provider/ProviderWizard.svelte`
around lines 419 - 430, Add id="single-machine" to the Switch and set the
corresponding Label’s for attribute to "single-machine" in the Reuse machine
control, preserving the existing toggle behavior.
🧹 Nitpick comments (1)
pkg/driver/apple/runargs_test.go (1)

50-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the complete image/command tail.

This only verifies that two arguments follow the image; swapped or altered command values would still pass.

Proposed test hardening
-	// Image must precede the command, and both must be last.
-	if args[len(args)-3] != testImageRef {
-		t.Errorf("expected image before cmd, got tail: %v", args[len(args)-3:])
+	// Image must precede the exact command, and all must be last.
+	wantTail := []string{testImageRef, "-c", "sleep infinity"}
+	if len(args) < len(wantTail) {
+		t.Fatalf("args unexpectedly short: %v", args)
+	}
+	for i, want := range wantTail {
+		if got := args[len(args)-len(wantTail)+i]; got != want {
+			t.Errorf("unexpected image/command tail: got %v, want %v", args[len(args)-len(wantTail):], wantTail)
+			break
+		}
 	}
🤖 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 `@pkg/driver/apple/runargs_test.go` around lines 50 - 53, Strengthen the
assertion in the runargs test around the image/command tail to validate the
complete expected sequence, including the exact command and its arguments,
rather than checking only testImageRef. Preserve the existing ordering
requirement and retain the diagnostic tail output when the assertion fails.
🤖 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.

Outside diff comments:
In `@desktop/src/renderer/src/lib/components/provider/ProviderWizard.svelte`:
- Around line 419-430: Add id="single-machine" to the Switch and set the
corresponding Label’s for attribute to "single-machine" in the Reuse machine
control, preserving the existing toggle behavior.

---

Nitpick comments:
In `@pkg/driver/apple/runargs_test.go`:
- Around line 50-53: Strengthen the assertion in the runargs test around the
image/command tail to validate the complete expected sequence, including the
exact command and its arguments, rather than checking only testImageRef.
Preserve the existing ordering requirement and retain the diagnostic tail output
when the assertion fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 60f5fe0e-32f0-4334-a1b8-979c422b736b

📥 Commits

Reviewing files that changed from the base of the PR and between bcee7a8 and bd6ca1c.

⛔ Files ignored due to path filters (1)
  • desktop/src/renderer/public/icons/providers/apple.svg is excluded by !**/*.svg
📒 Files selected for processing (53)
  • cmd/internal/agentworkspace/build.go
  • cmd/internal/agentworkspace/delete.go
  • cmd/internal/agentworkspace/logs.go
  • cmd/internal/agentworkspace/status.go
  • cmd/internal/agentworkspace/stop.go
  • cmd/internal/agentworkspace/up.go
  • cmd/internal/container_tunnel.go
  • cmd/internal/runusercommands.go
  • cmd/workspace/exec.go
  • desktop/src/renderer/src/lib/components/provider/ProviderIcon.svelte
  • desktop/src/renderer/src/lib/components/provider/ProviderWizard.svelte
  • pkg/agent/delivery/factory.go
  • pkg/agent/delivery/factory_test.go
  • pkg/apple/helper.go
  • pkg/apple/helper_test.go
  • pkg/apple/integration_test.go
  • pkg/apple/types.go
  • pkg/apple/types_test.go
  • pkg/devcontainer/build.go
  • pkg/devcontainer/compose.go
  • pkg/devcontainer/inspect.go
  • pkg/devcontainer/prebuild.go
  • pkg/devcontainer/run.go
  • pkg/devcontainer/setup.go
  • pkg/devcontainer/single.go
  • pkg/driver/apple/build.go
  • pkg/driver/apple/build_test.go
  • pkg/driver/apple/capability_test.go
  • pkg/driver/apple/client.go
  • pkg/driver/apple/driver.go
  • pkg/driver/apple/lifecycle.go
  • pkg/driver/apple/lifecycle_test.go
  • pkg/driver/apple/runargs.go
  • pkg/driver/apple/runargs_test.go
  • pkg/driver/docker.go
  • pkg/driver/docker/docker.go
  • pkg/driver/docker/lifecycle.go
  • pkg/driver/docker/runargs.go
  • pkg/driver/docker/runargs_test.go
  • pkg/driver/drivercreate/create.go
  • pkg/driver/kubernetes/driver.go
  • pkg/driver/types.go
  • pkg/options/resolve.go
  • pkg/options/resolve_test.go
  • pkg/provider/parse.go
  • pkg/provider/provider.go
  • pkg/workspace/exec.go
  • pkg/workspace/exec_apple.go
  • pkg/workspace/exec_shared_test.go
  • pkg/workspace/exec_test.go
  • providers/apple/provider.yaml
  • providers/providers.go
  • providers/providers_test.go
🚧 Files skipped from review as they are similar to previous changes (40)
  • pkg/devcontainer/prebuild.go
  • providers/apple/provider.yaml
  • pkg/driver/apple/capability_test.go
  • cmd/internal/agentworkspace/delete.go
  • cmd/internal/container_tunnel.go
  • pkg/workspace/exec_test.go
  • pkg/driver/drivercreate/create.go
  • pkg/devcontainer/run.go
  • pkg/driver/apple/client.go
  • cmd/internal/agentworkspace/status.go
  • cmd/internal/agentworkspace/stop.go
  • pkg/driver/docker/runargs_test.go
  • pkg/driver/apple/build.go
  • cmd/internal/agentworkspace/build.go
  • providers/providers_test.go
  • pkg/provider/parse.go
  • pkg/devcontainer/build.go
  • providers/providers.go
  • pkg/driver/docker/docker.go
  • pkg/driver/docker/runargs.go
  • pkg/options/resolve.go
  • pkg/apple/types.go
  • pkg/agent/delivery/factory_test.go
  • pkg/driver/kubernetes/driver.go
  • pkg/apple/types_test.go
  • pkg/driver/types.go
  • pkg/devcontainer/single.go
  • pkg/driver/apple/driver.go
  • pkg/options/resolve_test.go
  • pkg/driver/docker/lifecycle.go
  • cmd/internal/agentworkspace/up.go
  • pkg/driver/apple/runargs.go
  • pkg/apple/integration_test.go
  • pkg/driver/docker.go
  • pkg/driver/apple/lifecycle.go
  • pkg/driver/apple/lifecycle_test.go
  • pkg/agent/delivery/factory.go
  • pkg/workspace/exec.go
  • pkg/apple/helper.go
  • pkg/devcontainer/inspect.go

@skevetter
skevetter merged commit 0c2ff12 into main Jul 26, 2026
67 checks passed
@skevetter
skevetter deleted the lethal-cobra branch July 26, 2026 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant