refactor(sidecars): bundle is the only shape (PRD 0024 chunk 5)
The CLAUDE_BOTTLE_SIDECAR_BUNDLE feature flag is gone. Every
bottle ships with the agent + bundle pair — no opt-in, no legacy
four-sidecar fallback.
Changes:
- Renderer (compose.py): bottle_plan_to_compose unconditionally
emits {agent, sidecars}. Deleted _pipelock_service,
_git_gate_service, _egress_service, _supervise_service helpers.
_agent_service.depends_on collapses to ["sidecars"].
- sidecar_bundle.py: deleted sidecar_bundle_enabled (the flag
parser). SIDECAR_BUNDLE_IMAGE + container-name helper stay.
- pipelock_apply.py: docker cp + docker restart now target
sidecar_bundle_container_name(slug). Bundle restart bounces
all four daemons together (per-daemon reload is the eventual
feature, not v1).
- Per-sidecar modules trimmed:
- egress.py: dropped EGRESS_IMAGE, EGRESS_DOCKERFILE,
build_egress_image, egress_url. Kept EGRESS_PORT, CA paths,
egress_container_name (still used by the renderer's network
aliases).
- git_gate.py: dropped GIT_GATE_IMAGE, GIT_GATE_DOCKERFILE,
build_git_gate_image. Kept git_gate_host + GIT_GATE_PORT.
- supervise.py: dropped SUPERVISE_IMAGE, SUPERVISE_DOCKERFILE,
build_supervise_image, supervise_url.
- Deleted Dockerfile.{egress,git-gate,supervise}. The bundle's
Dockerfile.sidecars is the only sidecar image now.
- test_compose.py: deleted TestPipelockAlwaysPresent,
TestConditionalGitGate, TestConditionalEgress,
TestConditionalSupervise, TestFullMatrix (legacy-shape only),
TestSidecarBundleFlag (flag is gone). TestSidecarBundleShape
drops its patch.dict wrapper. TestAgentAlwaysPresent's
depends_on cases collapse to one.
- test_pipelock_apply.py: bringup container name uses
sidecar_bundle_container_name(slug) to match the production
target.
- README.md Architecture section rewritten to describe the
agent + bundle pair.
Net: -626 lines.
Test status: 498 unit + 27 integration + 1 skipped (chunk-4
pending — superseded by this chunk's rewrite). Locally verified
end-to-end bottle launch produces exactly 2 containers
(claude-bottle-<slug> + claude-bottle-sidecars-<slug>).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,56 +1,39 @@
|
||||
"""DockerGitGate — the Docker-specific lifecycle for the per-agent
|
||||
git-gate sidecar (PRD 0008). Inherits the platform-agnostic prepare
|
||||
step (upstream lift + entrypoint/hook render) from `GitGate`."""
|
||||
"""DockerGitGate — Docker-flavored git-gate config (PRD 0008).
|
||||
Inherits the platform-agnostic prepare step (upstream lift +
|
||||
entrypoint/hook render) from `GitGate`. The git-gate daemon runs
|
||||
inside the sidecar bundle (PRD 0024); this module just holds the
|
||||
in-container paths the renderer's bind-mounts target."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from ...git_gate import GitGate
|
||||
from . import util as docker_mod
|
||||
|
||||
|
||||
GIT_GATE_IMAGE = os.environ.get(
|
||||
"CLAUDE_BOTTLE_GIT_GATE_IMAGE",
|
||||
"claude-bottle-git-gate:latest",
|
||||
)
|
||||
|
||||
GIT_GATE_DOCKERFILE = "Dockerfile.git-gate"
|
||||
|
||||
GIT_GATE_ENTRYPOINT_IN_CONTAINER = "/git-gate-entrypoint.sh"
|
||||
GIT_GATE_HOOK_IN_CONTAINER = "/etc/git-gate/pre-receive"
|
||||
GIT_GATE_ACCESS_HOOK_IN_CONTAINER = "/etc/git-gate/access-hook"
|
||||
GIT_GATE_CREDS_DIR_IN_CONTAINER = "/git-gate/creds"
|
||||
|
||||
# git daemon's default listening port. Surfaced as a constant because
|
||||
# integration tests probe the gate on it.
|
||||
# git daemon's default listening port.
|
||||
GIT_GATE_PORT = 9418
|
||||
|
||||
# Repo root, for `docker build` context. Resolved from this file's
|
||||
# location: claude_bottle/backend/docker/git_gate.py → repo root.
|
||||
_REPO_DIR = str(Path(__file__).resolve().parent.parent.parent.parent)
|
||||
|
||||
|
||||
def git_gate_container_name(slug: str) -> str:
|
||||
"""The legacy per-sidecar container name. Kept as a function so
|
||||
the renderer can register it as a docker-network alias on the
|
||||
bundle — any code still dialing `claude-bottle-git-gate-<slug>`
|
||||
resolves to the bundle's IP."""
|
||||
return f"claude-bottle-git-gate-{slug}"
|
||||
|
||||
|
||||
def git_gate_host(slug: str) -> str:
|
||||
"""The hostname the agent's git client should connect to (same as
|
||||
the container name — Docker's embedded DNS resolves it on the
|
||||
`--internal` network)."""
|
||||
"""The hostname the agent's git client connects to. Resolves via
|
||||
the bundle's network alias to the bundle container, where the
|
||||
git-gate daemon listens on GIT_GATE_PORT."""
|
||||
return git_gate_container_name(slug)
|
||||
|
||||
|
||||
def build_git_gate_image() -> None:
|
||||
"""Build the git-gate image from `Dockerfile.git-gate`. Called by
|
||||
`DockerGitGate.start`; exposed at module level so integration
|
||||
tests can build it without running the full launch pipeline."""
|
||||
docker_mod.build_image(GIT_GATE_IMAGE, _REPO_DIR, dockerfile=GIT_GATE_DOCKERFILE)
|
||||
|
||||
|
||||
class DockerGitGate(GitGate):
|
||||
"""Docker-flavored GitGate: inherits `.prepare()` from the base.
|
||||
Container lifecycle is owned by compose; per-container
|
||||
`.start()` / `.stop()` were removed in PRD 0024 chunk 3."""
|
||||
The git-gate daemon's container lifecycle is owned by the
|
||||
sidecar bundle (PRD 0024)."""
|
||||
|
||||
Reference in New Issue
Block a user