Inspiration
What it does
How we built it
Challenges we ran into
Accomplishments that we're proud of
What we learned
What's next for SunGate
Inspiration
Writing code is now fast. Everything after the code (review, security, failing pipelines, releases, incidents) still eats the day. CI also burns electricity at any hour, even when the grid is dirty. I wanted a path to production where agents do the work after the code, and the pipeline cares about carbon.
What it does
SunGate is a small app for solar owners: a clear-sky solar output forecast for any location, and the next low-carbon window on the electricity grid (live GB grid data).
Around it, four GitLab Duo Agent Platform flows run the lifecycle:
- Issue to MR (plan + create): a planner agent posts a plan, acceptance criteria and risk on the issue; a builder agent writes code and tests, runs lint, tests and governance, and opens the MR.
- MR Guardian (review + secure + govern): reads the diff and GitLab security findings (SAST, Secret Detection, Dependency and Container Scanning), fixes critical/high findings on the MR branch, posts a verdict. It never merges and never dismisses a vulnerability.
- Pipeline Doctor (verify + monitor): on a failed pipeline it classifies the failure. Code/CI problem → fix MR. Flaky runner → retry advice. Scheduled production check failed → incident issue with a rollback plan.
- Release Captain (release + govern): on a passed main pipeline it posts a release-readiness report: tests, findings, staging smoke, SCI grams, actions by AI service accounts from the audit log, and the link to the one manual production job.
The pipeline starts with a carbon gate that uses the same carbon.js the app ships. It reads the
24-hour grid forecast. Developer pipelines are never slowed (advice only). Scheduled pipelines move the
heavy work (Docker build, container scan, ephemeral staging) into a cleaner window with a GitLab
delayed job, when that window is at least 30 % cleaner and within 6 hours. Each pipeline publishes its
Software Carbon Intensity (SCI) from measured duration and live grid intensity.
A human does one thing: press play on the production job.
How we built it
.gitlab-ci.ymlwith 8 stages; heavy work in a dynamic child pipeline generated by the carbon gate.- Ephemeral staging: the image built in this pipeline runs as a CI service and gets a smoke test.
- Production: GitLab Pages behind a manual job; a pipeline schedule probes production every 30 minutes.
- Four custom flows (flow registry v1 YAML) with two-agent designs,
AGENTS.mdand project skills. - Guardrails as code:
scripts/governance.js(34 rules) fails the pipeline if, for example, a flow gets a destructive tool, production stops being manual, or CODEOWNERS stops covering automation. - Node.js 24 LTS, zero npm dependencies, 40 offline tests using a real grid-forecast fixture.
Lifecycle stages covered (9/9)
Plan, Create, Verify, Package, Secure, Release, Configure, Monitor, Govern. The table with the exact job or flow for each stage is in the README.
Sustainability (Most Environmentally Impactful)
- Method: GSF SCI (ISO/IEC 21031:2024), SCI = (E × I + M) per pipeline run. E = measured pipeline minutes × runner power (30 W, a stated assumption), I = live GB grid intensity, M excluded.
- Real data from Oct 23, 2026 08:15 UTC: grid at 98 gCO₂e/kWh, cleanest slot that day 43 gCO₂e/kWh, so moving heavy work cuts its carbon by 56 %. A 10-minute pipeline: 0.49 g now vs 0.215 g.
- Measured on GitLab: main pipeline #2980331251 (Oct 23, 2026, 09:10 UTC) ran 2.14 min and emitted 0.0954 g CO₂e (E = 0.001071 kWh at 89 gCO₂e/kWh). The cleanest 30-minute slot that day (22:30 UTC, 42 gCO₂e/kWh) would have cut it to 0.045 g (−52.8 %).
- Static production site (no always-on server), small Alpine image, zero dependencies.
- Limits: GB data is a public proxy, GitLab SaaS runners do not publish location or power.
Challenges
- Pipelines and flows must never loop: GitLab only starts triggers for human actions, and Pipeline Doctor is instructed to stop after 2 fix attempts on the same branch and hand over to a human.
- Shifting work without wasting a runner: a delayed job holds no runner while it waits.
- Being honest about carbon numbers: every assumption is printed in the report.
Accomplishments
- The app's own carbon code decides when its pipeline runs heavy work (dogfooding).
- One human click to production, everything else prepared and checked by agents and CI.
- Issue #4 (add a
tiltparameter) → MR !1 opened by the Issue to MR flow 2 min 12 s after assignment (plan on the issue, code, 7 new tests). MR Guardian posted its verdict 71 s after being assigned as reviewer. A human merged; Release Captain posted the readiness report on issue #2. - A deliberately broken push (branch
feat/hours-zero, failedtestjob) → Pipeline Doctor diagnosed it and opened fix MR !2 about 4 minutes after the pipeline failed. - A real production bug became a better monitor. The live page loads
solar.jsandcarbon.jsas browser scripts, and both declared a top-levelconst api, so the green-window card failed in browsers while every Node test passed. MR !3 fixed it. It adds a test that runs both files in one shared scope, and the scheduled production probe now executes the deployed scripts, so a page that returns 200 but cannot run fails the monitor. MR Guardian reviewed !3 (verdict: approve); it was then merged and the manualpagesjob was played.
What we learned
Agents are most useful when the rules are written down: AGENTS.md, skills and guardrails in CI
made the flows predictable.
What's next
More grid regions (Electricity Maps), carbon budgets per project, and runners that report real power.
Log in or sign up for Devpost to join the conversation.