Deploys
A deploy takes a repository from GitHub to a live URL in one run. Three agents do the work: Scout reads the repository, Builder builds and smoke-tests it in a sandbox, and Deployer plans, waits for your approval, deploys, and checks that it works.
Before you start
- A GitHub connection with the repository linked.
- A deploy target: a Kubernetes cluster connected with the deployer account, or an AWS account with deploys turned on. An AWS connection that only observes is refused, with a hint to turn deploys on.
- The owner or approver role. Viewers can follow deploys but not start or approve them.
The app needs to be something that runs in a container and answers HTTP on a port. If the repository has a Dockerfile, Groundcrew builds it as it is first. If not, Builder writes one.
Start a deploy
Pick the source
Open Deploy. Choose the GitHub connection and the repository, then a branch, tag, or commit.
Pick the target
A Kubernetes cluster, or an AWS account with deploys on.
Add env vars
Add the variables the app needs. Mark the sensitive ones as secret. You can also leave them out and add them at the approval card if Scout finds that the app needs them.
Deploy
The deploy page follows the run live: each stage, Builder's attempts, and the plan when it is ready. You can leave the page; the deploy keeps going and waits for an approval.
What happens, stage by stage
| Stage | Who | What happens |
|---|---|---|
| Scout | Scout | Reads the repository: language, framework, port, health path, and the env vars the code reads. |
| Build | Builder | Builds the image in the sandbox. On a failure it reads the error, changes the Dockerfile, and tries again, up to 5 attempts. |
| Smoke | Builder | Starts the image in the sandbox and checks it answers HTTP. |
| Plan | Deployer | Turns what Scout found into the exact resources for your target. |
| Preflight | Deployer | Read-only checks: the image passed, required env vars are set, names are free, the target is ready. |
| Approval | You | The plan waits for an owner or approver. |
| Apply | Deployer | Pushes the image, then creates or updates each resource in the plan, in order. |
| Verify | Deployer | Waits for the rollout, then checks the health path over HTTP. |
Nothing leaves the sandbox before you approve. Until then the image is only built and smoke-tested; pushing it to a registry is the first step of Apply.
Reviewing the plan
The approval card shows what will happen in your account: every resource Deployer will create or change, the image it will push (by its exact digest), the env vars with secret values replaced by ********, and the result of each preflight check.
- Approve and deploy runs this plan once. The approval is bound to the plan itself: if anything in it changed, the approval would not apply.
- Reject ends the deploy without touching anything.
- A failed preflight check disables Approve. Fix the cause and deploy again, or use the options below for a missing env var.
Env vars and secrets
A deploy takes up to 100 env vars. A secret value goes to a Kubernetes Secret or to AWS Secrets Manager, and is never shown again: the deploy page lists names, whether each is secret, and whether a value was given. Plain values do appear in the plan, because the plan is what you approve.
When preflight fails only because a required variable is missing, the approval card offers Set value (a masked input) or Continue without it. Either one re-runs only preflight with the image already built. Nothing is built again, and the old plan is shown as replaced.
Secret values are encrypted while the deploy is running and removed when it ends. They are never written to run steps, approvals, or logs.
What gets created
On AWS ECS, everything is named groundcrew-* and tagged project=groundcrew, inside the groundcrew-deploys cluster that the AWS template created:
- An ECR repository for the image.
- A log group under
/groundcrew/, and a security group for the app's port. - Secrets under
groundcrew/<app>/, written but never read back. - A task definition revision (0.25 vCPU, 0.5 GB) and a Fargate service with a public address.
The live URL is the task's public address and port. Every task definition revision is kept, so a rollback always has somewhere to go back to.
On Kubernetes, each app gets its own namespace gc-<app> labelled project=groundcrew, with a Secret for its secret env vars, a Deployment (250m CPU, 512Mi memory, a readiness probe), a Service, and an Ingress at <app>.<your app domain>. The image goes to the registry set in the cluster's Deploy settings.
In both cases the deploy appears on the map, with a deployed by line to Groundcrew, and the incident watcher starts watching it.
Verify and rollback
Verify waits for the rollout to finish, stopping early on errors such as an image that cannot be pulled or a container that keeps crashing. It then checks the health path, or / when the app has none.
If verify fails, Deployer collects the app's logs and offers a rollback to the previous revision (or, for a first deploy, removing it) as an emergency approval: Approve rollback. Rejecting it leaves the failed deployment in place for you to look at. A rollback never runs on its own.
Isolated builds
Builds and smoke tests of your code run in a sandbox on Groundcrew's servers: a rootless container engine, with each container in gVisor, so a build step never runs directly on the host. The sandbox has no route to cloud metadata services, private networks, or Groundcrew's own services, and it runs one build at a time with fixed memory and CPU. Everything a build created is deleted when the run ends.
When a deploy fails
- The build kept failing. The deploy page shows each attempt with the failing step and the error lines. Builder stops early when the same error comes back after the same kind of fix ("no progress"). Fix the cause in the repository and deploy again.
- A build took too long. One build attempt may take at most 15 minutes.
- The daily build limit. A workspace can run 10 deploy builds a day, reset at 00:00 UTC.
- Smoke test failed. The app did not answer HTTP in the sandbox. Check the port it listens on and that it starts without services it cannot reach from the sandbox.
- Verify failed on AWS. The stopped tasks' reasons are on the deploy page. Common causes are a wrong port, a missing env var, or a default VPC without public subnets.
You can stop a deploy at any point with Stop on its run. Pending approvals are rejected.
Cost and cleanup
Apps run in your account, on your bill. The smallest ECS deploy costs about $12 a month on AWS list prices while it runs, mostly Fargate and its public address. Deleting a Groundcrew workspace or connection does not stop apps it deployed: remove them in your account. On ECS, delete the service in groundcrew-deploys, then its groundcrew-* ECR repository, log group, security group, and secrets. On Kubernetes, deleting the gc-<app> namespace removes everything the deploy created.