diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 16e01fe..5835277 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -159,14 +159,23 @@ if [ '${COMPOSE_UP[$TARGET]}' = '1' ]; then # A Caddyfile render is a bind-mount content change, not a container # config change: the caddy container often survives 'up -d' and keeps # serving its in-memory config. Reload explicitly; the file watcher - # (admin on) is the backstop if the API is not up yet. + # (admin on) is the backstop if the API is not up yet. If the reload + # cannot be applied at all (e.g. the running config has the admin API + # disabled -- the fix cannot ride the API it is meant to enable), + # restart the container so it reads the file on start. + caddy_reloaded=0 for i in 1 2 3 4 5; do if podman exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then + caddy_reloaded=1 echo \" Caddy reloaded.\" break fi sleep 3 done + if [ \"\$caddy_reloaded\" -ne 1 ]; then + echo \" Caddy reload failed; restarting the container to load the file.\" + podman restart caddy + fi else echo '[4/4] Skipping compose restart (stack runs as bare containers on this host)' fi diff --git a/tests/deployment_flow.bats b/tests/deployment_flow.bats index 99614a5..96742d5 100644 --- a/tests/deployment_flow.bats +++ b/tests/deployment_flow.bats @@ -45,6 +45,14 @@ load helpers grep -q 'caddy reload' "$REPO_ROOT/scripts/deploy.sh" } +@test "deploy.sh restarts caddy when the reload cannot be applied" { + # If the running config has the admin API disabled (or the API is down), + # 'caddy reload' can never apply the new file -- the fix cannot be + # delivered over the API it is meant to enable. The fallback is a + # container restart, which always reads the file. + grep -q 'podman restart caddy' "$REPO_ROOT/scripts/deploy.sh" +} + @test "deploy.sh Caddyfile render survives a slash-bearing bcrypt hash" { local hash='$2a$14$dndiQ9EaycJv0w3Gp2oAYO/xH6O9x2ZRhMLJdCxrgi9rMn1te9D/spy' local rendered