First to Site
Release 3.5

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

  1. Fetch latest refs into the bare repo
  2. Create a git worktree at the target ref (branch, tag, or commit)
  3. Copy runtime files (.env.local, credentials, tokens) from the current live release
  4. Run full production bootstrap inside the worktree
  5. Restore persistent symlinks (media/uploads from EFS)
  6. Move finished build to ~/releases/source-<timestamp>
  7. Re-publish Symfony assets in the final location
  8. Atomic symlink swap (~/source -> new release)
  9. 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.sh

Files Touched

FileChange
scripts/release-prod-safe.tsCore isolated build script
scripts/bootstrap-prod.tsPer-app production bootstrap
scripts/post-release.shService restart script
package.jsonrelease:prod:safe, release:preprod commands

Changelog Reference

  • feat: add isolated build release script (release:prod:safe) (05c6554)
  • refactor: store releases in ~/releases/ instead of ~/ (1d36d48)
  • fix: run post-release as ubuntu, not ftsuser (98a74bd)