Inspiration

Release approvals are often built on evidence that no longer describes the thing being released. Yesterday's green test run, a scan of a different tag, or an image rebuilt after review all look fine on a dashboard. We wanted a release step that cannot be satisfied by stale or mismatched evidence, and an agent that helps fix a blocked release without quietly widening its own permissions.

What it does

  • Deterministic gate. evidence_validation collects the test, package, and scan results for one pipeline and checks that they all refer to the same commit SHA and the same container image digest. It blocks on any HIGH, CRITICAL, or UNKNOWN finding. Its decision (passed / blocked with a reason) and a human-readable report are stored as job artifacts.
  • Release engineer agent (GitLab Duo flow). Mentioned on a release issue, it reads the real failing jobs, logs, and scan artifacts. If the cause is application code, it may propose a minimal repair MR on a pinned branch. If the cause lies outside that scope (base image, dependency pins, CI or gate policy), it does not patch: it posts an escalation with the evidence and an exact fix.
  • Owner stays in charge. The agent cannot merge, approve, or promote. Its write tools are pinned in the flow definition to one repair branch. The test suite fails if anyone adds a shell or unpinned write tool. The owner reviews, merges, and makes the final production decision.

What actually happened (all records are public in the project)

  1. The first real release, v0.1.0 (issue #2), was blocked by our own gate. Pipeline 2960395835 found 109 blocking findings in the image.
  2. The Duo agent (session 9652104) read the job records, traced 106 findings to the Debian base image and 3 to a starlette pin, and escalated instead of patching because both causes were outside its scope—elapsed time: 1 min 45 s.
  3. The owner applied the recommended fix in MR !1: a Chainguard Python runtime pinned by digest, plus a starlette/fastapi bump. Same gate, same policy: zero findings, decision passed for that exact SHA and digest (pipeline 2960440396).
  4. While reviewing, we noticed the agent's service account could push to main. MR !3 removed the shell and pinned every write tool to duo/release-repair, enforced by a test. The owner merged !1, !3, and !2; main pipeline 2960878115 passes.
  5. Eight days later (Oct 25), the same gate blocked a docs-only MR (!4): Trivy found 4 new HIGH CVEs, published after Oct 18, in the Chainguard base image (ca-certificates-bundle, brotli). There was no exception and no policy change. MR !5 re-pinned the images to their patched digests, and the gate passed again (pipeline 2987286328). The gate keeps checking the release, not just the changed code.

How we built it

Python / FastAPI service (Chainguard Python runtime); a standard-library gate and report generator; GitLab CI with test → package (Docker-in-Docker, digest captured) → scan (Trivy 0.66) → evidence_validation, plus staging, smoke, and manual promotion jobs that activate only when cloud variables are configured. Every image and dependency is pinned by digest or hash. The Duo flow is defined in flows/release-evidence.yaml and published through the AI Catalog with a mention trigger. 105 tests cover the gate, the report, the CI structure, and the flow's tool pinning.

Lifecycle stages covered

Plan (release issue with acceptance criteria) · Create (merge requests !1, !3 and !5; agent repairs restricted to one pinned branch) · Verify (tests, junit report) · Package (image built once, pinned by digest) · Secure (Trivy scan with a blocking policy) · Release (evidence-bound gate decision and report) · Govern (pinned agent tools, owner-only merge and promotion, test-enforced policy). The pipeline includes deploy/monitor stages but doesn't demonstrate them without cloud credentials; we don't claim them.

Challenges

Custom catalog flows rejected per-tool approval settings, so supervision had to come from pinned tool parameters plus owner merges. The agent's read tools couldn't download artifacts through the proxy, and it reported that instead of guessing. Getting a base image with zero HIGH findings took several candidates: only the Chainguard runtime passed.

What we learned

An agent that escalates with evidence is as valuable as one that patches. On day one, it did the most useful thing: it refused to touch files it wasn't allowed to touch and explained exactly what the owner should change.

What's next

Cloud Run deployment with keyless workload identity (code already in the repo), digest-verified staging smoke tests, and promotion records added to the evidence chain.

AI use

Development used an AI strategist (Claude) for concept, rule analysis, and review, and an AI coding agent (Codex) for implementation, tests, and documentation. GitLab Duo Agent Platform powers the runtime agent. The entrant chose the project and its name, merged every change, and made the release decisions. Details: AI-USE.md. The demo video was made locally with Remotion using real screenshots from this project; the narration is a synthetic voice (Kokoro-82M, Apache-2.0), and the video states this.

Built With

  • chainguard
  • claude
  • docker
  • fastapi
  • gitlab
  • gitlab-ci
  • gitlab-duo
  • json-schema
  • pytest
  • python
  • trivy
  • uv
Share this project:

Updates

Submission history