feat(provider): add Apple container driver#749
Conversation
✅ Deploy Preview for devsydev canceled.
|
📝 WalkthroughWalkthroughThe 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. ChangesApple container support
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
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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. Comment |
✅ Deploy Preview for images-devsy-sh canceled.
|
6323cbf to
bcee7a8
Compare
There was a problem hiding this comment.
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
📒 Files selected for processing (51)
cmd/internal/agentworkspace/build.gocmd/internal/agentworkspace/delete.gocmd/internal/agentworkspace/logs.gocmd/internal/agentworkspace/status.gocmd/internal/agentworkspace/stop.gocmd/internal/agentworkspace/up.gocmd/internal/container_tunnel.gocmd/internal/runusercommands.gocmd/workspace/exec.gopkg/agent/delivery/factory.gopkg/agent/delivery/factory_test.gopkg/apple/helper.gopkg/apple/helper_test.gopkg/apple/integration_test.gopkg/apple/types.gopkg/apple/types_test.gopkg/devcontainer/build.gopkg/devcontainer/compose.gopkg/devcontainer/inspect.gopkg/devcontainer/prebuild.gopkg/devcontainer/run.gopkg/devcontainer/setup.gopkg/devcontainer/single.gopkg/driver/apple/build.gopkg/driver/apple/build_test.gopkg/driver/apple/capability_test.gopkg/driver/apple/client.gopkg/driver/apple/driver.gopkg/driver/apple/lifecycle.gopkg/driver/apple/lifecycle_test.gopkg/driver/apple/runargs.gopkg/driver/apple/runargs_test.gopkg/driver/docker.gopkg/driver/docker/docker.gopkg/driver/docker/lifecycle.gopkg/driver/docker/runargs.gopkg/driver/docker/runargs_test.gopkg/driver/drivercreate/create.gopkg/driver/kubernetes/driver.gopkg/driver/types.gopkg/options/resolve.gopkg/options/resolve_test.gopkg/provider/parse.gopkg/provider/provider.gopkg/workspace/exec.gopkg/workspace/exec_apple.gopkg/workspace/exec_shared_test.gopkg/workspace/exec_test.goproviders/apple/provider.yamlproviders/providers.goproviders/providers_test.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.
There was a problem hiding this comment.
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 winAssociate the switch with its label.
Add
id="single-machine"to<Switch>andfor="single-machine"to<Label>. This gives the Bits UIswitchan 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 winAssert 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
⛔ Files ignored due to path filters (1)
desktop/src/renderer/public/icons/providers/apple.svgis excluded by!**/*.svg
📒 Files selected for processing (53)
cmd/internal/agentworkspace/build.gocmd/internal/agentworkspace/delete.gocmd/internal/agentworkspace/logs.gocmd/internal/agentworkspace/status.gocmd/internal/agentworkspace/stop.gocmd/internal/agentworkspace/up.gocmd/internal/container_tunnel.gocmd/internal/runusercommands.gocmd/workspace/exec.godesktop/src/renderer/src/lib/components/provider/ProviderIcon.sveltedesktop/src/renderer/src/lib/components/provider/ProviderWizard.sveltepkg/agent/delivery/factory.gopkg/agent/delivery/factory_test.gopkg/apple/helper.gopkg/apple/helper_test.gopkg/apple/integration_test.gopkg/apple/types.gopkg/apple/types_test.gopkg/devcontainer/build.gopkg/devcontainer/compose.gopkg/devcontainer/inspect.gopkg/devcontainer/prebuild.gopkg/devcontainer/run.gopkg/devcontainer/setup.gopkg/devcontainer/single.gopkg/driver/apple/build.gopkg/driver/apple/build_test.gopkg/driver/apple/capability_test.gopkg/driver/apple/client.gopkg/driver/apple/driver.gopkg/driver/apple/lifecycle.gopkg/driver/apple/lifecycle_test.gopkg/driver/apple/runargs.gopkg/driver/apple/runargs_test.gopkg/driver/docker.gopkg/driver/docker/docker.gopkg/driver/docker/lifecycle.gopkg/driver/docker/runargs.gopkg/driver/docker/runargs_test.gopkg/driver/drivercreate/create.gopkg/driver/kubernetes/driver.gopkg/driver/types.gopkg/options/resolve.gopkg/options/resolve_test.gopkg/provider/parse.gopkg/provider/provider.gopkg/workspace/exec.gopkg/workspace/exec_apple.gopkg/workspace/exec_shared_test.gopkg/workspace/exec_test.goproviders/apple/provider.yamlproviders/providers.goproviders/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
Summary
Adds a first-class Apple
containerprovider — 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 (thedatabase/sql/driveridiom).Two commits, reviewable in order:
refactor(driver)— capability interfaces + context threading (behavior-preserving for docker/kubernetes/custom).feat(provider)— the Apple driver, provider YAML, wiring, and tests.Driver design
Driver— core lifecycle only.ImageDriver(renamed fromDockerDriver) — build/run a local OCI image; Docker and Apple.RunOptionsDriver— run fromRunOptions; Kubernetes, Custom.ComposeDriver/DockerHelperProvider— Docker-only capabilities, detected by type assertion (no more error-returning stubs).Apple driver
pkg/apple—AppleHelpertranslates to thecontainerCLI (grouped subcommands, JSON parsing rather than Go-template--format) and maps Apple's inspect JSON onto the Docker-shaped config structs.pkg/driver/apple— implementsImageDriverbehind anappleClientinterface (unit-testable with a mock). SupportsROSETTA, warns on unsupported GPU requirements, UID/GID remap is a no-op (VM + virtio-fs).providers/apple/provider.yaml— declarativeagent.driver: apple, embedded + registered.container execthat installs and launches the agent, which keeps the container alive).darwin/arm64only; verifies thecontainer systemservice is running.Verification
Verified end-to-end on macOS 26.5 /
container1.1.0:up,exec, Dockerfilebuild,--recreate,stop/restart,delete. Build/vet/lint clean.Notes for reviewers
containerneeds macOS 26 + Apple silicon (no such runner). Unit tests are cross-platform; integration is gated behindDEVSY_APPLE_E2E=1.pkg/compose/TestHelperSuite,e2e/TestRunE2ETests) are pre-existing and unrelated — confirmed identical on a clean tree (git stash).deliverPostStart → legacyInjectfallback inpkg/devcontainer/setup.gocan 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"
apple.svgicon to the asset host (referenced byprovider.yaml).sites/docs-devsy-sh.Summary by CodeRabbit
New Features
Improvements
Tests