Skip to content
GantryCD

Developer overview

This section is for people working on GantryCD. It’s a map and a set of principles, not a line-by-line reference — for that, each page links into the Reference section, which tracks the implementation in detail.

Tip — start with CLAUDE.md. The repository’s CLAUDE.md is the canonical entry point for contributors working in the code. This page is the gentler narrative version.

The four surfaces

GantryCD is one repository producing a few binaries plus a web app:

        Web (React SPA)
            │  /api/v1/...

   ┌──────────────────┐        PostgreSQL (source of truth)
   │     Backend      │ ─────▶ S3 (state/logs/artifacts), Redis, AWS STS, GitHub
   │  API + jobs      │
   └──────────────────┘

            │  poll / accept / done
   ┌──────────────────┐
   │   Runner group   │  long-lived; launches…
   │  + ephemeral     │  …ephemeral runners (one per run)
   │     runners      │
   └──────────────────┘
  • Backend (cmd/backend) — the HTTP API, orchestration, and background jobs.
  • Runner group (cmd/runner/group/*) — a long-lived coordinator with four launcher variants (local, docker, kubernetes, github).
  • Ephemeral runner (cmd/runner/ephemeral) — the real per-run worker.
  • Web (web/) — a React SPA, embedded into the backend binary at build time.
  • Plus the CLI (cmd/cli, gantrycli) — mostly an HTTP client like Web, plus a small direct-DB operator/ break-glass subtree.

Communication boundaries (non-negotiable)

These are architectural constraints, enforced and assumed everywhere:

  • Web → Backend only.
  • CLI resource commands (deployments, stacks, orgs, …) → Backend only, via pkg/sdk — same boundary as Web.
  • CLI operator/ subtree → PostgreSQL directly (documented break-glass exception; bypasses HTTP authz, only safe with database credentials).
  • Runner group / ephemeral runner → Backend only.
  • Backend → PostgreSQL, Redis, S3, AWS STS, GitHub.

Runners never talk to the web app, to each other, or directly to the database. If you find yourself wanting a new edge in that graph, you’re solving the problem in the wrong place.

Package layout

PathWhat lives there
cmd/Entry points and wiring (backend, runner group launchers, ephemeral runner, CLI).
internal/backend/The backend’s guts: handlers, services, repositories, db, middleware, scm, sso, jobs.
internal/authz/Hot-path authorization — three SQL queries, no service layer.
internal/runner/Shared runner-group and ephemeral-runner logic.
internal/clients/Outbound client wrappers (aws, gcp, github).
pkg/domain/Entities, validation, typed errors — the vocabulary.
pkg/contracts/Backend↔runner wire types, notably RunContext.
pkg/extensions/The pluggable extension points (e.g. runner-group types).
pkg/sdk/The Go API client, shared by the CLI and the Terraform provider.
schema/Declarative database schema (Atlas).
migrations/Data-only migrations (seeds, backfills) — never schema DDL.

How to navigate by question

You’re asking…Read
How is a request handled?Backend internals
How does a deployment progress / a run get executed?Execution model
How do I add an SCM / cloud / runner / SSO integration?Extending GantryCD
How do I build, test, and change the schema?Contributing

For depth on any topic, the Reference section has the detailed implementation doc.