Fix deploy.sh skipping SPA build on same-ref/aborted deploys
The build was gated on `git diff BEFORE AFTER`, where BEFORE was HEAD before checkout. Re-deploying the same ref (or re-running after an aborted deploy) made BEFORE == AFTER, so the diff was empty and the SPA build silently skipped — shipping stale assets while migrations still ran. - Always rebuild the SPA; only gate the heavy dep installs. - npm ci / composer install also run when node_modules / vendor are missing. - Track the last successfully deployed commit in .deploy-last-commit and diff against that, so an aborted run never advances the baseline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,4 +24,5 @@ yarn-error.log
|
||||
/.zed
|
||||
/.tmp/
|
||||
/.worktrees/
|
||||
/.deploy-last-commit
|
||||
/ONSPD_Online_Latest_Centroids_*.csv
|
||||
|
||||
45
deploy.sh
45
deploy.sh
@@ -6,10 +6,11 @@
|
||||
# ./deploy.sh v0.1.3 # deploy a specific tag
|
||||
#
|
||||
# It puts the site in maintenance mode, updates the code, runs migrations and
|
||||
# cache rebuilds, restarts the queue, then brings the site back up. composer
|
||||
# install and npm build only run when their inputs actually changed, so most
|
||||
# deploys skip them. If any step fails the script aborts and the site stays in
|
||||
# maintenance mode on purpose — fix the issue, then re-run.
|
||||
# cache rebuilds, restarts the queue, then brings the site back up. The SPA is
|
||||
# always rebuilt; the heavier dependency installs (composer install, npm ci)
|
||||
# only run when their lockfiles changed or the installed dir is missing. If any
|
||||
# step fails the script aborts and the site stays in maintenance mode on
|
||||
# purpose — fix the issue, then re-run.
|
||||
#
|
||||
# See docs/ops/deployment.md for first-time setup and troubleshooting.
|
||||
set -euo pipefail
|
||||
@@ -19,8 +20,13 @@ cd "$(dirname "$0")"
|
||||
REF="${1:-main}"
|
||||
echo "==> Deploying ref: ${REF}"
|
||||
|
||||
# Remember the current commit so we can see what changed after checkout.
|
||||
BEFORE="$(git rev-parse HEAD)"
|
||||
# Baseline for change detection: the last *fully* deployed commit, recorded at
|
||||
# the end of a successful run (falls back to current HEAD the first time). Using
|
||||
# a persisted marker instead of the pre-checkout HEAD keeps the diff honest even
|
||||
# when the same ref is re-deployed or a previous run aborted partway — both of
|
||||
# which otherwise make BEFORE == AFTER and silently skip build/install steps.
|
||||
MARKER=".deploy-last-commit"
|
||||
BEFORE="$(cat "${MARKER}" 2>/dev/null || git rev-parse HEAD)"
|
||||
|
||||
echo "==> Maintenance mode on"
|
||||
php artisan down --retry=15
|
||||
@@ -36,23 +42,29 @@ fi
|
||||
AFTER="$(git rev-parse HEAD)"
|
||||
CHANGED="$(git diff --name-only "${BEFORE}" "${AFTER}" || true)"
|
||||
|
||||
# Reinstall PHP deps only if the lockfile moved.
|
||||
if grep -q '^composer\.lock$' <<<"${CHANGED}"; then
|
||||
echo "==> composer.lock changed — installing PHP deps"
|
||||
# Reinstall PHP deps only when the lockfile moved or vendor is missing.
|
||||
if grep -q '^composer\.lock$' <<<"${CHANGED}" || [ ! -d vendor ]; then
|
||||
echo "==> Installing PHP deps (composer.lock changed or vendor missing)"
|
||||
composer install --no-dev --optimize-autoloader
|
||||
else
|
||||
echo "==> composer.lock unchanged — skipping composer install"
|
||||
fi
|
||||
|
||||
# Rebuild the Vue SPA only if frontend sources or the JS lockfile moved.
|
||||
if grep -qE '^(package(-lock)?\.json|vite\.config\.|resources/(js|css)/)' <<<"${CHANGED}"; then
|
||||
echo "==> Frontend changed — rebuilding SPA"
|
||||
# Install JS deps only when the lockfile moved or node_modules is missing.
|
||||
if grep -qE '^package(-lock)?\.json$' <<<"${CHANGED}" || [ ! -d node_modules ]; then
|
||||
echo "==> Installing JS deps (lockfile changed or node_modules missing)"
|
||||
npm ci
|
||||
npm run build
|
||||
else
|
||||
echo "==> No frontend changes — skipping npm build"
|
||||
echo "==> JS deps unchanged — skipping npm ci"
|
||||
fi
|
||||
|
||||
# Always rebuild the SPA. The build is cheap (a few seconds), and gating it on a
|
||||
# git diff silently shipped stale assets whenever BEFORE == AFTER — re-deploying
|
||||
# the same ref, or re-running after an aborted deploy. Correctness over the few
|
||||
# seconds saved.
|
||||
echo "==> Building SPA"
|
||||
npm run build
|
||||
|
||||
echo "==> Running migrations"
|
||||
php artisan migrate --force
|
||||
|
||||
@@ -68,5 +80,10 @@ php artisan queue:restart
|
||||
echo "==> Maintenance mode off"
|
||||
php artisan up
|
||||
|
||||
# Record the just-deployed commit as the baseline for the next run. Only reached
|
||||
# on full success — `set -e` aborts earlier on any failure, so a broken deploy
|
||||
# never advances the baseline and the next run re-evaluates from the last good one.
|
||||
git rev-parse HEAD > "${MARKER}"
|
||||
|
||||
echo "==> Deploy complete"
|
||||
php artisan about
|
||||
|
||||
Reference in New Issue
Block a user