fix: make the Hub backup scripts runnable on the Linux host
Found by running deploy/hub/backup.sh on the production VM:
- With core.autocrlf=true, `git archive` on the Windows release machine
shipped the .sh files with CRLF and `sh` aborted on line 4
("set: Illegal option -"): backup, restore and seed never ran.
.gitattributes now forces *.sh to LF.
- Docker creates the bind-mounted backups/ directory as root, so the
host-side retention `rm` would fail once the 15th dump existed.
Retention now runs inside the postgres container.
tests/test_deploy_scripts.py covers both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# Shell scripts run on the Linux Hub host. With core.autocrlf=true on the
|
||||||
|
# Windows release machine, `git archive`/checkout would otherwise ship them
|
||||||
|
# with CRLF and `sh` rejects them ("set: Illegal option -").
|
||||||
|
*.sh text eol=lf
|
||||||
@@ -9,5 +9,7 @@ STAMP="$(date +%Y%m%d_%H%M%S)"
|
|||||||
FILE="gti_fiscal_${STAMP}.dump"
|
FILE="gti_fiscal_${STAMP}.dump"
|
||||||
$COMPOSE exec -T postgres pg_dump -U gti -d gti_fiscal -Fc -f "/backups/${FILE}"
|
$COMPOSE exec -T postgres pg_dump -U gti -d gti_fiscal -Fc -f "/backups/${FILE}"
|
||||||
[ -s "$DIR/$FILE" ] || { echo "backup empty or missing: $DIR/$FILE" >&2; exit 1; }
|
[ -s "$DIR/$FILE" ] || { echo "backup empty or missing: $DIR/$FILE" >&2; exit 1; }
|
||||||
ls -1t "$DIR"/gti_fiscal_*.dump | tail -n +15 | xargs -r rm -f
|
# Retention runs inside the container: Docker creates the bind-mounted
|
||||||
|
# backup directory as root, so a host-side rm would fail from the 15th dump.
|
||||||
|
$COMPOSE exec -T postgres sh -c 'ls -1t /backups/gti_fiscal_*.dump | tail -n +15 | xargs -r rm -f'
|
||||||
echo "backup ok: $DIR/$FILE"
|
echo "backup ok: $DIR/$FILE"
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
"""The Hub backup/restore scripts must actually run on the Linux host.
|
||||||
|
|
||||||
|
Both failures below were found by running the scripts on the production VM,
|
||||||
|
not by reading them.
|
||||||
|
"""
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).parents[1]
|
||||||
|
HUB = ROOT / "deploy" / "hub"
|
||||||
|
|
||||||
|
|
||||||
|
def test_shell_scripts_are_forced_to_lf():
|
||||||
|
# With core.autocrlf=true on the Windows release machine, `git archive`
|
||||||
|
# shipped CRLF and `sh` failed on the first line ("set: Illegal option -").
|
||||||
|
rules = [line.split() for line in (ROOT / ".gitattributes").read_text(encoding="utf-8").splitlines() if line.strip() and not line.startswith("#")]
|
||||||
|
assert ["*.sh", "text", "eol=lf"] in rules
|
||||||
|
for script in HUB.glob("*.sh"):
|
||||||
|
assert b"\r" not in script.read_bytes(), script.name
|
||||||
|
|
||||||
|
|
||||||
|
def test_backup_retention_does_not_delete_on_the_host():
|
||||||
|
# Docker creates the bind-mounted backup directory as root, so a host-side
|
||||||
|
# rm by the deploy user fails once retention kicks in.
|
||||||
|
lines = [line.strip() for line in (HUB / "backup.sh").read_text(encoding="utf-8").splitlines() if not line.strip().startswith("#")]
|
||||||
|
retention = [line for line in lines if "rm -f" in line]
|
||||||
|
assert retention and all(line.startswith("$COMPOSE exec -T postgres") for line in retention)
|
||||||
Reference in New Issue
Block a user