Isolated Build Release Script
release:prod:safe - zero-downtime deployments via bare repo, git worktrees, and atomic symlink swap
Overview
Introduced release:prod:safe, replacing in-place builds with an isolated build system. The live site is never touched during the build process - only an atomic symlink swap cuts over to the new release.
What Changed
Build Isolation
The release script uses a persistent bare git repo (~/builds/repo.git) and disposable git worktrees for each build. The full production bootstrap (Composer, Bun, Webpack Encore, Symfony assets) runs inside the worktree, completely isolated from the live site.
Release Flow
- Fetch latest refs into the bare repo
- Create a git worktree at the target ref (branch, tag, or commit)
- Copy runtime files (.env.local, credentials, tokens) from the current live release
- Run full production bootstrap inside the worktree
- Restore persistent symlinks (media/uploads from EFS)
- Move finished build to
~/releases/source-<timestamp> - Re-publish Symfony assets in the final location
- Atomic symlink swap (
~/source-> new release) - Print post-release command for service restarts
Post-Release (runs as ubuntu)
The post-release script is a separate step run as ubuntu (who has sudo), not as ftsuser. It restarts PHP-FPM, messenger workers, releases (supervisor), dossier-api (systemd), and reloads nginx. Environment detection via LIVE_LINK_NAME routes to the correct services.
Rollback
The previous release directory is preserved. Rollback is a single symlink swap back to the prior release, followed by the post-release restart.
Usage
# As ftsuser:
bun run release:prod:safe -- master # deploy master
bun run release:prod:safe -- v3.5.0 # deploy a tag
# Then as ubuntu:
sudo LIVE_LINK_NAME=source bash ~/source/scripts/post-release.shFiles Touched
| File | Change |
|---|---|
scripts/release-prod-safe.ts | Core isolated build script |
scripts/bootstrap-prod.ts | Per-app production bootstrap |
scripts/post-release.sh | Service restart script |
package.json | release:prod:safe, release:preprod commands |