GitHub Actions DVR — rewind, replay, and analyze your CI/CD pipeline
ActionStream captures every GitHub Actions workflow run, job, and step in real-time via webhooks. It stores events in a time-series-friendly Postgres database and lets you scrub through CI/CD history like a DVR — pause, rewind, fast-forward. Built for teams that need visibility beyond the GitHub Actions UI.
Stream workflow events in real-time via Server-Sent Events. Watch runs execute step-by-step as they happen, with automatic UI updates and a live indicator.
Scrub to any point in time using the timeline slider and see the exact state of all workflows at that moment. Pre-computed snapshots make loading any time range instant.
Duration trends, success/failure rates, and historical analysis across all your workflows. Identify regressions before they become patterns.
Estimate GitHub Actions billing based on runner type and duration. Track spending trends over time.
Automatically identify workflows and steps that intermittently fail. Surface unreliable tests so you can fix them instead of re-running and hoping.
Side-by-side performance comparison between workflows. See how duration and reliability differ across branches, triggers, or time periods.
Get alerted on failures. Never miss a broken build again.
One dashboard for all your GitHub organizations. Filter by org, repo, workflow, branch, status, or event type.
Go beyond job-level visibility. ActionStream records individual step timing and status, giving you the granularity to pinpoint exactly where builds slow down or fail.
GitHub App ──webhook──▶ Next.js API ──enqueue──▶ Redis / BullMQ
│
Worker (10 concurrent)
│
┌─────────┴─────────┐
▼ ▼
Postgres Redis PubSub
(persistence) (live events)
│ │
▼ ▼
REST API ◀───── SSE ──▶ Dashboard
Webhooks arrive at a Next.js API route and are immediately enqueued in BullMQ (backed by Redis) so the response is fast and no events are lost under burst traffic. A background worker processes events with 10 concurrent jobs — writing to Postgres for persistence and publishing to Redis PubSub for live dashboard updates via SSE.
Pre-computed snapshots are built periodically so that loading any historical time range is a single query, not an expensive aggregation.
| Layer | Technology |
|---|---|
| Frontend | Next.js 15 (App Router + Turbopack), React 19, Tailwind CSS, Recharts |
| Backend | Next.js API Routes, Prisma 6 ORM |
| Queue | BullMQ 5 + Redis 7 (via ioredis) |
| Database | PostgreSQL 15 |
| Auth | GitHub App (Octokit) |
| Testing | Vitest |
| Infra | Docker Compose (dev), Vercel (prod) |
- Node.js 20+
- Docker & Docker Compose
- A GitHub App (setup guide below)
git clone https://github.com/tag-assistant/actionstream.git
cd actionstream
npm installdocker compose up -dStarts Postgres (5432) and Redis (6379) with health checks and persistent volumes.
cp .env.example .envEdit .env with your GitHub App credentials. See Environment Variables for details.
npx prisma generate
npx prisma db push# Terminal 1: Dev server
npm run dev
# Terminal 2: Queue worker
npm run workerOpen http://localhost:3000 🎉
Reference .env.example for the full template.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
REDIS_URL |
Yes | Redis connection string (for BullMQ) |
GITHUB_APP_ID |
Yes | Your GitHub App's ID |
GITHUB_APP_PRIVATE_KEY |
Yes | PEM private key (newlines as \n) |
GITHUB_WEBHOOK_SECRET |
Yes | Webhook secret from your GitHub App |
GITHUB_APP_INSTALLATION_ID |
Yes | Installation ID for your org/repo |
Docker Compose overrides (optional): POSTGRES_PASSWORD, POSTGRES_PORT, REDIS_PORT, APP_PORT.
ActionStream uses a GitHub App for webhook delivery and API access.
| Permission | Access | Purpose |
|---|---|---|
| Actions | Read | Query workflow runs and jobs |
| Metadata | Read | Basic repo info |
workflow_run— Track run lifecycle (queued → in_progress → completed)workflow_job— Track individual job and step execution
Set your webhook URL to https://your-domain.com/api/webhooks/github.
See github-app.yml for the full manifest.
actionstream/
├── app/src/
│ ├── app/ # Next.js App Router
│ │ ├── api/ # Webhook, dashboard, analytics, live SSE endpoints
│ │ ├── dashboard/ # Live dashboard with time-travel slider
│ │ ├── analytics/ # Duration trends & failure analysis
│ │ ├── compare/ # Side-by-side workflow comparison
│ │ ├── flaky/ # Flaky workflow detection
│ │ └── notifications/ # Failure alerts
│ ├── components/ # StatsBar, FilterBar, TimeSlider, RunList, etc.
│ └── hooks/ # useLiveEvents (SSE), useRunFilters
├── lib/
│ ├── analytics/ # Analytics computation
│ ├── db/ # Prisma client & seed data
│ ├── github/ # GitHub App auth & webhook verification
│ ├── queue/ # BullMQ queue, worker, Redis connection
│ ├── types/ # Shared TypeScript types
│ └── utils/ # BigInt serialization, helpers
├── prisma/ # Schema & migrations
├── tests/ # Vitest test suite
├── docker-compose.yml # Postgres + Redis for local dev
├── .env.example # Environment variable template
└── github-app.yml # GitHub App manifest
npm run dev # Next.js dev server (Turbopack, port 3000)
npm run worker # BullMQ worker (separate terminal)
npm run build # Production build
npm run lint # ESLint
npm run test # Vitest test suite
npm run test:watch # Vitest watch mode
npx prisma studio # Database GUI
npx prisma db push # Push schema changes
npm run db:seed # Seed sample datadocker compose up -d # Start everything
docker compose logs -f # Tail logs
docker compose down # StopContributions are welcome! To get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes and add tests
- Run
npm run lint && npm testto verify - Commit with a descriptive message
- Open a Pull Request
Please keep PRs focused and include tests for new functionality.