OpenProject ↔ Slack Bridge
Ticket changes into threaded Slack notifications, with a GitOps config dashboard
Overview
An internal tool that turns OpenProject ticket changes into threaded Slack notifications and personal DMs. I rewrote a Python prototype into a Go engine plus a Next.js dashboard, made it multi-tenant, and built its deployment. Delivered with Claude Code, Codex and Cursor.
Architecture
OpenProject webhooks → Go engine (snapshot diff → Slack Block Kit messages, threads and DMs; S3 for media; cron jobs per instance). Admin service (Go) ↔ GitLab API for versioned YAML config; push webhook → per-service rebuild or restart over SSH. Next.js dashboard with dropdowns filled from live OpenProject and Slack data. The engine ships as a scratch-based image built by GitLab CI.
Key Highlights
Field-level change detection against stored snapshots; threaded channel messages and role-based DMs
Private attachments re-hosted on S3 so they render in Slack; thread links written back to the ticket
One deployment serves 3 OpenProject instances (separate teams), with per-instance config and data isolation
Scheduled bug-statistics, ticket-health and daily-report jobs with batched messages
GitOps config dashboard: every edit is a Git commit through the GitLab API (~340 changes); a push webhook rebuilds or restarts only the affected service
Technical Decisions
| Technical Decisions | Chosen | Alternative | Reason |
|---|---|---|---|
| Config store | YAML in Git, edited through a dashboard that commits via the GitLab API | A database table | Every change gets history, review and revert for free, and config-only edits can restart services without rebuilding images. |