A single multi-stage Dockerfile builds all apps into one image.
| Stage | Purpose |
|---|---|
base | Node 24 Alpine + pnpm via corepack |
pruner | turbo prune — extracts only the files needed for the target apps |
deps | Installs all dependencies (--frozen-lockfile) |
builder | Copies source code and runs pnpm build |
prod-deps | Installs production dependencies only (--prod) |
runner | Final image — copies prod deps, built artifacts, and entrypoint |
The final image:
app user (UID 1001)/healthcheckThe 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.
GitHub Actions (.github/workflows/main.yaml) runs on every push.
Runs on all branches:
pnpm install --frozen-lockfilepnpm check:deps (manypkg consistency)pnpm lint --affectedpnpm typecheck --affectedpnpm test --affectedThe --affected flag ensures only changed packages are validated, keeping CI fast.
Runs after validation passes. Uses omni/omni-action@v1:
main branch)with:
k8s_clusters: omni-pre-1,omni-pro-1
argocd_project: omni
dockerfile: Dockerfile
sync_argocd_apps: ${{ github.ref == 'refs/heads/main' }}
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 Honoingestion-service — background ingestion worker| Environment | Cluster | ArgoCD Sync |
|---|---|---|
| Development | omni-dev-1 | Manual |
| Staging | omni-pre-1 | On merge to main |
| Production | omni-pro-1 | On 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 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.