Building & Deploying ​
With your infrastructure provisioned by yolo sync, shipping code is one command:
yolo deploy productiondeploy builds the image and ships it. You rarely need build on its own — deploy runs it for you.
What deploy does ​
yolo deploy runs the build, then the rollout, end to end:
- Build — runs the full
buildpipeline below (image built and pushed to ECR). - Push assets — uploads compiled assets to the S3 asset bucket (served via CloudFront when configured).
- Register task definition — registers a new ECS task definition revision pointing at the freshly pushed image.
- Run deploy hooks — runs your manifest's
deploycommands (e.g.php artisan migrate --force) as a one-off ECS task before traffic shifts. - Update the service — points the ECS service at the new revision and starts the rolling deployment.
- Wait for healthy — polls until the new tasks pass their health checks.
- Point DNS — UPSERTs the Route 53 record(s) once the deployment is healthy.
- Recap — prints a summary of what's now running (each service's task spec, count, scaling, and new revision) plus a link to the app's CloudWatch dashboard — the same view
yolo statusshows.
To watch a rollout as it happens, or check what's running at any time, run yolo status <env> — a live dashboard of services, load, scaling, and any in-progress deploy.
The build ​
yolo build production prepares and packages the image:
- Purge the build directory and stage a clean copy of your app.
- Pull
.env.<environment>from S3 and stamp inAPP_VERSION(andASSET_URL, mirrored intoVITE_ASSET_URLfor Vite, if a CDN is configured). - Run your manifest's
buildhooks (composer install,npm run build, …). With Inertia SSR enabled, this is also wherenpm run buildproduces the SSR bundle that gets baked into the image. - Generate the entrypoint and supervisord config (see The Container Image). Two preflight checks gate this step. First, YOLO hard-fails the build if
laravel/octaneisn't in your committedcomposer.lockproduction requirements — the web role runsoctane:start, so a missing (orrequire-dev-only) octane would crash-loop the container on boot. Second, whentasks.web.ssris on, it warns if your Dockerfile has no Node runtime for the SSR process. - Log in to ECR, build the Docker image, and push it.
The image-building steps (4–5) only run when your manifest declares tasks — a headless app with no web task still builds its source artefact.
Zero-downtime rollout ​
The rollout uses the ECS deployment circuit breaker. New tasks must pass their ALB health checks before the old ones are drained and stopped; if the new version fails to stabilise, ECS automatically rolls back to the previous task definition. Combined with the graceful-shutdown drain window, a healthy deploy serves traffic with no dropped requests — and a broken one never takes the service down.
App version ​
Every build is stamped with an APP_VERSION. By default it's a timestamp in the form y.W.N.Hi (two-digit year, ISO week, ISO weekday, hour-minute) — for example 26.22.5.1430. Override it to stamp a meaningful tag, such as a GitHub release name:
yolo deploy production --app-version=26.22.1The version must start with the current year.week prefix (e.g. 26.22) — this keeps versions monotonic and prevents accidental stale tags. Both 26.22 and the non-zero-padded 26.<week> forms are accepted.
TIP
The week prefix is computed in your manifest's timezone (defaulting to UTC). Set timezone to your team's timezone so a version cut just before midnight on a Sunday doesn't trip the validation. See timezone.
Hooks: build vs deploy vs deploy-all ​
Three manifest arrays run shell commands at different points:
| Hook | Runs | Where | Use for |
|---|---|---|---|
build | At build time, on your machine | the build context | composer install, npm run build, asset compilation |
deploy | Once per deploy, before traffic shifts | a one-off ECS task | php artisan migrate --force |
deploy-all | On every container start | the entrypoint | php artisan optimize (cache config/routes/views) |
The deploy task templates on your management-tier service — a dedicated scheduler if you've extracted one, else a standalone queue, else web (the same scheduler → queue → web order yolo run uses). It's a one-off task, so it just runs the hooks once and exits.
build:
- composer install --no-dev --optimize-autoloader
- npm ci
- npm run build
deploy:
- php artisan migrate --force
deploy-all:
- php artisan optimizeHiding progress output ​
All stepped commands accept --no-progress to suppress the live progress UI — useful in CI logs:
yolo deploy production --no-progressRunning commands in the container ​
To open a shell or run a one-off command inside a running task (via ECS Exec):
yolo run production # interactive shell
yolo run production --command="php artisan tinker" # one-off command
yolo run production --command="php artisan queue:restart" --group=web,queueThis needs tasks.web.enable-execute-command: true in your manifest and the AWS Session Manager plugin installed locally (yolo init offers to install it). See yolo run.
