Builds
Builds turn source code into container images that deployments can run. ZopNight builds from a connected git integration (GitHub today). The actual docker build runs on a GitHub Actions dispatcher (zop-dev/zopnight-builder) — no in-cluster Kaniko, no shared build farm, no build queue contention between tenants.
Where these routes live
Builds = revisions
/builds resource. Each deployment revision carries its build state — image ref, status, error message, log tail — and the lifecycle endpoints under /deployments/{id}/revisions are how builds are tracked.Pick a Repository & Branch
Repos and branches are read live through the connected GitHub App token (or PAT for self-hosted) — ZopNight does not cache the user's repo list across sessions.
/repositoriesList repositories visible through your connected integrations. Used by the deploy wizard's repo picker. (deployer)
{
"data": [
{
"integrationID": "int_github_001",
"owner": "acme",
"repo": "checkout",
"defaultBranch": "main",
"private": true
}
]
}/branchesList branches in a selected repository. Pass integrationID + owner + repo as query params. (deployer)
Analyze a Repository
Before kicking off a build, the wizard runs an analyzer that inspects the repo and proposes deployment defaults — language, framework, port, health probe path, and (when present) a Dockerfile. Stack detection is powered by Railpack since #1203, so most repos can be deployed without ever opening a config file.
/analyzeAnalyze a repo + branch and return suggested deployment defaults. Used by the deploy wizard before the deployment is created. (deployer)
curl -X POST https://zopnight.com/api/analyze \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"integrationID": "int_github_001",
"owner": "acme",
"repo": "checkout",
"branch": "main",
"rootPath": "."
}'{
"data": {
"language": "go",
"framework": "gofr",
"suggestedPort": 8080,
"suggestedHealthPath": "/health",
"dockerfile": "Dockerfile",
"buildContext": ".",
"needsBuild": true,
"warnings": []
}
}Note: /analyze is the wizard-time analyzer (pre-create). For re-analyzing an existing deployment, see POST /deployments/{id}/analyze on the Deployments page.
How a Build Runs
- You create a deployment (or push to a branch with auto-deploy on). Config writes the catalog row + revision #1 placeholder and enqueues a job on the deployer's MySQL
jobsqueue. - A deployer worker claims the job, clones the repo, and dispatches a
workflow_dispatchtozop-dev/zopnight-builderwith a callback URL and an HMAC-signed JWT. - The builder workflow runs Railpack (if there's no Dockerfile) or a plain
docker build, then pushes the image to your registry. - The workflow POSTs the result back to
/build-callbacks/{revisionID}. The deployer verifies the JWT, stamps the image ref onto the revision, and re-enqueues the deploy job. - The deployer mints a per-deploy ephemeral kubeconfig from the cloud account creds and applies a Helm release to the target cluster's namespace.
Build Callback
The builder workflow reports back over an unauthenticated gateway path that the deployer secures with a body-carried HMAC-signed JWT — the secret is BUILD_CALLBACK_SECRET in the deployer's environment. If the secret isn't set, the callback route isn't registered at all (so the workflow_dispatch path is effectively disabled in environments where you haven't configured builds).
/build-callbacks/{revisionID}Builder workflow → deployer callback. Auth is the JWT in the JSON body (signed with BUILD_CALLBACK_SECRET), not the gateway session. (deployer)
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<payload>.<sig>",
"status": "succeeded",
"imageRef": "registry.zopnight.com/acme/checkout:sha-abc1234",
"logTailUrl": "https://github.com/zop-dev/zopnight-builder/actions/runs/12345"
}See Deployments for revision endpoints, and Webhooks for how the GitHub push event kicks the build pipeline off in the first place.