Files
bot-bottle/claude_bottle/backend/docker/git_gate.py
T
didericis 539234f29e
test / unit (pull_request) Successful in 21s
test / integration (pull_request) Successful in 41s
refactor(sidecars): drop vestigial start/stop methods (PRD 0024 chunk 3)
Compose-up has owned per-container lifecycle since PRD 0018 ch3;
the .start() / .stop() methods on DockerPipelockProxy /
DockerEgress / DockerGitGate / DockerSupervise (and their
abstractmethod declarations in the four base ABCs) were already
documented as vestigial. With the bundle path in flight
(PRD 0024 ch2), they are truly dead — collapse to nothing.

Changes:
- Removed start/stop methods from the four DockerSidecar
  classes. Plan dataclasses, image/path constants,
  container-name helpers, and the .prepare() methods all stay
  (the renderer + apply path still need them).
- Removed the matching @abstractmethod declarations in the
  base ABCs so concrete subclasses don't have to stub them.
- launch.launch() and prepare.resolve_plan() no longer take
  proxy/git_gate/egress/supervise instance parameters. backend.py
  loses the four instance attributes it threaded through.
  prepare.resolve_plan() instantiates the four classes itself
  to call their .prepare() methods.
- Deleted four integration tests that only exercised the
  removed lifecycle: test_pipelock_sidecar_smoke,
  test_supervise_sidecar, test_git_gate_sidecar,
  test_git_gate_mirror.
- Dropped the .stop-idempotency case in test_orphan_cleanup;
  the network-cleanup cases stay (those test real production
  code).
- Marked test_pipelock_apply @skip pending chunk 4 — its
  bringup helper used .start; chunk 4 rewrites it with direct
  `docker run`.

Dockerfile deletion deferred to chunk 5 (when the bundle flag
default flips) — the legacy compose path still needs
Dockerfile.{egress,git-gate,supervise} until then.

Net: 708 lines removed, 80 added.

533 unit tests + 27 integration tests passing (5 skipped: the
chunk-4-pending case + existing GITEA_ACTIONS guards).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 01:01:10 -04:00

57 lines
1.9 KiB
Python

"""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`."""
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_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:
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)."""
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."""