Skip to content

Git Host Webhooks

The endpoints in gradient-web/src/endpoints/git_host_hooks/ receive Git host events. The routes carry no session. Every delivery must prove its origin with the Git host's signature. A push will end as a Queued evaluation.

sequenceDiagram
    participant F as Git host
    participant H as git_host_hooks
    participant C as gradient_ci
    participant S as eval-dispatch
    F->>H: POST push (signed)
    H->>H: verify signature, match repository
    H->>C: fan_out_triggers -> apply_trigger
    C->>C: dedup, concurrency
    C->>C: trigger_evaluation: Commit + Queued evaluation
    S->>S: woken by the new evaluation, handing the evaluation to a worker

Routes

Route Verification
POST /api/v1/hooks/github X-Hub-Signature-256 against GRADIENT_GITHUB_APP_WEBHOOK_SECRET_FILE. 503 until the App is fully configured
POST /api/v1/hooks/{git_host}/{project}/{integration_name} gitea / forgejo: HMAC from X-Forgejo-Signature, then X-Gitea-Signature. gitlab: X-Gitlab-Token compared in constant time. github is answering 400
  • The generic route can find the integration by (project, inbound, name), without git_host_type.
  • One inbound row can answer all three Git hosts.
  • The server will decrypt the secret with the crypt file.
  • allowed_ips will reject other sources with 403.
  • GitHub installation / installation_repositories events upsert or clear github_installation and seed the github-<login> integration pair (github-<installation_id> without a login).

GitHub App Events

Event Handler
push Push chain below
pull_request Pull request triggers
release route_github_app_release: triggers with releases_only
check_run approval::handle_github_check_run
pull_request_review approval::handle_pull_request_review
issue_comment commands::handle_issue_comment: comment commands
installation, installation_repositories handle_github_installation

Push Chain

Step Code Action
1 fan_out_triggers (git_host_hooks/fanout.rs) Active task_trigger rows of type ReporterPush whose branch and tag globs match
2 normalize_repo_url, event_repo_matches_task Stripping .git and a trailing /, rewriting git@ URLs. Comparing lowercased owner/repo, ignoring the host
3 gradient_ci::apply_trigger Dedup and concurrency, aborting the running evaluation or parking the new one in Waiting. A violation of uq_evaluation_one_active_per_task is mapping to SkippedConcurrency
4 gradient_ci::trigger::trigger_evaluation Inserting the Commit row and a Queued evaluation, setting task.force_evaluation, resetting last_check_at
5 eval-dispatch Woken by the created evaluation (record_evaluation_created), offering the evaluation to workers. The 5 s tick is the fallback