0d696674e3
tracker-policy-pr / check-pr (pull_request) Successful in 16s
test / integration-docker (pull_request) Successful in 31s
test / unit (pull_request) Successful in 40s
test / integration-firecracker (pull_request) Failing after 2m36s
test / coverage (pull_request) Failing after 3m34s
The Firecracker integration + coverage jobs pull a prebuilt infra rootfs artifact (PRD 0069 Stage 2) versioned by a content hash of the Dockerfiles, bot_bottle/, and the guest init. Building that artifact (publish_infra -> docker build Dockerfile.gateway) has been broken since5ad3449, so the artifact was never published and the KVM runner's integration test 404'd on the pull — the failure this branch surfaced once it stopped falsely skipping. Two build-time bugs, both from5ad3449, neither exercised since: - pyproject.toml declared build-backend "setuptools.backends.legacy:build", which is not an importable module; `pip install /src/` failed with BackendUnavailable. Use the real backend, "setuptools.build_meta" (the project has proper [project] metadata + flat-layout autodiscovery). Not part of the artifact hash, so this alone doesn't move the version. - Dockerfile.gateway wrote /app/egress_addon.py before /app existed (the mkdir/WORKDIR came later), so the RUN redirect died with exit 2. Move WORKDIR /app above the shim write (WORKDIR creates it) and drop the now redundant later WORKDIR. This changes the gateway Dockerfile, so the infra artifact version moves 3c9e7b23260992db -> 01e6aaa714756fce; the matching artifact has been built and published to the generic package registry. Also add Dockerfile* and pyproject.toml to test.yml's path filters: these inputs determine what the firecracker jobs build/pull, so a change to them must re-run the suite (and lets this push trigger a pull_request run). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9qa3xoavjQScufDfZaXKR
126 lines
6.2 KiB
Docker
126 lines
6.2 KiB
Docker
# Gateway data-plane image (PRD 0024 bundle shape; PRD 0070 gateway).
|
|
#
|
|
# The egress / git-gate / supervise *data plane* — one image, run by
|
|
# the consolidated per-host gateway (PRD 0070). It is NOT the
|
|
# orchestrator control plane: that is the separate, lean
|
|
# `bot-bottle-orchestrator` image (Dockerfile.orchestrator, #384), which
|
|
# ships only python + the stdlib-only `bot_bottle` package and none of
|
|
# this image's mitmproxy / git / gitleaks payload.
|
|
#
|
|
# Collapses the prior per-daemon images (egress, git-gate,
|
|
# supervise) into one. A small stdlib-Python init supervisor at
|
|
# /app/gateway_init.py spawns all daemons, forwards SIGTERM, and
|
|
# propagates per-daemon stdout/stderr to the container log with a
|
|
# `[name]` prefix. See PRD 0024 for the rationale.
|
|
#
|
|
# Layout:
|
|
#
|
|
# /usr/bin/gitleaks gitleaks binary
|
|
# /app/egress_addon.py mitmproxy addon entry point
|
|
# /app/egress-entrypoint.sh mitmdump launcher
|
|
# /usr/local/lib/python*/bot_bottle/ installed package (all daemons + shared modules)
|
|
# /app/egress_addon.py one-line shim: re-exports addons from package
|
|
# (mitmdump -s requires a file path, not a module)
|
|
# /etc/egress/routes.yaml bind-mounted at run time
|
|
# /etc/git-gate/pre-receive docker-cp'd at start time
|
|
# /git-gate-entrypoint.sh docker-cp'd at start time
|
|
# /git-gate/creds/* docker-cp'd at start time
|
|
# /git/* bare repos, populated at runtime
|
|
# /run/supervise/bot-bottle.db bind-mounted at run time
|
|
# /home/mitmproxy/.mitmproxy/ mitmproxy CA dir
|
|
#
|
|
# Exposed ports inside the container:
|
|
# 9099 egress (mitmproxy, agent-facing HTTPS proxy)
|
|
# 9418 git-gate (git-daemon)
|
|
# 9420 git-gate smart HTTP (VM-backend agent-facing transport)
|
|
# 9100 supervise (MCP HTTP)
|
|
|
|
# Based on `python:3.12-slim` (Debian trixie) rather than the
|
|
# `mitmproxy/mitmproxy` image (Debian bookworm) so the whole stack —
|
|
# gateway here, and the firecracker infra image that builds FROM this —
|
|
# lands on trixie, whose buildah (1.39) can build agent Dockerfiles that
|
|
# use heredocs. mitmproxy is pip-installed to the same effect as the
|
|
# upstream image. (bookworm's buildah is 1.28, which can't parse
|
|
# `RUN ... <<EOF`; see the infra image + PR discussion.)
|
|
FROM python:3.12-slim
|
|
|
|
# Runtime system deps:
|
|
# git supplies the `git daemon` subcommand (no separate package)
|
|
# plus the core `git` binary the pre-receive hook invokes.
|
|
# openssh-client supplies the upstream SSH transport the
|
|
# pre-receive hook uses to forward accepted refs.
|
|
# ca-certificates is needed for mitmdump upstream TLS.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
git openssh-client ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# mitmdump (the egress data plane). The upstream mitmproxy image baked
|
|
# this in; on the plain python base we pip-install the same pinned
|
|
# version. Its CA dir is set explicitly via `--set confdir=` in
|
|
# egress-entrypoint.sh, so it doesn't depend on a `mitmproxy` home user.
|
|
RUN pip install --no-cache-dir mitmproxy==11.1.3
|
|
|
|
# gitleaks (the pre-receive hook's secret scanner). Installed from its
|
|
# official release, pinned by version + SHA256 and verified — rather than
|
|
# using a third-party image as a build stage (supply-chain surface, and it
|
|
# would pin us to that image's cadence). python (already present) does the
|
|
# download so we add no curl/wget. trixie apt also ships gitleaks, but an
|
|
# older 8.16; the pinned download keeps the verified 8.30.1.
|
|
#
|
|
# Arch-aware: the asset + SHA are picked from the build's target
|
|
# architecture so an arm64 host (Apple Silicon) gets the arm64 binary
|
|
# rather than an x86_64 one that dies with "Exec format error" the first
|
|
# time the pre-receive hook runs it. TARGETARCH is auto-populated by
|
|
# BuildKit; the dpkg fallback keeps it correct under a legacy builder.
|
|
ARG GITLEAKS_VERSION=8.30.1
|
|
ARG GITLEAKS_SHA256_AMD64=551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
|
|
ARG GITLEAKS_SHA256_ARM64=e4a487ee7ccd7d3a7f7ec08657610aa3606637dab924210b3aee62570fb4b080
|
|
ARG TARGETARCH
|
|
RUN arch="${TARGETARCH:-$(dpkg --print-architecture)}" \
|
|
&& case "$arch" in \
|
|
amd64) asset="linux_x64"; sha="${GITLEAKS_SHA256_AMD64}" ;; \
|
|
arm64) asset="linux_arm64"; sha="${GITLEAKS_SHA256_ARM64}" ;; \
|
|
*) echo "unsupported gitleaks target arch: $arch" >&2; exit 1 ;; \
|
|
esac \
|
|
&& url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_${asset}.tar.gz" \
|
|
&& python3 -c "import sys,urllib.request; urllib.request.urlretrieve(sys.argv[1], '/tmp/gitleaks.tar.gz')" "$url" \
|
|
&& echo "${sha} /tmp/gitleaks.tar.gz" | sha256sum -c - \
|
|
&& tar -xzf /tmp/gitleaks.tar.gz -C /usr/bin gitleaks \
|
|
&& rm /tmp/gitleaks.tar.gz
|
|
|
|
# Install bot_bottle as a proper package so entry-point scripts can use
|
|
# `from bot_bottle.X import Y` absolute imports. A rename or a missing
|
|
# module is caught at pip-install time — not at container runtime.
|
|
COPY pyproject.toml /src/
|
|
COPY bot_bottle/ /src/bot_bottle/
|
|
RUN pip install --no-cache-dir /src/
|
|
|
|
# mitmdump -s requires a file path, not a module. Write a one-line shim that
|
|
# re-exports `addons` from the installed package; mitmdump finds it there.
|
|
# WORKDIR here also creates /app so the shim + COPYs below can write into it
|
|
# (nothing created /app before this point).
|
|
WORKDIR /app
|
|
RUN printf 'from bot_bottle.egress_addon import addons\n' > /app/egress_addon.py
|
|
COPY bot_bottle/egress_entrypoint.sh /app/egress-entrypoint.sh
|
|
RUN chmod +x /app/egress-entrypoint.sh
|
|
|
|
# Pre-create runtime directories the compose renderer + start
|
|
# step expect to exist. `docker cp` does not create intermediate
|
|
# dirs, and bind mounts won't either if the parent is missing.
|
|
RUN mkdir -p \
|
|
/etc/egress \
|
|
/etc/git-gate \
|
|
/git-gate/creds \
|
|
/git \
|
|
/run/supervise \
|
|
/home/mitmproxy/.mitmproxy
|
|
|
|
# Documentation only — the compose renderer publishes whichever
|
|
# subset the bottle uses.
|
|
EXPOSE 8888 9099 9418 9420 9100
|
|
|
|
# PID 1 is the supervisor. It owns signal handling and exit-code
|
|
# propagation; no `exec` chain in the entrypoint itself.
|
|
ENTRYPOINT ["python3", "-m", "bot_bottle.gateway_init"]
|