Inspiration
Writing code is no longer the slow part of shipping. Everything after it is: tests, lint, type checks, container builds, secret detection, SAST triage, release notes. On a small team, each issue turns into an afternoon of watching pipelines. I wanted that whole post-code stretch to start from one label, while a person still decides what reaches main.
What it does
GitDone turns a GitLab issue into a released change. Add the ship label and the GitDone issue-to-production flow on GitLab Duo Agent Platform (AI Catalog item 1016378) picks it up within seconds. It then runs these stages:
- Plan. Reads the issue and posts a plan as an issue note.
- Create. Writes the code and tests, pushes a branch and opens a merge request.
- Verify. Waits for the MR pipeline (unit tests, lint, typecheck, e2e) and acts on the real result, not on a guess.
- Package. Builds a container image tagged to the exact commit and pushes it to the GitLab registry.
- Secure. Runs secret detection and Semgrep SAST, then triages the findings. False positives are explained on the issue instead of being ignored.
- Ready to merge. The agent stops here. GitLab blocks AI workflows from merging (the
/mergequick action returns 403), and GitDone treats that as a feature: the one human step is the Merge click. - Release. After the merge,
release:notesandrelease:publishpublish a versioned release with notes from the MR. - Govern.
journey:recordlogs the whole trip: stages covered, human interventions and lead time.
The live web app lets anyone Sign in with GitLab, Connect your project and follow every journey on the Mission dashboard.
These numbers come from real runs: seven journeys shipped (issues #1–#7), releases up to v0.1.44 and 82 tests passing. Examples:
- #4 added rate limiting to sign-in.
- #5: the agent fixed a bug in its own dashboard (merged journeys were shown as "in flight").
- #7 fixed the lead-time figure on the Mission page.
Each journey needed exactly one human action: Merge.
How we built it
- Agent: a custom flow defined in
.gitlab/duo/flows/issue-to-production.yml, published to the AI Catalog and run on GitLab Duo Agent Platform. A trigger onship-labelled work items starts it. - Pipeline: GitLab CI with lint, unit, e2e (Playwright), typecheck, package (registry image tagged by SHA), secret_detection, semgrep-sast, release:notes, release:publish and journey:record. Releases are published with the CI job token, because release creation is outside the flow token's scope.
- App: Next.js and TypeScript, Postgres, GitLab OAuth with PKCE, hosted on Render.
- License: MIT. All config, the flow YAML and the pipeline history are public in the repo.
Configure: After every merge, GitDone points the GitLab production environment at the live app, waits until production serves the exact merged commit, and checks that every runtime setting production needs is present (database, session secret, token key, OAuth, public URL, GitLab token), reporting only yes/no flags, never secret values. The result is written into the issue's journey. If anything is missing it opens a self-explaining incident issue that closes itself with evidence once the check passes again. It did exactly this for real: a failed Render build was caught, the root cause fixed, and the incident closed itself.
Monitor: GitDone then checks five live endpoints (/, /api/health, /api/version, /mission, /feed.xml) over three rounds, records status and latency to a monitor-report.json artifact, and writes the Monitor stage onto the Mission page. Any failure opens an incident. A pipeline schedule runs the same monitor every 6 hours between releases.
Challenges we ran into
- Merging is blocked for AI workflows. The flow token cannot merge, and the
/mergequick action returns403 Forbidden. Instead of working around GitLab's guard with a stored human token or direct commits to main, I built the design around it: the flow stops at Ready to merge and a person approves the outcome. That is also the Supervised level. - Release permissions. The flow token can't create releases, so publishing moved into the pipeline and uses the CI job token.
- Duplicate pipelines. The flow's first push starts a branch pipeline before the MR exists. The security templates run on the branch pipeline, so the flow reads both.
- Flaky external fetch. One main-branch e2e run failed because a Google Fonts download timed out during the build. It passed on retry. I left it visible in the history rather than hiding it.
- Honest metrics. The first dashboard figures for lead time and timeline were wrong. Fixing them became journeys #5 and #7, done by the agent itself.
Accomplishments that we're proud of
- Seven real issue-to-release journeys, each with one human click, all visible in public pipelines and releases.
- The agent fixed its own dashboard bug (journey #5) and the lead-time metric (journey #7).
- One flow covers Plan, Create, Verify, Package, Secure, Release and Govern.
- Security findings are triaged with written reasons, not just reported.
- The supervised boundary follows GitLab's own policy instead of fighting it.
What we learned
- A clear stopping point makes an agent easier to trust. "Ready to merge" plus a written journey record is a review that takes minutes.
- Agents should read real pipeline results. Waiting for green and reading job output avoided false "done" claims.
- Platform limits are design input. GitLab's merge block pushed GitDone toward the Supervised model, which suits real teams better.
- Real numbers convince more than seeded demo data, so every figure on the Mission page comes from actual journeys.
What's next for GitDone
- Deploy stages: staging deploy, smoke test and rollback guard (already sketched in
ci/gcp-deploy.gitlab-ci.yml, off by default). - Automatic fix-ups when Verify or Secure fails, before handing the MR back.
- Per-project policies: which labels, paths and risk levels may go through the flow.
- Team views on the Mission dashboard: lead time trends and stage coverage across projects.
Built With
- docker
- gitlab
- gitlab-ci
- gitlab-container-registry
- gitlab-duo-agent-platform
- next.js
- oauth-pkce
- playwright
- postgresql
- react
- render
- secret-detection
- semgrep
- typescript
Log in or sign up for Devpost to join the conversation.