Deployments
Deployments are how your code goes from a container image to running workloads on Kubernetes. Lucity handles the entire pipeline: build, push to GitOps, ArgoCD sync, and gives you real-time visibility into every step.
Deploy a service
The unified deploy mutation chains the full pipeline in one operation: build the image, update the GitOps repo, and sync via ArgoCD.
mutation {
deploy(input: {
projectId: "myapp"
service: "api"
environment: "development"
gitRef: "main"
}) {
id
phase
}
}
One command, full pipeline. If you've already built an image and just want to deploy it, use deployBuild instead:
mutation {
deployBuild(input: {
projectId: "myapp"
service: "api"
environment: "production"
tag: "a1b2c3d"
})
}
Provide the image tag (typically a git commit SHA) and an optional digest for exact image matching. This skips the build entirely and goes straight to the GitOps update and sync. Handy for redeploying a known-good image.
Track deploy progress
Deploy runs move through phases just like builds, but with an extra step at the end:
| Phase | What's happening |
|---|---|
QUEUED | Waiting to start. |
CLONING | Fetching source code. |
BUILDING | Railpack is building the image. |
PUSHING | Image is being pushed to the registry. |
DEPLOYING | ArgoCD is syncing the new image to Kubernetes. The moment of truth. |
SUCCEEDED | Running. Everything is healthy. |
FAILED | Something went wrong. Check the error. |
When using deployBuild, the pipeline skips straight to DEPLOYING since the image already exists.
Watch real-time logs
Subscribe to deploy logs as they stream:
subscription {
deployLogs(id: "deploy-xyz789")
}
Each message is a log line as a plain string.
Build output, push progress, deployment status: it all streams in real time. No refreshing, no polling, no "I'll check back in five minutes." You see what's happening as it happens.
Monitor rollout health
After the deployment reaches Kubernetes, Lucity reports the rollout health status. If your pods can't pull the image, crash on startup, or fail health checks, you'll know immediately:
query {
deployStatus(id: "deploy-xyz789") {
phase
rolloutHealth
rolloutMessage
}
}
Common issues like ImagePullBackOff and CrashLoopBackOff surface directly in the deploy run. No switching to a terminal and running kubectl describe pod, though you still can if that's your thing.
Browse deployment history
Each service instance tracks its deployment history, so you can see exactly what shipped and when:
query {
project(id: "myapp") {
services {
name
instances {
environment
imageTag
deployments {
imageTag
active
timestamp
revision
message
sourceCommitMessage
sourceUrl
}
}
}
}
}
Every deployment records the image tag, timestamp, git revision, commit message, source commit message from GitHub, and whether it's the currently active deployment. Useful for answering "what changed?" when something breaks at 2 AM. (Not that anything breaks at 2 AM. But just in case.)
Understand how it works under the hood
When you deploy, five things happen in sequence:
- Builder clones your source code and builds a container image using railpack.
- Builder pushes the image to the OCI registry, tagged with the git commit SHA.
- Packager updates the image tag in the GitOps repository's
environments/<target>/values.yamland commits. - Deployer creates or syncs the ArgoCD Application for the target environment.
- ArgoCD detects the new commit and applies the changes to Kubernetes.
Each step is handled by the service that owns that domain. The gateway orchestrates the flow, but each service operates independently. If the builder crashes mid-push, the deploy fails cleanly. No half-applied state, no orphaned resources.