Skip to content

engine: add Engine.Shutdown honoring shutdownAction#32

Merged
bilby91 merged 2 commits into
mainfrom
shutdown-action
May 10, 2026
Merged

engine: add Engine.Shutdown honoring shutdownAction#32
bilby91 merged 2 commits into
mainfrom
shutdown-action

Conversation

@bilby91

@bilby91 bilby91 commented May 10, 2026

Copy link
Copy Markdown
Member

Summary

  • New `Engine.Shutdown(ctx, *Workspace) error` consults the workspace's `shutdownAction` and tears down accordingly.
  • `Engine.Down` stays the explicit "always teardown" path — DAP and existing callers are unaffected.

Mapping (per spec)

`shutdownAction` Behavior
`none` No-op; container left running.
`stop` / `stopContainer` / unset (image/build) Stop container, keep it for fast restart.
`stopCompose` / unset (compose) Stop the project. Currently approximated with a primary-container stop until #10 adds a `ComposeStop` primitive — same observable behavior, just not project-wide yet.

Closes #22.

Test plan

Unit (`shutdown_test.go`): all six branches exercised against the in-memory `fakeRuntime` — `none` no-op, explicit `stopContainer`, default for image, `stopCompose` for compose, `stopCompose` fallback when set on a non-compose workspace, nil-workspace rejection.

Integration (`test/integration/shutdown_action_test.go`): Up against the alpine test image with each action, then assert container state via `InspectContainer`:

  • `none` → still `running`.
  • `stopContainer` → not running, container record preserved.

The latter also serves as a regression test for the "stop without remove" contract.

  • `go test ./...`
  • `go vet ./...`, gofmt clean
  • `go build -tags=integration ./test/integration/...`

Why a new method instead of changing `Down`?

`Down` already has callers (DAP, the integration suite) that expect unconditional teardown. Making it silently no-op for `shutdownAction: none` would surprise them. `Shutdown` is the spec-faithful complement; consumers who want spec semantics call it; consumers who want "gone now" call `Down`.

Summary by CodeRabbit

  • New Features

    • Added configurable shutdown behavior via devcontainer.json's shutdownAction with modes: none (leave running), stopContainer (stop container), and stopCompose (stop compose services). Default behavior chosen based on workspace type.
  • Tests

    • Added unit and integration tests covering each shutdownAction, defaulting, compose vs non-compose behavior, and input validation.

Review Change Stack

Engine.Down stays the explicit teardown path: callers calling
Down still get unconditional stop (and Remove) regardless of the
spec field. Engine.Shutdown is the new spec-aware companion for
editor-close / idle-shutdown semantics:

  - "none": no-op, container left running.
  - "stop" / "stopContainer" / unset (image/build): stop without
    remove.
  - "stopCompose" / unset (compose): stop without remove (project-
    level Stop is approximated with primary-container stop until #10
    adds a ComposeStop primitive).

Closes #22.

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

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds Engine.Shutdown(ctx, ws) which validates inputs, resolves an effective shutdownAction (from config or defaulting: stopCompose for compose workspaces, stopContainer otherwise), and dispatches to shutdownStopContainer or shutdownStopCompose (ShutdownNone is a no-op). Unit and integration tests exercise behavior and input validation.

Changes

Engine.Shutdown Implementation

Layer / File(s) Summary
Public API
down.go
Engine.Shutdown(ctx, ws) validates ctx/ws, computes effectiveShutdownAction(ws), and dispatches to shutdown helpers; imports config for action enums.
Helper Functions
down.go
effectiveShutdownAction returns config action or defaults by workspace type; shutdownStopContainer stops container by ID and treats not-found as success; shutdownStopCompose stops the compose primary container or falls back to container stop.
Unit Tests
shutdown_test.go
newTestWorkspace helper and tests covering: none no-op, stopContainer single stop, default empty action for non-compose, stopCompose primary stop, fallback for non-compose, and input validation for nil/empty workspace/container.
Integration Tests
test/integration/shutdown_action_test.go
Integration tests (//go:build integration) asserting shutdownAction: none leaves container running and shutdownAction: stopContainer stops the container; tests skip in short mode.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 A shutdown action now comes to call,
To choose how containers will fall,
Leave running, stop quick, or compose with a trick—
The engine now honors them all! 🎪

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% 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 'engine: add Engine.Shutdown honoring shutdownAction' clearly and concisely summarizes the main change: adding a Shutdown method that respects the shutdownAction configuration.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #22: Engine.Shutdown now branches on shutdownAction (none, stopContainer, stopCompose) per spec, with comprehensive unit and integration tests validating each behavior path.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing Engine.Shutdown and its validation tests; no unrelated modifications to other engine methods or configuration parsing are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch shutdown-action

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🤖 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 `@down.go`:
- Around line 142-144: The Shutdown path currently only checks ws for nil but
later dereferences ws.Container.ID and can panic; update Engine.Shutdown (and
the similar check around the second dispatch at the 170-172 area) to validate
that ws.Container is non-nil before proceeding and return a clear error (e.g.,
fmt.Errorf("Engine.Shutdown: Workspace.Container is required") or similar)
instead of continuing; locate the checks around ws == nil and add a guard that
checks if ws.Container == nil and fails fast, referencing Workspace.Container
and ws.Container.ID in your change so you prevent nil-pointer dereferences.
- Around line 185-189: The current shutdownAction=stopCompose path only calls
shutdownStopContainer(ctx, ws) which stops just the primary container and leaves
sibling services running; update the implementation so stopCompose performs a
project-level stop by iterating all containers/services in the workspace or
invoking the Compose runtime's project-stop API (e.g., call a
ComposeRuntime.StopProject/Stop(ctx, project) if available) instead of
shutdownStopContainer; modify or add a function (e.g.,
shutdownStopComposeProject or extend shutdownStopContainer) to enumerate ws
services/containers and stop each one (or call the compose project stop API) to
ensure all sibling services are stopped.
🪄 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

Run ID: 708d21e0-4a3e-4e7d-8a57-383d00de130a

📥 Commits

Reviewing files that changed from the base of the PR and between b4bec75 and 633668d.

📒 Files selected for processing (3)
  • down.go
  • shutdown_test.go
  • test/integration/shutdown_action_test.go

Comment thread down.go
Comment thread down.go
Validates ws.Container and ws.Container.ID up front so the dispatch
paths can dereference safely (CodeRabbit #32). Tests cover both
nil-Container and empty-ID cases.

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

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

🤖 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 `@down.go`:
- Around line 130-132: The doc comment for "stopCompose" incorrectly claims it
performs a project-level `docker compose stop`; update the comment to state that
the current implementation (stopCompose) only stops the primary container as an
approximation of a full compose stop, and mention that callers should use Down
with Remove=true for full teardown; optionally add a TODO in the comment
pointing to implementing full project-level stopping in the future.
🪄 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

Run ID: 52e12cd4-0e38-4813-afa4-b07e28eab898

📥 Commits

Reviewing files that changed from the base of the PR and between 633668d and 2996e0f.

📒 Files selected for processing (2)
  • down.go
  • shutdown_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • shutdown_test.go

Comment thread down.go
@bilby91 bilby91 merged commit ad340b0 into main May 10, 2026
5 checks passed
@bilby91 bilby91 deleted the shutdown-action branch May 11, 2026 17:16
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.

shutdownAction: parsed but not enforced at Down/Stop

1 participant