Platform Core

Core Deployment

This section covers deploying the core services required to run the platform — first and foremost the engine, together with the supporting services it needs.

The platform services run on Kubernetes. Container images are built by CI from the Dockerfile of each application module, and released with the Helm charts in deploy/ — see Helm Charts for the charts themselves.

Container Images

Each deployable module has its own Dockerfile next to its sources (engine/Dockerfile, bridge/Dockerfile, relay/Dockerfile). The image is assembled from the distribution archive produced by the Gradle build, on a Temurin 21 base; the engine image additionally installs ffmpeg and bundles the OpenTelemetry Java agent.

Images are pushed to the project’s GitLab container registry as $CI_REGISTRY_IMAGE/{engine|bridge|relay} and tagged:

Trigger Tag

Merge request on a PRP- or release/ branch

the short commit SHA

Git tag (release)

the tag name, and latest

Pipeline Stages

The GitLab pipeline (.gitlab-ci.yml) runs these stages:

Stage Contents

validate

KtLint formatting check on the changed Kotlin files, SAST and secret detection.

build

Gradle build (all modules, unit tests), container image builds, Helm chart packaging.

test

Integration tests — a manual job, since they require live infrastructure and provider credentials.

canary deploy

On a release tag: deploys the new version alongside the current one with a share of the traffic.

deploy

Deploys the services to the target environment (see below).

release

Creates the GitLab release with generated notes and links to the published images.

document

Generates and publishes the Dokka API reference for lib, common and engine.

Draft merge requests do not run pipelines.

Environments

Environment Trigger Domain Notes

Issue

Merge request from a PRP-* branch

platform-{issue}.promethist.dev

An ephemeral namespace per issue on the development cluster, one replica, spot instances, values-develop.yaml. Torn down by the manual stop_environment job.

Develop

Merge request from a release/* branch

promethist.dev

Shared development environment, one replica, values-develop.yaml.

Preview

Merge request from a release/* branch

eu.promethist.ai, us.promethist.ai

The release candidate, deployed with the preview suffix and namespace, per region.

Production

Git tag

eu.promethist.ai, us.promethist.ai

Deployed per region, with the tag as image tag. A canary release is deployed first and the canary release is removed once the full deployment succeeds.

Each region has its own Kubernetes cluster, its own Keycloak realm URL and, where applicable, a secondary domain served by the same ingress.

How a Deploy Runs

All service deployments follow the same shape — a helm upgrade --install against the chart in deploy/{service}/helm, with the environment’s specifics passed as --set values:

helm -n $NAMESPACE upgrade --force --install promethist-$RELEASE_NAME deploy/engine/helm \
  --set app.name=engine \
  --set app.namespace=$NAMESPACE \
  --set app.suffix=$SUFFIX \
  --set app.domain=$DOMAIN \
  --set app.image=$CI_REGISTRY_IMAGE/engine \
  --set app.tag=$IMAGE_TAG \
  --set oauth.authority.url=$OAUTH_AUTHORITY_URL

The same command is what to reach for when deploying manually — for example to reproduce an environment or to roll back to a previous image tag by changing app.tag.

Per-issue namespaces are prepared by deploy/prepare-namespace.sh, which creates the namespace and the secrets the charts expect.

Configuration and Secrets

A deployed engine reads its configuration from two files mounted into the container:

  • /config/application.properties — rendered by the chart from its values (domain, namespace, version, storage, database name).

  • /config/application-default.properties — the environment’s own settings and credentials, supplied from a Kubernetes secret.

In Azure-hosted clusters that secret is projected from Azure Key Vault through the Secrets Store CSI driver (deploy/secret-provider.yaml), which also provides the Google service account key, the Firebase admin key and the registry pull secret. Elsewhere the same content is provided as a plain Kubernetes secret:

kubectl -n $NAMESPACE create secret generic promethist-engine \
  --from-file=engine/config/application-default.properties

Identity Provider

Deployments authenticate against Keycloak. Beyond the realm and client setup, the SCIM provisioning integration used to synchronize enterprise users into a realm is documented in deploy/KEYCLOAK_SCIM.md.

In this section