Deployment

Docker

A single multi-stage Dockerfile builds all apps into one image.

Build Stages

StagePurpose
baseNode 24 Alpine + pnpm via corepack
prunerturbo prune — extracts only the files needed for the target apps
depsInstalls all dependencies (--frozen-lockfile)
builderCopies source code and runs pnpm build
prod-depsInstalls production dependencies only (--prod)
runnerFinal image — copies prod deps, built artifacts, and entrypoint

The final image:

  • Runs as a non-root app user (UID 1001)
  • Uses dumb-init as PID 1 for proper signal handling
  • Exposes port 8080
  • Includes a healthcheck hitting /healthcheck

Runtime App Selection

The APP environment variable controls which app starts:

# Start the unified frontend
docker run -e APP=frontend syntropy

# Start the ingestion service
docker run -e APP=ingestion-service syntropy

This is handled by scripts/entrypoint.sh, which maps APP to the correct Node.js entry point.

CI/CD Pipeline

GitHub Actions (.github/workflows/main.yaml) runs on every push.

Validate Job

Runs on all branches:

  1. Installpnpm install --frozen-lockfile
  2. Check depspnpm check:deps (manypkg consistency)
  3. Lintpnpm lint --affected
  4. Typecheckpnpm typecheck --affected
  5. Testpnpm test --affected

The --affected flag ensures only changed packages are validated, keeping CI fast.

Deploy Job

Runs after validation passes. Uses omni/omni-action@v1:

  1. Builds the Docker image
  2. Pushes to Artifactory container registry
  3. Syncs ArgoCD applications (only on main branch)
with:
  k8s_clusters: omni-pre-1,omni-pro-1
  argocd_project: omni
  dockerfile: Dockerfile
  sync_argocd_apps: ${{ github.ref == 'refs/heads/main' }}

Kubernetes

Helm Chart

The chart (kubernetes/overlays/omni/Chart.yaml) uses the omni-app Helm chart from Schibsted's Artifactory as a dependency, aliased once per app:

  • frontend — unified React SPA served by Hono
  • ingestion-service — background ingestion worker

Environments

EnvironmentClusterArgoCD Sync
Developmentomni-dev-1Manual
Stagingomni-pre-1On merge to main
Productionomni-pro-1On merge to main

Each environment has two values files:

  • values-<cluster>.yaml — deployment config (replicas, resources, image)
  • values-<cluster>-config.yaml — application config (environment variables)

ArgoCD

ArgoCD watches the Helm chart and values files. On main, the CI pipeline triggers an ArgoCD sync to deploy to staging and production clusters. Non-main branches require manual sync for the dev environment.