-
-
The idea (illustration): every piece of release evidence must match one commit and one image digest, or the gate blocks.
-
Real record: our first release, v0.1.0, was blocked by our own gate. 109 HIGH, CRITICAL or UNKNOWN findings (job 17265824678).
-
The GitLab Duo agent's escalation issue #2: causes were outside its repair scope, it didn't patch. Explained why, gave the owner exact fix
-
After the owner's fix (MR !1): same gate, same policy, zero findings. Decision "passed" for commit caeadba and its image digest.
-
MR !3: the agent's write tools are pinned to one repair branch, with no shell. A test enforces this on every pipeline.
-
Seven lifecycle stages shown on real records in the project. Configure and monitor aren't claimed.
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_validationcollects 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/blockedwith 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)
- The first real release, v0.1.0 (issue #2), was blocked by our own gate. Pipeline 2960395835 found 109 blocking findings in the image.
- 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.
- 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
passedfor that exact SHA and digest (pipeline 2960440396). - While reviewing, we noticed the agent's service account could push to
main. MR !3 removed the shell and pinned every write tool toduo/release-repair, enforced by a test. The owner merged !1, !3, and !2; main pipeline 2960878115 passes. - 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.
Log in or sign up for Devpost to join the conversation.