CI/CD
Two distinct pipelines: service images (build → registry → Flux) and docs sites (build → Cloudflare Pages).
Service image builds
Each Node service has a buildspec.yml (AWS CodeBuild). The shared shape:
1. ECR/ACR login
2. docker build (from the service Dockerfile)
3. tag + push to the registry
4. post-build: kubectl rollout restart (where applicable)
From there, FluxCD's image automation takes over — see
Deployment & GitOps. The registry is
Azure ACR (knockknockacr.azurecr.io) for Flux-tracked tags; some specs also push
to AWS ECR.
Dockerfiles are multi-stage and run as non-root on Node 22 Alpine (frontend's Dockerfile.azure moved to node:24-alpine on 2026-09-04):
| Service | Notable build detail |
|---|---|
| backend | Node 22 + FFmpeg, 6 GB heap, port 8888 |
| ms-ai | 3-stage (deps → build → runtime); workflows use docker/setup-buildx-action@v3 with an ACR :buildcache registry cache (mode=max); prod pushes straight from buildx (--push, no --load — the tarball round-trip cost ~5 min), dev uses --load; migrations run as a deploy step via npm run migration:run:prod |
| ms-communication / ms-sessions | Node 22 Alpine; ms-sessions ships an HTTP image + a worker process |
| frontend / widget | multi-stage → nginx Alpine static serving. Frontend has no lockfile by design, so every CI build re-resolves from the registry — npm 10.9.8 crashed with Cannot read properties of null (reading 'edgesOut') on vitest 5.0.0's peers (2026-09-03), fixed by the node:24 (npm 11) base |
| desktop | not containerized — electron-builder → GitHub releases |
There are also Dockerfile.azure / Dockerfile.stage variants per service for the
Azure and staging targets.
Desktop releases
desktop publishes via electron-builder → GitHub releases (publish /
publish:next for white-label), with delta updates consumed by electron-updater.
Not part of the Kubernetes pipeline.
Docs sites
Both docs-site and internal-docs deploy to Cloudflare Pages via GitHub
Actions on push to main:
# .github/workflows/deploy.yml
- npm ci
- npm run build
- wrangler pages deploy build --project-name=knock-knock-internal-docs
(Customer docs use --project-name=knock-knock-docs.) Requires the
CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID repo secrets.
Branch model
Service repos build from dev; flux-deployments and the docs sites track main.
Image automation bumps tags in flux-deployments automatically — those commits are
made by the Flux bot, not engineers.