feat(orchestration): event-driven webhook queue, trigger evaluation, PR/tag pipelines, Checks reporting, repo event timeline - #39
Conversation
…PR/tag pipelines, Checks reporting, repo event timeline
GitHub becomes purely the event source and repository provider; overup is
the complete CI/CD control plane. The webhook receiver now does
verification -> validation -> durable persistence -> 202 ack only, and
every side effect runs asynchronously off the request path.
Backend:
- Durable webhook queue: webhook_deliveries gains a normalized server-built
payload (never the raw body), pending|processing|processed|ignored|failed
lifecycle, and retry_count (migration 20260717000001)
- services/webhook_processor.rs: sequential FOR UPDATE SKIP LOCKED consumer
(poke + 2s tick) preserving per-repo ordering; <=3 retries, 5-min
stuck-row revert, payload nulling on terminal states; manual GitHub
redelivery revives a terminally failed row
- services/trigger_eval.rs: pure/bounded GitHub-flavored trigger evaluation
- parser v3 extracts on.push / on.pull_request filters into
workflows.metadata.triggerFilters; hand-rolled glob (*, **, ?, +,
[a-z], \ escapes, ordered ! negation) with no regex or recursion;
branch+path dimensions compose, paths never apply to tags, truncated
changed-path sets fail open on path filters only
- PR + tag pipelines: trigger vocabulary push|manual|pull_request|tag,
pipelines.pr_number; PR head SHAs build under refs/pull/{n}/head; fork
PRs are skipped with static fork_pr_skipped (secrets never flow to fork
code); refs/tags/ pushes run on:push workflows as trigger tag
- services/github_checks.rs: best-effort Checks API reporting for
event-triggered pipelines (queued -> in_progress -> completed with a
details link); a SEPARATE checks:write installation token keeps the sync
token read-only; 403/422 parks the installation for 1h with one
edge-triggered warn; GITHUB_CHECKS_ENABLED gate; fast pipelines that
finish before the async create fall back to creating the check run
directly in completed status
- Immutable repository_events timeline (outcome CHECK, static
ignored_reason, pipeline_ids[], capped summary) + keyset
GET .../repositories/{id}/events + a health object on the repo detail
response; terminal delivery failures always surface a failed timeline row
Frontend (same design system throughout):
- RepositorySyncPanel: KPI strip (Auto-sync, Last event, Pending,
Failed 24h, GitHub checks) between the meta strip and tabs
- RepositoryEventsList: Events tab with outcome badges, ref/PR/tag chips,
skip tooltips, pipeline links, IntersectionObserver infinite scroll
- Pipelines UI: pull_request/tag trigger filters + icons, PR # link on the
Metadata tab, branchOfRef renders tag and PR refs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
✅ Deploy Preview for overup-app ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (38)
📝 WalkthroughWalkthroughThis change adds durable asynchronous webhook orchestration, GitHub-style trigger evaluation, pipeline Checks reporting, immutable repository event history and health APIs, and frontend repository and pipeline displays for pull request and tag triggers. ChangesEvent orchestration
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant GitHub
participant WebhookReceiver
participant WebhookQueue
participant WebhookProcessor
participant PipelineRun
participant GitHubChecks
GitHub->>WebhookReceiver: Send verified webhook
WebhookReceiver->>WebhookQueue: Persist normalized payload
WebhookReceiver-->>GitHub: Return 202 Accepted
WebhookProcessor->>WebhookQueue: Claim delivery
WebhookProcessor->>PipelineRun: Evaluate triggers and create pipelines
PipelineRun->>GitHubChecks: Report lifecycle phase
GitHubChecks->>GitHub: Create or update check run
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
There was a problem hiding this comment.
This PR successfully delivers the event-driven orchestration layer with solid security practices and thorough implementation. The webhook handler properly performs constant-time HMAC verification, caps all inputs, and sanitizes data before persistence. The asynchronous processor maintains per-repo ordering guarantees while handling retries and crash recovery. The trigger evaluation uses bounded iterative glob matching to prevent DoS attacks. Fork PR protection is correctly implemented, and all paths are validated before URL interpolation. The codebase is well-tested with 190 passing tests and demonstrates production-ready quality.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
Summary
Ships the event-driven orchestration layer: GitHub becomes purely the event source and repository provider, while overup remains the complete CI/CD control plane. The webhook endpoint now does verification → validation → durable persistence → 202 ack ONLY (GitHub's 10-second budget), and every side effect — sync scheduling, trigger evaluation, pipeline creation, timeline writes, Checks reporting — runs asynchronously off the request path.
Architecture
webhook_deliveriesbecomes a queue: normalized server-built payload JSONB (never the raw body),pending|processing|processed|ignored|failedlifecycle,retry_count(migration20260717000001). Events from repositories not connected to any workspace are discarded before any processing.services/webhook_processor.rs) — sequentialFOR UPDATE SKIP LOCKEDconsumer (poke + 2 s tick) preserving per-repo ordering; ≤3 retries, 5-min stuck-row revert, payload nulling on terminal states so the table stays bounded; a manual GitHub redelivery revives a terminally failed row. Timeline row + delivery status flip commit in one transaction.services/trigger_eval.rs, pure/bounded) — parser v3 extractson.push/on.pull_requestfilters intoworkflows.metadata.triggerFilters; hand-rolled GitHub-flavored glob (*,**,?/+,[a-z],\escapes, ordered!negation, last match wins) with no regex and no recursion; branch AND path dimensions must both pass, paths never apply to tag pushes, truncated changed-path sets fail OPEN on path filters only. Skips are recorded per-workflow with static reasons.push|manual|pull_request|tag(+pipelines.pr_number); PR head SHAs build underrefs/pull/{n}/head; fork PRs are skipped with staticfork_pr_skipped(secrets never flow to fork code);refs/tags/pushes runon: pushworkflows as triggertag. Cron stays parse/display-only.services/github_checks.rs) — event-triggered pipelines surface as GitHub check runs (queued → in_progress → completed,details_url→ the pipeline page; static templates + job counts, never runner text). A separatechecks:writeinstallation token keeps the sync token read-only; 403/422 parks the installation for 1 h with one edge-triggered warn;GITHUB_CHECKS_ENABLED(default true) gates it. Manual dispatches never report.repository_events(outcome CHECK, staticignored_reason,pipeline_ids[], capped summary) feeds a keysetGET …/repositories/{id}/eventsand ahealthobject on the repo detail response.UI (same design system throughout)
RepositorySyncPanel— KPI strip (Auto-sync, Last event, Pending, Failed 24 h, GitHub checks) between the repo meta strip and tabs; identical to the dashboard KpiStrip pattern.RepositoryEventsList— new Events tab: ActivityFeed-style compact rows, outcome badges, ref/PR/tag chips, skip tooltips, pipeline links, IntersectionObserver infinite scroll with Load-more fallback.pull_request/tagtrigger filter options + icons, PR # link on the Metadata tab,branchOfRefrenders tag andPR #nrefs.Hardening fixes applied in review
queued; completion now falls back to creating the check run directly incompletedstatus.failedrepository timeline row (previously only processing errors did).#[allow(dead_code)]onClaimedDelivery.installation_id.Security notes
outcome/ignored_reason/skip reasons are static category strings, CHECK-enforced in SQL./webhooks; replay protection = delivery-id idempotency (GitHub does not sign a timestamp).Deliberately deferred (follow-ups)
Workflow version archiving, concurrency groups, cron/schedule dispatch,
release/deployment/check_suite rerequestedevents, Commit Status API fallback when Checks is unavailable.Verification
cargo check,cargo clippy -- -D warnings,cargo test(190 passed) inbackend/npm run build— compiled successfully🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
GITHUB_CHECKS_ENABLED.Bug Fixes
Documentation