Production-ready university course monorepo starter for centralized GitHub Actions monitoring and analytics.
- Course: Full stack Application Development with Node.js + Express.js + React.js - 2026
- Author: Yordan B.
- FN: 9MI3400735
DWMAS centralizes workflow execution data across repositories, provides role-based access control, realtime monitoring, analytics, local issues/comments, and export/reporting.
Key highlights:
- GitHub OAuth-only authentication (no local email/password auth)
- Automatic local user creation on first OAuth login
- Default first role:
DEVELOPER(admin bootstrap through env allow-list) - PostgreSQL + Prisma persistence
- REST API with validation and RBAC middleware
- Realtime updates via SSE and Socket.IO
- SPA frontend with protected routes and role-aware navigation
dwmas/
apps/
api/ # Express + TypeScript backend (REST, RBAC, Prisma, realtime)
web/ # React + Vite + TypeScript SPA dashboard
github-gateway/ # Express reverse proxy: token pool, Redis cache, GitHub API proxy
worker/ # BullMQ background job worker (repo sync, analytics)
packages/
shared/ # Shared constants, types, and utilities
github-contracts/ # Typed contracts for GitHub Gateway ↔ API communication
prisma/
schema.prisma # Canonical Prisma schema (source of truth)
README.md # Schema docs, ERD, migration workflow
docs/
architecture.md # System architecture + Mermaid diagrams
oauth-sequence.md # GitHub OAuth login sequence
workflow-sync-sequence.md # Workflow sync sequence
docker-compose.yml
pnpm-workspace.yaml
.env.example
LICENSE
README.md
| Service / Package | README |
|---|---|
| API (backend) | apps/api/ — see root README sections below |
| Web (frontend SPA) | apps/web/README.md |
| GitHub Gateway | apps/github-gateway/README.md |
| Worker | apps/worker/README.md |
| Prisma schema | prisma/README.md |
| Architecture & diagrams | docs/architecture.md |
| OAuth sequence | docs/oauth-sequence.md |
| Workflow sync sequence | docs/workflow-sync-sequence.md |
- Frontend: React 18, Vite, TypeScript, React Router, TanStack Query, Zustand, Tailwind CSS, Recharts
- Backend: Node.js, Express, TypeScript
- ORM/DB: Prisma + PostgreSQL
- Auth: GitHub OAuth (Passport GitHub strategy), httpOnly cookie token
- Validation: Zod
- Logging: Pino
- Realtime: SSE + Socket.IO
- GitHub Integration: Octokit
- Testing: Vitest, Supertest, React Testing Library
- Quality: ESLint + Prettier
GET /api/auth/githubGET /api/auth/github/callbackPOST /api/logoutGET /api/me- RBAC middleware:
requireAuthrequireRolesrequireRepositoryAccess
GET /api/usersGET /api/users/:userIdPUT /api/users/:userIdDELETE /api/users/:userId(soft deactivate)
GET /api/repositoriesPOST /api/repositoriesGET /api/repositories/:repoIdPUT /api/repositories/:repoIdDELETE /api/repositories/:repoIdPOST /api/repositories/:repoId/sync
GET /api/workflowsGET /api/workflows/:workflowIdGET /api/workflows/:workflowId/jobs
GET /api/analyticsGET /api/analytics/summaryGET /api/analytics/trendsGET /api/analytics/failure-rateGET /api/analytics/repositories
GET /api/active-runs(SSE)- Socket event:
active-runs:updated
GET /api/repositories/:repoId/issuesPOST /api/repositories/:repoId/issuesGET /api/repositories/:repoId/issues/:issueIdPUT /api/repositories/:repoId/issues/:issueIdDELETE /api/repositories/:repoId/issues/:issueIdGET /api/issues/:issueIdGET /api/issues/:issueId/commentsPOST /api/issues/:issueId/commentsDELETE /api/issues/:issueId/comments/:commentId
GET /api/export/workflows.csvGET /api/export/workflows.json
GET /api/healthGET /api/docs
Copy .env.example to .env and fill values:
DATABASE_URLSESSION_SECRETJWT_SECRETCORS_ORIGINGITHUB_CLIENT_IDGITHUB_CLIENT_SECRETGITHUB_CALLBACK_URLGITHUB_API_TOKEN(recommended for sync)ADMIN_GITHUB_IDS/ADMIN_GITHUB_USERNAMESVITE_API_URLVITE_API_WS_URL
- Node.js 20+
- pnpm 9+
- Docker + Docker Compose
pnpm installdocker compose up -dpnpm run prisma:generate
pnpm run prisma:migrate
pnpm run prisma:seedpnpm run dev- API:
http://localhost:4000 - Web:
http://localhost:5173
- Create GitHub OAuth App.
- Set callback URL to
http://localhost:4000/api/auth/github/callback. - Put client ID/secret into
.env. - Open
http://localhost:5173/loginand use Continue with GitHub.
The app keeps GitHub OAuth as the source of authentication and uses environment allow-lists to assign internal roles:
ADMIN_GITHUB_USERNAMES/ADMIN_GITHUB_IDS→ user becomesADMINDEVOPS_GITHUB_USERNAMES/DEVOPS_GITHUB_IDS→ user becomesDEVOPS- otherwise default role is
DEVELOPER
Example .env:
ADMIN_GITHUB_USERNAMES=your_admin_username
ADMIN_GITHUB_IDS=1234567
DEVOPS_GITHUB_USERNAMES=your_devops_username
DEVOPS_GITHUB_IDS=7654321- Put your GitHub username or ID in
ADMIN_GITHUB_USERNAMESorADMIN_GITHUB_IDS - Login via GitHub OAuth
- Open
/profileand confirm role badge showsAdmin - Open
/usersand manage other users
- Admin: configured via admin bootstrap env vars above
- DevOps: configured via devops bootstrap env vars, or promoted by admin from Users page
- Developer: default for any OAuth user not matched by admin/devops bootstrap, or set by admin
- Developer can see workflow/repository data only for:
- repositories assigned to them
- repositories they connected/created
- DevOps/Admin can see all repositories/workflows
- Admin manages role and repository assignments in
/users
Workflow visibility is now fixed end-to-end with these behaviors:
- Connect repository in
/repositories - Click Sync runs
- Server fetches GitHub Actions workflow runs (paginated) and persists runs + jobs
- Open
/workflowsto browse runs - Open run details page for jobs/metadata
If no runs exist in the GitHub repository, UI clearly shows an explicit empty state. If sync fails (permissions/repo/API), API now returns readable sync error text that is shown in UI.
- GitHub is the authoritative source for repository/workflow/jobs data.
- PostgreSQL stores synchronized snapshots/cache for fast UI reads, analytics, reporting and history.
- The system uses a hybrid sync strategy:
- eager sync on repository connect
- manual sync via “Sync runs”
- lazy/background refresh when repository/workflow data is stale or
refresh=trueis requested
Repository records now include sync metadata fields:
syncStatus(IDLE|SYNCING|SUCCESS|ERROR)lastSyncedAtlastSuccessfulSyncAtsyncErrorsourceUpdatedAt
- OAuth login:
read:user,user:email - Repository sync: server token (
GITHUB_API_TOKEN) should have access to target repositories and Actions data - For private repos, token must include the repository in scope
- Visible logout button is available in the top-right authenticated header.
- Clicking logout calls
POST /api/auth/logout, clears auth cookie/session, resets frontend auth state, clears cached queries, and redirects to/login.
- Verify repository exists in
/repositories - Check repository sync status column (
SUCCESSexpected) - If status is
ERROR, readsyncErrorand fix token/repo permissions - Click Sync runs again
- In
/workflows, optionally enable “Refresh from GitHub on apply” and apply filters
- Ensure
.envincludes correctADMIN_GITHUB_USERNAMESorADMIN_GITHUB_IDS - Re-login via GitHub OAuth
- Open
/profileand verify role badge isADMIN
- Confirm frontend calls
POST /api/auth/logout - Confirm
dwmas_tokencookie is cleared in browser devtools - Protected routes should redirect to
/loginafter logout
Report templates are saved filter configurations for workflows analytics/export.
Each template can include:
- report name + description + type
- date range preset (
7d,30d,90d,custom) - filters (
status,conclusion,branch,actor) - optional repository targeting
- export format preference (CSV/JSON-ready)
- Open
/reports - Create template with desired filters
- Save template
- Apply template to preview filtered workflow data
- Export CSV using template action
- Failed runs last 30 days
- Repository health overview
- Main branch deployment failures
- Average duration trend by repository
- Prisma seed creates:
- admin-like demo user
- one repository
- repository assignment
- report templates
- First login becomes
ADMINwhen GitHub ID or username matches:ADMIN_GITHUB_IDSADMIN_GITHUB_USERNAMES
pnpm run testpnpm run lint
pnpm run formatIf zsh suggests correct 'pnpm' to 'npm', choose n. Using npm in this workspace can break pnpm workspace linking.
- Basic OpenAPI-like descriptor:
GET /api/docs
See docs/:
docs/architecture.mddocs/oauth-sequence.mddocs/workflow-sync-sequence.md
Implemented:
- Monorepo architecture
- OAuth-only auth flow
- RBAC and repository-scoped access checks
- Repository onboarding + workflow sync with Octokit
- Realtime stream and socket push
- Analytics, exports, local issues/comments
- Seed/bootstrap path and base tests
Optional/Future:
- richer Swagger UI generation
- webhook-triggered sync
- advanced analytics caching and report template UI
- broader test coverage for all pages and edge conditions
- Move secrets to secure vault.
- Use managed PostgreSQL.
- Set
NODE_ENV=productionand secure cookie domain. - Build web assets and serve behind reverse proxy.
- Add CI pipeline and production observability.
MIT (LICENSE)