Inspiration

I build and ship apps alone. Every release of ReleaseKeeper ??a release-readiness tool I wrote for solo developers ??was still a checklist on my laptop: run the tests, guess the version, check the store copy, write the notes, deploy by hand. The tool that checks other people's releases had no release process of its own. Path B was the honest test: move it to GitLab and let it release itself.

What it does

A work item labelled release is the only thing a person has to write. From there:

  • Plan + create ??the release-planner flow (GitLab Duo Agent Platform, custom flow) runs ReleaseKeeper's own notes command, so the scope and the next version come from the commits, not from the model (two new features ??0.2.0 becomes 0.3.0). It posts the plan and a checklist on the issue and opens the version-bump merge request.
  • Verify + secure ??the MR pipeline runs tests on Python 3.12 and the 3.10 floor, SAST, secret detection and container scanning. The release-readiness flow reads the pipeline, failed-job logs and security findings, runs ReleaseKeeper's copy check on the store listing, and posts one note: READY or NOT READY, with the evidence.
  • Package + deploy ??every main commit builds an amd64 image into the project registry and deploys it to Cloud Run staging, keyless (GitLab OIDC ??Google Workload Identity Federation), then smoke-tests the live service with the same copy check.
  • Release + govern ??production is a manual job. When a person starts it, the pipeline deploys, smoke-tests, and publishes a GitLab Release whose body is ReleaseKeeper's notes plus a deployment record: who approved, when, which revision, which checks passed.
  • Monitor ??an uptime schedule runs every 6 hours. A failure starts the incident-triage flow, which opens one evidence-backed incident issue (proved with a deliberate drill: issue #2).

The agents do the multi-step work; the person approves outcomes ??the release candidate (merge) and production. No flow can merge, deploy, roll back or change settings. Each flow has its own service account and a fixed tool list.

One real release, v0.3.0 (2026-10-11 UTC): 00:33:51 issue #3 created ??00:35:31 plan + MR !13 by the planner ??00:47:03 READY ??00:47:21 merged ??staging deploy + smoke green ??01:05:08 production started by a person ??01:06:41 Release v0.3.0 published. All of it is public in the project: issues, MRs, pipelines, environments, releases.

All nine stages are touched, each with a run you can open (table in the README): plan 쨌 create 쨌 verify 쨌 package 쨌 secure 쨌 release 쨌 configure 쨌 monitor 쨌 govern.

How we built it

  • Imported the original MIT repo with its 21 commits and author dates (1296104), then built everything after it in MRs !1??15 from 2026-10-10.
  • .gitlab-ci.yml: test / secure / package / deploy / release stages, GitLab's SAST, Secret-Detection and Container-Scanning templates, workflow:rules so scheduled runs only do the uptime check.
  • Three custom flows in .gitlab/duo/flows/, published in the AI Catalog and kept in sync with scripts/duo_flow_sync.py (GraphQL: read the live definition, bump the version, --check for drift). Triggers: work item created (planner, label-gated), MR pipeline finished (readiness), scheduled pipeline failed (incident triage).
  • .gitlab/duo/agent-config.yml installs ReleaseKeeper before each agent sandbox starts ??the sandbox can reach only gitlab.com, so the agents call the real CLI instead of re-implementing it in a prompt.
  • Cloud Run: two services (staging auto, production manual), a deployer service account with the minimum roles, Workload Identity Federation bound to the protected main branch of this project.
  • scripts/release.py publishes the Release with the CI job token only.
  • The demo video is reproducible from demo/gitlab/ (narration ??text-to-speech ??Playwright recorder of the logged-out public pages).

Challenges we ran into

  • The agent sandbox has no package index. The first readiness run honestly reported NOT READY because pip install returned 403. Moving the install into agent-config.yml (runs before the sandbox) fixed it.
  • Triggering on the right event. The readiness flow first fired on mentions only, so it judged pipelines that were still running. It now triggers on the MR pipeline's final status, with a trigger filter on object_attributes.status and source.
  • Agents can't approve themselves ??by design, and that has a cost. Commits by a flow's service account don't start other flows, so the planner's MR doesn't get a readiness verdict on its own: a person asks for it with one click (assign the flow as reviewer). We kept that rather than giving an agent merge rights.
  • A release MR has one commit. The readiness flow first said "empty notes" for MR !13, because it looked at the MR's own range. Release MRs are now checked against the previous release, and the branch version must equal the computed next version.
  • Cloud Run deploy permission. Keyless auth worked first time, but the deploy failed until the deployer could read the image repository.

Accomplishments that we're proud of

  • Two real releases (v0.2.0, v0.3.0) through the full lane, each with the approver on record.
  • A deliberate failure drill that the incident-triage flow caught and filed correctly, calling it a drill and advising no rollback.
  • The numbers in every agent note come from ReleaseKeeper's deterministic CLI, not from the model.
  • Dogfooding found a real product bug: the copy check flagged "do not guarantee" as an overstated claim (negation) ??now on the roadmap.

What we learned

  • Agent flows are most useful as readers and writers of evidence around deterministic tools, not as the source of the numbers.
  • Trigger design (which event, which filter) decides whether an agent is helpful or noisy.
  • Least privilege is easy to keep when each flow has its own service account and an explicit tool list.

What's next

  • Remove the first human click: start the readiness verdict on the planner's MR automatically once service-account pipelines can trigger flows (or via a pipeline-event hook).
  • Fix the negation false positive in the copy check, shipped as v0.3.1 through this same lane.
  • Offer the flows from the AI Catalog to other solo developers' projects.

Built With

  • docker
  • fastapi
  • gitlab-ci
  • gitlab-duo-agent-platform
  • gitlab-releases
  • google-cloud-run
  • python
  • semgrep
  • strands-agents
  • workload-identity-federation
Share this project:

Updates

Submission history