Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
Only minor nit-level comment and changelog-link cleanups remain; no blocking issues were identified.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Hardens production Docker images with digest-pinned distroless bases and replaces shell-based verifier pausing with ccv quiesce.
Changes:
- Migrates six images to nonroot distroless runtime stages.
- Adds tested process discovery and SIGSTOP/SIGCONT quiescing.
- Updates E2E tooling, runbooks, changelog, Docker contexts, and Dependabot configuration.
| File | Summary |
|---|---|
verifier/Dockerfile |
Distroless verifier image with static tini. |
pricer/Dockerfile |
Distroless nonroot pricer image. |
indexer/Dockerfile |
Distroless nonroot indexer image. |
executor/Dockerfile |
Distroless nonroot executor image. |
docs/migration/staging-migration-plan.md |
Updates probes and quiesce instructions. |
cmd/verifier/run_ccv_cli.go |
Registers quiesce commands. |
cli/quiesce/quiesce.go |
Implements process discovery and signaling. |
cli/quiesce/quiesce_test.go |
Tests quiesce behavior and PID selection. |
changelog/2026-09-25_distroless_images_and_quiesce.md |
Documents migration and compatibility changes. |
build/devenv/tests/e2e/verifiercli/committee.go |
Updates resume helper documentation. |
build/devenv/tests/e2e/verifiercli/client.go |
Uses quiesce instead of pkill. |
build/devenv/fakes/Dockerfile |
Adds a distroless fakes image. |
aggregator/Dockerfile |
Adds a distroless image and staged migration symlink. |
.github/dependabot.yml |
Configures grouped weekly Docker digest updates. |
.dockerignore |
Excludes unnecessary and sensitive build-context files. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| @@ -1,5 +1,5 @@ | |||
| # syntax=docker/dockerfile:1.7 | |||
| FROM golang:1.26.6-alpine AS builder | |||
| FROM golang:1.26.6-alpine@sha256:3889b425f035be855a72fb4755265311293b6d414521f0a519d819df32222d83 AS builder | |||
There was a problem hiding this comment.
can you drop a comment why this hash?
| // A best-effort helper for cleanup paths is ResumeBestEffort. | ||
| func (c *Client) Resume(ctx context.Context) error { | ||
| _, err := c.Exec(ctx, "pkill", "-CONT", "-f", c.processMatch) | ||
| _, err := c.CLI(ctx, []string{"ccv", "quiesce"}, "resume") |
There was a problem hiding this comment.
if there is no shell, how this works?
There was a problem hiding this comment.
docker exec runs the static verifier binary directly (/bin/verifier ccv quiesce pause). The binary scans /proc itself from Go (os.ReadDir/os.ReadFile in cli/quiesce/quiesce.go), finds the service PID by comm, and sends SIGSTOP with syscall.Kill. pkill/sh were only ever a workaround for not having a signaling path in the binary.
|
Code coverage report:
Files added (in
|
| @@ -0,0 +1,19 @@ | |||
| version: 2 | |||
There was a problem hiding this comment.
Does this hav to use the GATI github token, o/w it won't trigger CI? Or is dependabot a special thing that doesn't need it?
There was a problem hiding this comment.
I think it's provided by GH itself so shouldn't need GATI because there are no cross-repo calls. We'll find out 🙂

Description
Hardens all production images: digest-pinned bases and distroless final stages
Images
gcr.io/distroless/static-debian12:nonrootas the distroless nonroot user (65532:65532): no shell, noapk, noapk upgradesecurity-patch surface. The distroless base ships the CA certificates the services need./app/migrationssymlink in the builderccv quiesce pause|resume(cli/quiesce)pkill, which the e2e suite (chain-status, policy-hook, jobqueue, replay, reorg, chaos) and the staging runbook used to freeze the verifier during CLI mutations and curse replay. The new subcommand finds the verifier service by scanning/procfor the lowest non-self PID whosecommmatches the CLI binary's own name, then sends SIGSTOP/SIGCONT.verifiercli.Pause/Resume(plus the best-effort variants) now execccv quiesce ...instead ofpkill -STOP/-CONT -f verifier;WithProcessMatch/DefaultProcessMatchare goneBuild context and updates
.dockerignore: VCS dirs,.build/,docs/,changelog/, local keystores (**/keystore.json), and.env*files never enter a build context;build/devenv/*is excluded except the fakes module, which the fakes image builds..github/dependabot.yml: weekly digest bumps for the pinned bases across all six Dockerfiles, grouped into a single PR.Runbook (
docs/migration/staging-migration-plan.md): in-containerwgetprobes replaced withkubectl port-forward+curl, andpkill -STOP -f verifierreplaced withccv quiesce pause.Breaking for anything that exec-ed a shell in these images, referenced the per-service users, or probed them with
wgetfrom inside the container. See the changelog entry for the migration steps.Testing
verifiercli.Pause/Resumethroughccv quiesceagainst the distroless verifier image: chain-status, policy-hook, jobqueue, replay, reorg, and chaos suitescli/quiesceunit tests: lowest-PID selection, self-exclusion, no-match error, and a kill seam asserting the target PID and signal (tests never signal their own process)..dockerignorenegation keeps the fakes module files in the context, the pinned digests resolve to the right images, and the distroless final stage runs.Checklist
changelogdirectory)changelog/2026-09-25_distroless_images_and_quiesce.md