From 0054fe426b37a0e55122fc26bea31ace4e033419 Mon Sep 17 00:00:00 2001 From: KellyMichels Date: Thu, 23 Jul 2026 13:13:32 -0500 Subject: [PATCH] fix(bash): zbackup/zbackup_and_sync require an explicit target, matching PowerShell Bare `zbackup` quietly backed up every project - inconsistent with the PowerShell version (and with zdeploy), and an easy way to kick off a huge unintended backup. Now a bare invocation prints usage and lists the projects; `all` does what bare used to (every project + the scripts folder). Same for `zbackup_and_sync`, and setup_backup_schedule's cron line now passes `all` so the scheduled job still backs everything up. --- bash/setup_backup_schedule | 2 +- bash/zbackup | 14 ++++++++++++-- bash/zbackup_and_sync | 12 ++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/bash/setup_backup_schedule b/bash/setup_backup_schedule index e15f0d7..48a0e72 100644 --- a/bash/setup_backup_schedule +++ b/bash/setup_backup_schedule @@ -30,7 +30,7 @@ if ! [[ "$hh" =~ ^[0-9]{1,2}$ && "$mm" =~ ^[0-9]{2}$ ]] || [ "$hh" -gt 23 ] || [ err "Invalid --time '$at_time' (expected HH:MM, 24h)"; exit 1 fi -cron_line="${mm#0} ${hh#0} * * * $_HERE/zbackup_and_sync >> \$HOME/zbackup_and_sync.log 2>&1" +cron_line="${mm#0} ${hh#0} * * * $_HERE/zbackup_and_sync all >> \$HOME/zbackup_and_sync.log 2>&1" info "=== Backup schedule (cron) ===" dim "Daily at $at_time:" diff --git a/bash/zbackup b/bash/zbackup index 8009d3b..31c5cc2 100644 --- a/bash/zbackup +++ b/bash/zbackup @@ -7,8 +7,8 @@ # project's .env has a DATABASE_URL) into the backups folder. # # Usage: -# zbackup # every project in zconfig.json + this scripts folder # zbackup [ ...] +# zbackup all # every project in zconfig.json + this scripts folder # zbackup scripts # just this scripts folder ('scripts' is a reserved word) # zbackup pyapp --tag "pre-migration" # @@ -30,8 +30,18 @@ while [ $# -gt 0 ]; do done BACKUP_ROOT="$(z_path "$(zq '.paths.backupsLocal')")" -include_scripts=0 + +# Require an explicit target: bare invocation shows usage instead of quietly +# backing up everything - 'all' is explicit, matching zdeploy. if [ "${#projects[@]}" -eq 0 ]; then + printf '\n'; warn "Usage: zbackup [ ...] | all | scripts [--tag \"label\"]" + dim " Projects in zconfig.json: $(zproj_csv)" + dim " 'all' backs up every project plus this scripts folder; 'scripts' just this folder." + exit 1 +fi + +include_scripts=0 +if printf '%s\n' "${projects[@]}" | grep -qx 'all'; then projects=(); while IFS= read -r _zl || [ -n "$_zl" ]; do projects+=("$_zl"); done < <(zproj_keys) include_scripts=1 else diff --git a/bash/zbackup_and_sync b/bash/zbackup_and_sync index 497c37b..06bbcec 100644 --- a/bash/zbackup_and_sync +++ b/bash/zbackup_and_sync @@ -6,11 +6,11 @@ # zbackup_and_sync — run backups, then sync the backups folder offsite. # # Usage: -# zbackup_and_sync # backup everything + sync # zbackup_and_sync [ ...] +# zbackup_and_sync all # backup everything + sync # # Cron example (see setup_backup_schedule): -# 0 2 * * * /path/to/zscripts/bash/zbackup_and_sync >> ~/zbackup.log 2>&1 +# 0 2 * * * /path/to/zscripts/bash/zbackup_and_sync all >> ~/zbackup.log 2>&1 set -uo pipefail _HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -18,6 +18,14 @@ source "$_HERE/zhelpers.sh" z_track_start "$@" z_need_config +# Require an explicit target (matching zbackup/zdeploy); 'all' backs up everything. +if [ $# -eq 0 ]; then + printf '\n'; warn "Usage: zbackup_and_sync [ ...] | all" + dim " Projects in zconfig.json: $(zproj_csv)" + dim " 'all' backs up every project plus the scripts folder, then syncs offsite." + exit 1 +fi + printf '\n' info "============================================" info " Backup & Sync - $(date '+%Y-%m-%d %H:%M:%S')"