Skip to main content
Version: 1.0

Build Service

Repo: o-apps/build-service · Port: 8098

Build Service turns a tenant's own Git repository into a running app, without the platform ever needing to see anything beyond a public or private clone URL. It's the piece that makes the Deploy Application Wizard's "GitHub Repository" source option real: give it a repository, branch, and Dockerfile path, and it produces a container image that hands off directly into the same deployment path a registry-image deploy already uses — this service never gets its own separate way of running an app, it only ever produces an image and lets KubeOpera API take it from there.

How a build runs​

Each build is one Kaniko Job, created in a dedicated kubeopera-builds namespace on the host cluster rather than inside any tenant's vCluster — this keeps build privileges and capacity centrally managed, rather than granting every tenant vCluster the ability to run privileged build pods. The Job clones the requested repository (using a mounted, ephemeral Secret for a private-repo token, or a persistent one stored against a registered Build Config for repeat builds of the same repo), runs Kaniko against the given Dockerfile path and build context, and pushes the resulting image to a per-tenant path in KubeOpera's own self-hosted registry — registry.dev.kubeopera.io:5000/tenant-<tenant_id>/<app_id>:<timestamp>. Kaniko was chosen over Buildpacks (too much implicit magic for a Dockerfile-centric wizard) and over Tekton (a heavier dependency than warranted for "clone, build, push").

Every build's registry credentials are provisioned per tenant, not shared — see Auth Service for how the registry's own token issuer scopes a push/pull credential to exactly one tenant's path, so one tenant's build can never read or overwrite another's images.

Build Configs — auto-rebuild on push​

A Build Config is a standing registration of "this repository and branch belong to this app" — register one once, and every future push triggers a fresh build automatically, without needing to go back through the wizard. POST /webhook/github and POST /webhook/gitlab are the receiving end of this: on a push event, the service looks up a matching registered config by repository and branch and starts a build from it. A push to a repository with no registered config is treated as a normal, silent no-op rather than an error — GitHub and GitLab both surface webhook delivery failures to the repository owner, and an unregistered repository is an expected, common case, not a misconfiguration worth alarming anyone about.

A Build Config can also be triggered manually, on demand, without waiting for a push — useful for the very first build after registering a config, or for re-running a build against the same source without a new commit.

Reporting into a Pipeline​

When a build is associated with a Pipeline (set once, automatically, the first time a tenant deploys from a given repository — see KubeOpera API's Pipelines section), the service reports its own progress into that Pipeline's run history in the background, independently of whatever triggered the build. This matters because a tenant might close the deploy wizard, or their whole browser, before a build finishes — since the reporting happens server-side rather than depending on the frontend staying open to poll for completion, the Pipeline's run still reaches a correct final status (clone and build-and-push stages, each with real start/finish timestamps read directly from the Kaniko Pod's own container statuses) regardless of whether anyone is still watching.

REST API​

MethodPathDescription
POST/api/v1/buildsStart a build
GET/api/v1/buildsList builds
GET/api/v1/builds/{id}Build status
GET/api/v1/builds/{id}/logsKaniko Job logs
POST/api/v1/build-configsRegister an auto-rebuild-on-push config
GET/api/v1/build-configsList configs
DELETE/api/v1/build-configs/{id}Remove a config
POST/api/v1/build-configs/{id}/triggerManually launch a build from a registered config
POST/webhook/github | /webhook/gitlabInbound push webhooks (public, unauthenticated by design — verified by GitHub/GitLab's own signature scheme where configured)
GET/healthHealth check

All /api/v1/* routes are internal, API-key-authenticated calls from KubeOpera API, which resolves the caller's tenant from their session and forwards it explicitly — this service itself never trusts a client-supplied tenant ID.

Environment Variables​

VariableDescription
DATABASE_URLPostgreSQL connection
MIGRATIONS_DIRPath to goose migration files
CICD_GATEWAY_BASE_URL / CICD_GATEWAY_API_KEYInternal call for the background Pipeline-progress reporting described above
GITHUB_WEBHOOK_SECRET / GITLAB_WEBHOOK_TOKENOptional — verifies inbound webhook signatures when set
HTTP_PORTHTTP port (default: 8098)