DevPulse is a full-stack engineering analytics workspace for GitHub and Gitea. It ingests repository activity into PostgreSQL, processes sync work through a Redis-backed worker, and turns commits, pull requests, reviews, sync health, and team delivery signals into repository-level trends and recommended actions. A separate FastAPI ML service estimates merge time for open pull requests and records versioned predictions with confidence ranges.
The current version is focused on one clean loop:
- Connect GitHub through either the Standard or Full GitHub App flow.
- Optionally connect any Gitea server from Settings.
- Discover repositories.
- Sync them in the background through Redis.
- Explore trends, forecasts, recommended actions, and supervisor views in the dashboard.
Repository hosts expose activity, but they do not always explain where a team should focus next. DevPulse combines GitHub and self-hosted Gitea data in one workspace, supports personal and whole-repository scopes, and connects each recommendation to the repository and evidence that produced it.
- GitHub App sign-in with tiered Standard / Full access and an HTTP-only session cookie
- Per-user Gitea connections for any compatible server, with encrypted access-token storage
- Supervisor team workspaces with explicit shared-repository assignment and role-based membership
- Team-only delivery totals for commits, pull requests, merges, and reviews without exposing personal repos
- Background repo sync queue backed by Redis
- Manual sync actions for all visible repos or a single repo
- Nightly / catch-up sync worker flow
- Repo visibility management for hiding repos from the dashboard
- Bulk restore for hidden repositories
- Repo-manager search, status/visibility filters, result counts, and quick reset
- Dashboard totals for repos, commits, pull requests, and active repos
- Contribution heatmap with date range and
Mine/Allscope 30d,90d,1y, and true all-time analytics windows- Repo-level detail view with:
- commit trend
- PR cycle trend
- review latency
- sync status and last sync error details
- commit and pull-request comparisons against workspace averages
- stable hover readouts with weekly PR/review sample counts
- Evidence-backed recommended actions with repository links and impact levels
- Seven-day snooze, dismiss/restore controls, and browser-persisted outcome baselines
- Improvement/regression tracking against the first observed recommendation metric
- Provider-aware repo handling for GitHub and Gitea
- API smoke tests and helper tests
- Queue payload validation and background-sync failure coverage
- Settings diagnostics for queue depth, worker state, and recent sync failures
- One-click retry for failed GitHub and Gitea syncs
- PR merge-time forecasts for open pull requests
- Time-ordered Random Forest evaluation with a median-baseline safety fallback
- Versioned prediction history with confidence ranges and feature snapshots
- Automatic post-sync inference and scheduled model retraining
- Render deployment config for API, web, and ML services
- Production Docker Compose, container health checks, and GitHub Actions CI
- AES-256-GCM encryption for newly stored GitHub provider tokens
| Layer | Tech |
|---|---|
| Frontend | React, Vite, TypeScript |
| API | Fastify, TypeScript |
| ORM | Prisma |
| Database | PostgreSQL |
| Queue / cache | Redis |
| ML service | FastAPI, pandas, scikit-learn |
| Local orchestration | Docker Compose |
| Monitoring scaffold | Prometheus, Grafana |
GitHub App / per-user Gitea token
|
v
Fastify API
|
---------------------------
| | |
v v v
PostgreSQL Redis React dashboard
|
v
Background worker
|
v
FastAPI ML service
The API owns auth, provider sync, database writes, analytics responses, and repo visibility state. The worker consumes Redis jobs and performs background syncs with bounded exponential retry, schedules stale repositories, and starts model retraining. The ML service trains and serves PR-cycle predictions. The frontend reads the APIs using the HTTP-only session cookie created after sign-in.
The dashboard currently calculates:
- Daily commit history and contribution intensity
- Repository activity compared with workspace averages
- Weekly PR cycle-time direction, average, and median
- Time from pull-request creation to first review
- Repository sync freshness and failure state
- Open-PR merge-time forecasts and confidence ranges
Recommended actions are deterministic and evidence-backed. They identify stale or failed syncs, slow first reviews, long PR cycles, and concentrated activity. Each action includes an impact level, the source repository, supporting evidence, and a direct sync or inspect command. Dismissed and snoozed actions are stored in the browser, along with the first observed metric used to show later movement.
The PR-cycle model uses repository, provider, author, title length, weekday, and opening-hour features. Training is chronological: the oldest 80% of merged PRs form the training set and the newest 20% form the evaluation set. DevPulse uses a 300-tree Random Forest only when it beats a median predictor on mean absolute error; otherwise it retains the baseline. Fewer than 20 merged PRs also keeps the baseline, avoiding a misleading model trained on too little data.
- Node.js
20+ - Docker Desktop
- Python
3.11or3.12forml-service
Python 3.14 is not supported by the pinned ML stack in
ml-service/requirements.txt. If you use the system's newest Python, numpy,
pandas, and scikit-learn may fail to install.
cd api
npm install
cd ../web
npm installThe root .env is used by docker-compose.yml.
cp .env.example .envFill in your provider values:
DATABASE_URL=postgresql://devpulse:devpulse_secret@localhost:5433/devpulse_db
JWT_SECRET=change_me_in_production
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GITHUB_APP_ID=
GITHUB_APP_PRIVATE_KEY=
GITHUB_APP_SLUG=
GITHUB_APP_WEBHOOK_SECRET=
GITHUB_APP_FULL_CLIENT_ID=
GITHUB_APP_FULL_CLIENT_SECRET=
GITHUB_APP_FULL_ID=
GITHUB_APP_FULL_PRIVATE_KEY=
GITHUB_APP_FULL_SLUG=
GITHUB_APP_FULL_WEBHOOK_SECRET=
GITHUB_CALLBACK_URL=http://localhost:3000/auth/github/callback
REDIS_URL=redis://localhost:6379
ML_SERVICE_URL=http://localhost:8001
ML_SERVICE_TOKEN=
SYNC_INTERVAL_SECONDS=86400
RUN_ON_START=true
SYNC_MAX_ATTEMPTS=3
SYNC_RETRY_BASE_MS=5000
SYNC_RETRY_MAX_MS=60000
PROVIDER_REQUEST_CONCURRENCY=5
FRONTEND_URL=http://localhost:5173
PORT=3000
HOST=127.0.0.1Do not commit real secrets.
You can also use api/.env.example as a reference when running the API outside Docker.
docker compose up postgres redisPostgres is mapped to local port 5433 to avoid clashing with other local
installs.
cd api
npx prisma migrate devcd api
npm run build
node dist/index.jsHealth check:
http://localhost:3000/health
In another terminal:
cd api
npm run worker:devcd web
npm run devOpen:
http://localhost:5173
cd ml-service
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn api.main:app --host 127.0.0.1 --port 8001If python3.12 is not available on your machine, use python3.11.
Train the model manually after syncing merged pull requests:
curl -X POST http://localhost:8001/train/pr-cycleThe background worker also retrains on startup and on the configured training interval.
DevPulse supports two GitHub App tiers:
Standard: public repos, PRs, reviews, and commentsFull: everything in Standard plus commit history, activity analytics, and private repos you explicitly select during GitHub App installation
For local development and Render deployment, configure:
GITHUB_APP_IDGITHUB_APP_PRIVATE_KEYGITHUB_APP_SLUGGITHUB_APP_WEBHOOK_SECRETGITHUB_APP_FULL_CLIENT_IDGITHUB_APP_FULL_CLIENT_SECRETGITHUB_APP_FULL_IDGITHUB_APP_FULL_PRIVATE_KEYGITHUB_APP_FULL_SLUGGITHUB_APP_FULL_WEBHOOK_SECRETGITHUB_CALLBACK_URL
The callback URL for local web sign-in is:
http://localhost:3000/auth/github/callback
After login, the API stores the GitHub access token, GitHub App installation
metadata, signs a devpulse_token cookie, and redirects back to the frontend.
If Full access is connected but private repos still do not sync, the usual cause is GitHub App installation scope: the Full app must be installed and the private repository must be selected during the installation flow.
The repo includes render.yaml for a free-tier Render setup with three services:
devpulse-web: static React frontenddevpulse-api: Fastify APIdevpulse-ml: FastAPI ML service
The API can run its background worker inside the same Render service with:
RUN_WORKER_IN_API=trueRender also expects:
DATABASE_URLDATABASE_URL_UNPOOLEDREDIS_URLUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKENML_SERVICE_URLML_SERVICE_TOKENJWT_SECRETTOKEN_ENCRYPTION_KEYFRONTEND_URL
After provisioning Postgres, run Prisma migrations against the deployed API database before first use.
cd api
npm run dev
npm run worker:dev
npm testcd web
npm run dev
npm run build
npm testcd ml-service
.venv/bin/python -m unittest discover -s tests| Route | Method | Purpose |
|---|---|---|
/health |
GET | API health check |
/auth/github |
GET | Start GitHub App sign-in |
/auth/github/callback |
GET | GitHub App callback |
/auth/me |
GET | Current session user |
/auth/logout |
POST | Clear session cookie |
/auth/system |
GET | API / provider / queue status |
/github/repos |
GET | Discover and save GitHub repos |
/github/repos/manage |
GET | Visible + hidden repo manager data |
/github/repos/sync-all/background |
POST | Queue all visible GitHub repos |
/github/repos/:repoId/sync/background |
POST | Queue one GitHub repo |
/github/repos/:repoId/visibility |
POST/PATCH | Hide or restore a repo |
/github/repos/:repoId/summary |
GET | Repo-level metrics |
/github/repos/:repoId/pr-cycle |
GET | Weekly PR cycle trend |
/github/repos/:repoId/review-latency |
GET | Weekly review latency |
/github/repos/:repoId/predictions |
GET | Latest open-PR merge forecasts |
/github/overview |
GET | Dashboard totals and repo list |
/github/activity |
GET | Daily commit counts |
/github/insights |
GET | High-level dashboard insights |
/gitea/repos |
GET | Discover and save Gitea repos |
/gitea/connect |
POST | Validate and securely save the current user's Gitea connection |
/gitea/repos/sync-all/background |
POST | Queue all visible Gitea repos |
/gitea/repos/:repoId/sync/background |
POST | Queue one Gitea repo |
/teams |
GET / POST | List or create team workspaces |
/teams/:teamId |
GET | Read metrics from explicitly shared team repositories |
/teams/:teamId/repos |
PUT | Replace the team's shared repository set (owner/admin) |
/teams/:teamId/members |
POST | Add a signed-up DevPulse user to a team (owner/admin) |
devpulse/
├── api/ # Fastify API, Prisma schema, worker, tests
├── web/ # React dashboard
├── ml-service/ # PR cycle-time training and inference service
├── etl/ # older ETL scaffold
├── infra/ # monitoring / infra config
├── docker-compose.yml
└── README.md
Current test coverage includes:
- 56 API route, queue, retry, provider, sync, and encryption tests
- 7 frontend filtering, comparison, queue-copy, and sync-health tests
- Python tests for PR-cycle model training and prediction behavior
Run them with:
cd api && npm test
cd web && npm test
cd ml-service && python -m unittest discover -s tests- The frontend uses
VITE_API_URL, defaulting tohttp://localhost:3000. - Set
TOKEN_ENCRYPTION_KEYbefore reconnecting GitHub to encrypt newly stored access tokens. Existing plaintext local tokens remain readable for migration. - Generate a token key with
openssl rand -base64 32. .DS_Storeis ignored and should stay untracked.- The ML service should be run with Python
3.11or3.12. - This is a portfolio-ready v1, but not a fully hardened multi-tenant production SaaS.