ALL ARCHITECTURE

Architecture

PR Quality Gate

Stages fan out in parallel per pull request instead of running serially per repo. Advisory mode reports without blocking until a team opts in.

scroll to render
01

What you're looking at

A push opens a pull request, which fires a webhook at the dispatcher. The dispatcher fans the work out — lint, test, coverage and SAST all start at once rather than queueing. Each reports back independently, and the verdict node aggregates them. The dashed edge from the artifact registry is credential flow, not code: the gate mints a short-lived token so private packages resolve without a long-lived secret sitting in CI.

02

Why parallel matters more than it sounds

Serially, gate time is the sum of every stage. In parallel it is the slowest single stage. On a 200-repo estate that is the difference between a gate people wait for and a gate people route around — and a gate that gets routed around protects nothing.

03

What goes wrong here

Three things, in order of frequency. The registry token expires mid-build on long runs, producing a 401 that looks like a dependency problem. A SAST scan with no per-PR cap runs on every push to a busy branch and the bill arrives at the end of the month. And a gate switched from advisory to blocking before teams have fixed their existing findings blocks every merge on day one, which is how gates get disabled entirely.

Inspect it yourself

  • Is the gate actually parallel?

    # compare wall-clock against the sum of stage durations
    gh run view RUN_ID --json jobs -q '[.jobs[] | {name, started: .startedAt, ended: .completedAt}]'

    If total elapsed ≈ sum of stages, they are running one after another regardless of what the config claims.

  • Find repos not covered by the gate

    gh repo list ORG --limit 500 --json name,defaultBranchRef -q '.[].name' | while read r; do gh api repos/ORG/$r/branches/main/protection >/dev/null 2>&1 || echo "unprotected: $r"; done

    Coverage is the number that matters. A gate on 70 of 200 repos is a gate with a 130-repo hole in it.

Read the source

Components

  • DEVELOPERgit push
  • PULL REQUESTwebhook
  • DISPATCHERfan-out
  • LINT
  • TEST
  • COVERAGE
  • SASTper-PR cap
  • VERDICTadvisory / blocking
  • ARTIFACT REGISTRYshort-lived token

Flows

  • devprpush
  • prdispwebhook
  • displint
  • disptest
  • dispcov
  • dispsast
  • registrydispauth
  • lintverdict
  • testverdict
  • covverdict
  • sastverdict