Skip to content
Last updated: Sep 25, 2026

Build ​

All images are built with Docker (multi-arch) via GitHub Actions and pushed to GHCR (GitHub Container Registry) under the finaisse-org org.

Builds are normally triggered by a version tag, not by a merge. Pushing <service>-vX.Y.Z builds that service and is the first step of a release — see Deploy for the full path. Manual dispatch remains available for forcing a rebuild.

GitHub ​

Backend (blitz) ​

Each microservice in src/apps/ is independently containerised.

Trigger a build via GitHub Actions:

WorkflowTriggerOutput
build-push-<service>.yml<service>-vX.Y.Z tag push, or manualSingle service image
build-push-all.ymlManual onlyAll service images
_build-push-service.ymlworkflow_call (reusable)The shared build used by all 12

build-push-all.yml has no schedule. The nightly build was removed (a12f2060) once releases became tag-driven — an unattended :latest rebuild no longer matches how anything is deployed. Do not rely on an overnight build existing.

Image tags:

  • ghcr.io/finaisse-org/blitz-<service>:latest — most recent build from main
  • ghcr.io/finaisse-org/blitz-<service>:<short-sha> — specific commit (all branches)
  • ghcr.io/finaisse-org/blitz-<service>:<branch-slug> — non-main branches

Services with CI build workflows (12, all of them): api, ws, apimgmt, agents, emailprocessor, wfw, wfwpdf, recon, remotecontrol, excelrw, bapiproxy, classicml.

All 12 route through the one reusable _build-push-service.yml, including the two .NET services (excelrw, bapiproxy) and the Python one (classicml) — it bakes each service's compose target rather than assuming Bun, so "has a build workflow" does not imply "is a Bun service".

The version gate ​

Every tag-triggered build verifies version monotonicity before pushing: a tag whose version is not strictly higher than every existing tag for that service fails the build, so no bad-version image reaches GHCR. This runs as a step inside the build job (it used to be a separate workflow — one job per service, each billed a full minute for ~19s of work).

It only applies to <service>-vX.Y.Z tag pushes; branch builds and manual dispatches skip it. It never blocks a rollback, because redeploying an already-tagged version via the manifest creates no tag.

Frontend (blitz-ui) ​

The frontend is a Module Federation multi-app monorepo. Each sub-app is built independently; the ui host shell loads the others at runtime via URLs baked in at build time.

Sub-apps: ui (host), closehub, invoice, journal, recon, collections

Important: VITE_*_REMOTE_URL environment variables must be set correctly before the build runs — they are compiled into the JavaScript bundle and cannot be changed at runtime. All 6 apps are built and deployed in a coordinated pipeline.

Trigger a build: a ui-vX.Y.Z tag push, or GitHub Actions → build-push-ui.yml in the blitz-ui repo.

The UI build is the slowest in the fleet — ~9–10 minutes

Each app needs roughly 6 GB of heap, so the apps are built natively and sequentially (not in Docker, not in parallel) to avoid OOM on a standard runner. Low observed RSS does not mean low demand. This sets the pace of every full release: backend services finish in ~2–3 minutes and then wait on this one.

Admin / mgmt UI (blitz-mgmtui) ​

The mgmt portal UI (apps/mgmt) is a standalone Vue app (not a federation remote), built and pushed as its own image ghcr.io/finaisse-org/blitz-mgmtui.

CI: a mgmtui-vX.Y.Z tag push, or GitHub Actions → build-push-mgmtui.yml, which builds natively first then packages via the OOM-safe build/Dockerfile.mgmt.prebuilt. Both UI workflows carry the same version gate as the backend builds.

A manual dispatch of build-push-mgmtui.yml also accepts an image_type input (private default / public), producing a separate ghcr.io/finaisse-org/blitz-mgmtui-public image for the public-variant build — not used by the standard release path.

Local ​

Backend, single service:

bash
cd blitz/src
just docker-build-api      # multi-arch build
just docker-push-api       # push to GHCR

Frontend, tenant UI:

bash
cd blitz-ui/src
just docker-build-ui       # tenant UI
just docker-build-mgmtui   # admin / mgmt UI

Admin / mgmt UI one-shot build: just docker-build-mgmtui (uses the in-container build/Dockerfile.mgmt, mirroring the tenant UI) then just docker-push-mgmtui. Both are in the blitz-ui justfile. Set VITE_SYNCFUSION_LICENSEKEY in your environment first — the recipe passes it as a build arg.

Build Artifacts ​

All images are stored in GHCR:

  • Backend: ghcr.io/finaisse-org/blitz-<service>
  • Frontend: ghcr.io/finaisse-org/blitz-ui (tenant), ghcr.io/finaisse-org/blitz-mgmtui (admin)

Images are pulled by Railway (staging) at deploy time — at the digest the release manifest pins, not at :latest. See Deploy.

Tag scheme per release: ghcr.io/finaisse-org/blitz-<service>:<service>-vX.Y.Z. The :latest and :<short-sha> tags are still pushed on main builds but nothing deploys from them any more.

Finaisse Internal — Confidential. Access-restricted; not for external distribution.