From 6c93e6cb70102f1f5c4b34414270b540fc2d9f99 Mon Sep 17 00:00:00 2001 From: RootX22 Date: Sun, 23 Aug 2026 19:36:39 +0300 Subject: [PATCH] Fix set -e abort after successful deploy, and shellcheck findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prune step used (( pruned++ )), which evaluates to 0 on the first increment. Under set -e that is a non-zero status and aborted the script *after* the release had gone live and the ERR trap had been disarmed — so a completely successful deploy exited 1. CI caught it in the pruning integration test. The trailing [[ $pruned -gt 0 ]] && log had the same problem when nothing needed pruning. Also addressed the shellcheck findings that gated CI: - SC2155: split the readonly STAMP declaration from its assignment so a failing date(1) is not masked by the declaration's exit status. - SC2015: the rollback reload used A && B || true, which swallowed a genuinely failing reload command. Replaced with an explicit if that reports the failure instead of hiding it. - SC2012: replaced ls with find for the release listing. find -printf is GNU-only, so the basename is stripped with sed to match the portability already required by atomic_symlink. --- scripts/deploy.sh | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 86583f6..4b8fe83 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -34,7 +34,8 @@ SHARED_PATHS=${SHARED_PATHS:-".env storage"} readonly RELEASES="$APP_ROOT/releases" readonly SHARED="$APP_ROOT/shared" readonly CURRENT="$APP_ROOT/current" -readonly STAMP=$(date -u '+%Y%m%dT%H%M%SZ') +STAMP=$(date -u '+%Y%m%dT%H%M%SZ') +readonly STAMP readonly NEW_RELEASE="$RELEASES/$STAMP" log() { printf '\033[1;34m▸\033[0m %s\n' "$*"; } @@ -96,7 +97,9 @@ rollback() { printf '\033[1;31m✗ deploy failed — rolling back\033[0m\n' >&2 if [[ -n $PREVIOUS && -d $PREVIOUS ]]; then atomic_symlink "$PREVIOUS" "$CURRENT" - [[ -n $RELOAD_CMD ]] && eval "$RELOAD_CMD" || true + if [[ -n $RELOAD_CMD ]]; then + eval "$RELOAD_CMD" || printf ' reload command failed during rollback\n' >&2 + fi printf '\033[1;33m↩ restored %s\033[0m\n' "$(basename "$PREVIOUS")" >&2 printf ' the failed release is left at %s for inspection\n' "$NEW_RELEASE" >&2 else @@ -204,13 +207,21 @@ ROLLBACK_ARMED=0 # The currently-linked release is excluded explicitly rather than relying on # it being newest — a rollback makes an older release the live one. log "Pruning to the last $KEEP_RELEASES releases" +# find -printf '%f' is GNU-only, so the basename is stripped with sed instead. +# Release directory names are our own UTC timestamps, so they contain no +# newlines or spaces and sort lexicographically in chronological order. live=$(basename "$(readlink -f "$CURRENT")") pruned=0 while IFS= read -r old; do + [[ -n $old ]] || continue [[ $old == "$live" ]] && continue rm -rf "${RELEASES:?}/$old" - (( pruned++ )) -done < <(ls -1 "$RELEASES" 2>/dev/null | sort -r | tail -n +$(( KEEP_RELEASES + 1 ))) -[[ $pruned -gt 0 ]] && log " removed $pruned old release(s)" + pruned=$(( pruned + 1 )) +done < <(find "$RELEASES" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \ + | sed 's|.*/||' | sort -r | tail -n +$(( KEEP_RELEASES + 1 ))) + +if [[ $pruned -gt 0 ]]; then + log " removed $pruned old release(s)" +fi ok "Deployed $STAMP"