Inspiration

Pipelines run thousands of times a day. Most teams re-run every test on every change and build container images they never ship. Nobody sees what that costs the planet, because carbon is invisible at the one moment it could be reduced: inside the merge request.

I hold a certificate in sustainable finance. In finance, what gets measured and disclosed gets managed, and emissions reporting changed how companies invest. I wanted the same thing for software delivery: a receipt on every merge request, in a recognised standard, sitting next to the security results, at the moment a human decides to ship.

At the same time, tests and scanners pass while real bugs still slip through, and reviewers rarely have time to read every diff. So EcoGate puts both questions in one place: is this change safe to ship, and what did it cost to check?

What it does

Every merge request passes through EcoGate before it ships.

  1. Carbon-aware pipeline. EcoGate reads the diff and runs only the tests that change can affect (on our demo MR, 1 of 5 test files). Config or dependency changes still run the full suite. SAST and secret detection always run. The container image is built only on main, never on merge requests.
  2. Carbon Receipt. A comment on the MR with the energy, grid intensity, embodied emissions and the SCI per pipeline (Green Software Foundation, ISO/IEC 21031:2024), compared with the last main pipeline. It also shows what the same work would emit in the greenest Google Cloud region. The receipt updates in place on every push.
  3. Release Guardian (a custom GitLab Duo Agent Platform flow). A human assigns it as reviewer or mentions it. It reads the MR, the diffs, the Carbon Receipt and the security findings, posts inline comments with one-click suggested fixes, and gives a verdict: ✅ READY TO SHIP, ⚠️ NEEDS CHANGES or ⛔ BLOCKED, with a checklist of what is left for the human. It never merges, approves or deploys.
  4. After merge: the deploy region is picked from Google Cloud's carbon data, the Cloud Run deploy is manual (human approval), and a health check opens an incident issue if the service fails.

What happened in the demo (MR !4, unedited run)

  • A new /api/compare endpoint was pushed. Lint, tests and both security scanners passed.
  • The pipeline ran 1 of 5 test files: 0.16 g CO₂e, 41% less than the last main pipeline.
  • Release Guardian found two bugs the tests missed: an unknown region raised a KeyError (HTTP 500), and a region with zero grid intensity would raise a ZeroDivisionError. It posted a one-click fix that returns HTTP 400 for both, and said NEEDS CHANGES.
  • I applied the fix with one click. The pipeline re-ran and the receipt updated.
  • I mentioned the agent again. It checked the fix commit, said READY TO SHIP, and suggested a unit test for the 400 path as an optional follow-up.
  • I merged.

The agent only called the tools it needed. It skipped the pipeline-error and finding-detail tools because the pipeline passed and there were no findings.

How I built it

  • Release Guardian is a custom flow (YAML v1, ambient environment) with one AgentComponent. It uses the GitLab tools get_merge_request, list_merge_request_diffs, list_all_merge_request_notes, list_security_findings, get_security_finding_details, get_pipeline_errors, get_repository_file, create_merge_request_diff_note and create_merge_request_note. It is triggered by Assign reviewer and Mention. The prompt limits it to at most three inline suggestions and one structured report, and forbids merging, approving or deploying.
  • The carbon engine (carbon_ci/, Python) gets job durations from the GitLab API and calculates energy with the Cloud Carbon Footprint method. It takes grid intensity from Google Cloud's published per-region data and adds embodied emissions, then writes the SCI.
  • Test selection maps changed files to the test files they can affect, with a safe fallback to the full suite for anything global (CI config, dependencies, conftest.py, data files).
  • The pipeline covers verify, secure, package, configure, deploy, monitor and report stages, with GitLab SAST and Secret Detection enabled on MR pipelines (AST_ENABLE_MR_PIPELINES).
  • A Flask dashboard shows recent pipeline receipts, a what-if estimator and Google Cloud regions ranked by grid intensity. It is containerised for Cloud Run.
  • 39 pytest tests. MIT licensed.

DevSecOps lifecycle coverage

Stage How EcoGate touches it
Create Release Guardian reviews the diff and posts one-click code suggestions
Verify Carbon-aware test selection; JUnit report on every MR
Secure GitLab SAST + secret detection on MR pipelines; the agent explains findings
Package Container image built only on main and tags
Configure Deploy region chosen from Google Cloud's carbon data
Release Ship verdict from the agent; manual, human-approved Cloud Run deploy
Monitor Post-deploy health check; opens an incident issue on failure
Govern Carbon Receipt + agent report kept on every MR as an audit trail

Challenges I ran into

  • Security scanners skipped MR pipelines by default. My first receipts looked much better than reality because SAST and secret detection weren't running on merge requests. I enabled them on MR pipelines and re-measured. Honest numbers mattered more than big ones.
  • Test selection had an accumulation bug: one changed file could pull in tests that belonged to another. I fixed it and added tests for it.
  • Keeping the agent in its lane. It took several prompt iterations to get one structured report, at most three suggestions, and a clear rule that it never takes a shipping action itself.

Accomplishments I'm proud of

  • The agent caught a real second bug (division by zero) that I had not planted.
  • Every number on the receipt can be traced to a published method and dataset, and every coefficient can be overridden with a CI variable.
  • The whole loop (pipeline → receipt → agent review → one-click fix → re-review → merge) runs inside GitLab, with a human approving every step.

What I learned

  • An agent is most useful when it explains and proposes, and a person decides.
  • Carbon data is only actionable if it appears where the decision is made, not in a quarterly report.
  • Building with the Duo Agent Platform: flows, triggers, tools and service accounts.

What's next

  • Use real runner telemetry (Eco CI energy measurements) instead of estimated power.
  • Time-shifting: defer non-urgent pipelines to hours with cleaner grid power.
  • A carbon budget per project, with the agent flagging MRs that exceed it.
  • Learn the test map from coverage data instead of file naming rules.

Built With

Share this project:

Updates

Submission history