From 347a71154b614051bdeaa410eee6ce5b560de075 Mon Sep 17 00:00:00 2001 From: Ovidiu U Date: Fri, 12 Jun 2026 10:41:47 +0100 Subject: [PATCH] Fix deploy.sh skipping SPA build on same-ref/aborted deploys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .gitignore | 1 + deploy.sh | 45 +++++++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 77fdc4e..d7e02fc 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ yarn-error.log /.zed /.tmp/ /.worktrees/ +/.deploy-last-commit /ONSPD_Online_Latest_Centroids_*.csv diff --git a/deploy.sh b/deploy.sh index c7a6005..b5b15c9 100755 --- a/deploy.sh +++ b/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