Inspiration

Food banks run on volunteers, and when a shift signup fails, nobody shows up. The same silent failure happens in company systems: one team renames a field in the API, the service that calls it isn't updated, and requests start failing with a generic error. Retries hide it and nobody connects it to the change.

Count Me In is built around that failure. The volunteer app is deliberately small. The point is the automation around it: what happens after the code is written.

What it does

Volunteers pick a shift on a live page and book a place. Behind it, four services and GitLab Duo Agent Platform automate the rest of the lifecycle at the Supervised level: agents run multi-step workflows on their own, and a person approves the outcome (merging, and the production release).

Seven custom flows and one custom agent

  • Contract Guardian (merge request created or ready): finds the services a change would break, comments, and opens a fix merge request for each.
  • Incident to Release (incident created): names the likely commit, posts a plan, opens a fix, proves it on a staging canary, then waits for a person to approve production.
  • Carbon Optimizer (pipeline passed): estimates the pipeline's energy use and removes avoidable CI work without removing a test.
  • IaC Policy Fixer (merge request created): fixes safely fixable Terraform and Kubernetes violations; intended ones need a recorded exception.
  • Docs Drift Fixer (merge request approved): rewrites documentation lines made stale by a rename.
  • Issue Triage (work item created): proposes labels and a reply, posted only after a person approves.
  • Secret Rotation (mention): moves hard-coded secrets behind vault references; a person runs the rotation and confirms revocation.
  • Release Notes agent (Duo Chat): drafts notes from the merge requests between two versions.

Pipeline automation without AI: contract verification on every pipeline, a carbon-aware release scheduler, a hashed evidence pack for each production release, and a 24-hour post-release watch.

Lifecycle stages touched: plan, create, verify, package, secure, release, configure, monitor, govern.

How a flow stays honest

A deterministic script computes each answer and the flow acts on it, so agents don't guess. Before any flow that changes code opens a merge request, it runs the project's own checks (make check: lint, strict types, tests, contract and policy checks) and fixes what it broke. If a check still fails it opens nothing and reports that the change is not ready. Merge requests list what was run under Validation.

How we built it

  • Services: four small FastAPI services (shift_api, signup_listener, notify, vault_mock), each with its own tests and container. The shift API's contract is generated from its models and checked against what each consumer sends and reads.
  • Automation: Duo custom flows in YAML, with Python tools behind them, all type-checked (mypy --strict) and tested.
  • Deployment: Google Cloud Run through Terraform. A pipeline builds the images and a manual job applies the infrastructure. GitLab signs in with its OIDC token through workload identity federation, so no key is stored. The private services accept only signed calls from each other.
  • Environment: a Software Carbon Intensity estimate per pipeline, and release timing that waits for a low-carbon hour. These are estimates from assumed coefficients, and the page and docs show the method.

Challenges

  • Flow jobs can't read custom CI/CD variables, so the secret-rotation flow never touches the vault. A person-run job does the rotation.
  • Triggers can't filter by path or label, so each flow starts for every matching event and ends in one cheap step when it doesn't apply.
  • A bot can't start a flow, so the post-release watch files incidents with a person's token.
  • GitLab attributes a flow's merge request to the person who triggered it, so the evidence pack recognises agent work by branch name.
  • Cloud Run needed at least 512 MiB for an always-on instance, and a new access rule took about a minute to apply, which failed our first deploy check until we added retries.

What we learned

Agents are most useful when a script decides and the agent acts, and when a flow must pass the same checks a developer would before it can claim a change is ready.

What's next

Hands-off promotion for low-risk fixes, persistent storage instead of in-memory data, and a real forecast source for carbon-aware releases.

Honest limits

Data is held in memory and resets on each deploy. Carbon figures are estimates. [Add: how many flow runs you completed and any flow that did not run end to end.]

Built With

  • artifact-registry
  • css
  • docker
  • fastapi
  • gitlab-ci-cd
  • gitlab-duo-agent-platform
  • gitlab-duo-custom-flows
  • google-cloud-run
  • html
  • httpx
  • javascript
  • kubernetes
  • mypy
  • openapi
  • pydantic
  • pytest
  • python
  • ruff
  • terraform
  • workload-identity-federation
  • yaml
Share this project:

Updates

Submission history