From 7b1ce47de748c5201d594e9ead0cb2ade8d66324 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 24 Aug 2026 07:35:22 -0700 Subject: [PATCH 1/2] Address review findings from the develop-to-main promotion PR .secrets/README.md now scopes the 'every real value comes from ~/.secrets/' claim to local invocations, since CI supplies the same values directly from the GitHub Environment. OPERATIONS.md, README.md, and deploy/README.md now name ENV_FILE explicitly alongside sourcing it, since make-release.sh sources it independently and a value already exported earlier in the same shell session would otherwise win silently. OPERATIONS.md's Deploying section now reuses one release id across both the release and the live check, so EXPECT_RELEASE actually verifies the release that command just built rather than skipping the release-stamp guard entirely. ops/install.sh's HOME-to-~ abbreviation now requires a directory boundary after the prefix, so a sibling directory sharing the same prefix (/home/alice2 under HOME=/home/alice) is no longer misread as a subdirectory of HOME. --- .secrets/README.md | 2 +- OPERATIONS.md | 9 +++++---- README.md | 2 +- deploy/README.md | 2 +- ops/install.sh | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.secrets/README.md b/.secrets/README.md index 642bbd5..4cb150b 100644 --- a/.secrets/README.md +++ b/.secrets/README.md @@ -7,7 +7,7 @@ exposing one. ## Real values live on the host, never in the checkout -Every real value this repo's scripts read comes from `~/.secrets/`, not from this directory. +Every real value a local invocation of this repo's scripts reads comes from `~/.secrets/`, not from this directory. CI supplies the same values directly from the GitHub Environment instead, reading no file here at all. `ENV_FILE= deploy/make-release.sh` and `ops/install.sh` both resolve a relative `ENV_FILE` against `$HOME/.secrets`, refuse a traversing one, and default to `~/.secrets/Blog.local.production.env`. `~/.secrets/` is shared across every repo on the host, diff --git a/OPERATIONS.md b/OPERATIONS.md index 9379f3a..0a839aa 100644 --- a/OPERATIONS.md +++ b/OPERATIONS.md @@ -77,11 +77,11 @@ So release to the local mirror and run the live check **before** opening a pull ```sh set -a; . ~/.secrets/Blog.local.production.env; set +a -deploy/make-release.sh +ENV_FILE=~/.secrets/Blog.local.production.env deploy/make-release.sh checks/check-live-urls.sh "$SITE_BASE_URL" ``` -Against the staging mirror, name its file in both places, since the sourced values and the ones `make-release.sh` reads must describe the same environment: +Name the file in both places, even when it is the default, since `make-release.sh` sources `ENV_FILE` independently of the shell above and a value already exported earlier in the same session would otherwise win silently over the sourced one: ```sh set -a; . ~/.secrets/Blog.local.staging.env; set +a @@ -142,8 +142,9 @@ Three properties of how the credential is handled, each there for a reason worth ## Deploying ```sh -SITE_BASE_URL= deploy/make-release.sh "$(git rev-parse --short HEAD)" -checks/check-live-urls.sh +RELEASE="$(git rev-parse --short HEAD)" +SITE_BASE_URL= deploy/make-release.sh "$RELEASE" +EXPECT_RELEASE="$RELEASE" checks/check-live-urls.sh ``` The deploy root and the base URL are the only host-specific values. A local run reads them from a file under `~/.secrets/`, one per environment, copied from [`.secrets/example.env`](./.secrets/example.env), and CI passes both explicitly. The real files live on the host, never in this checkout. diff --git a/README.md b/README.md index 3a03b33..6996220 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ Build a release and verify it against a running server: ```sh set -a; . ~/.secrets/Blog.local.production.env; set +a -deploy/make-release.sh +ENV_FILE=~/.secrets/Blog.local.production.env deploy/make-release.sh checks/check-live-urls.sh "$SITE_BASE_URL" ``` diff --git a/deploy/README.md b/deploy/README.md index 610439e..6c36bad 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -54,7 +54,7 @@ neither. Seven facts are the whole contract: ```sh set -a; . ~/.secrets/Blog.local.production.env; set +a -deploy/make-release.sh +ENV_FILE=~/.secrets/Blog.local.production.env deploy/make-release.sh checks/check-live-urls.sh "$SITE_BASE_URL" ``` diff --git a/ops/install.sh b/ops/install.sh index 22baf0e..d45a79b 100755 --- a/ops/install.sh +++ b/ops/install.sh @@ -91,7 +91,7 @@ MOUNT=$(findmnt -no TARGET --target "$ANCESTOR" 2>/dev/null) || VPS_TRAEFIK_ARCHIVE=${VPS_TRAEFIK_LOG_ARCHIVE:-/var/log/traefik/archive} -printf '=== derived from %s\n' "${ENV_FILE/#"$HOME"/\~}" +printf '=== derived from %s\n' "${ENV_FILE/#"$HOME"\//\~/}" note "VPS_SSH_HOST $VPS_SSH_HOST" note "BACKUP_ARCHIVE_ROOT $BACKUP_ARCHIVE_ROOT" note "LOG_ARCHIVE_ROOT $LOG_ARCHIVE_ROOT" @@ -105,7 +105,7 @@ DROPIN_DEST=$DROPIN_DIR/local.conf ENV_BODY=$( cat < Date: Mon, 24 Aug 2026 08:20:34 -0700 Subject: [PATCH 2/2] Fix a scope claim and a bash-version-sensitive display escape .secrets/README.md now notes that an absolute ENV_FILE is honored as given, an escape hatch outside the documented ~/.secrets/ convention, rather than claiming every local invocation is confined to it. ops/install.sh no longer relies on the \~ parameter-expansion escape for its HOME-to-~ display, since bash versions differ on whether that yields a literal backslash. A case statement builds the same display value without it. --- .secrets/README.md | 9 ++++++--- ops/install.sh | 13 +++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.secrets/README.md b/.secrets/README.md index 4cb150b..e97323e 100644 --- a/.secrets/README.md +++ b/.secrets/README.md @@ -7,11 +7,14 @@ exposing one. ## Real values live on the host, never in the checkout -Every real value a local invocation of this repo's scripts reads comes from `~/.secrets/`, not from this directory. CI supplies the same values directly from the GitHub Environment instead, reading no file here at all. +The documented local convention is `~/.secrets/`, not this directory. CI supplies the same +values directly from the GitHub Environment instead, reading no file here at all. `ENV_FILE= deploy/make-release.sh` and `ops/install.sh` both resolve a relative `ENV_FILE` against `$HOME/.secrets`, refuse a traversing one, and default to -`~/.secrets/Blog.local.production.env`. `~/.secrets/` is shared across every repo on the host, -so each of this repo's files carries the `Blog.` prefix: +`~/.secrets/Blog.local.production.env`. An absolute `ENV_FILE` is honored as given rather than +resolved against `~/.secrets/`, an escape hatch rather than the documented shape. +`~/.secrets/` is shared across every repo on the host, so each of this repo's files carries the +`Blog.` prefix: | File | Selects | | --- | --- | diff --git a/ops/install.sh b/ops/install.sh index d45a79b..f5fb64a 100755 --- a/ops/install.sh +++ b/ops/install.sh @@ -91,7 +91,16 @@ MOUNT=$(findmnt -no TARGET --target "$ANCESTOR" 2>/dev/null) || VPS_TRAEFIK_ARCHIVE=${VPS_TRAEFIK_LOG_ARCHIVE:-/var/log/traefik/archive} -printf '=== derived from %s\n' "${ENV_FILE/#"$HOME"\//\~/}" +# A display value only, built without the \~ parameter-expansion escape, since bash versions differ on whether that yields a literal backslash, and this is what an operator reads to trust the source file. +ENV_FILE_DISPLAY=$ENV_FILE +case "$ENV_FILE_DISPLAY" in +"$HOME"/*) + # shellcheck disable=SC2088 # Literal display text, deliberately not expanded. + ENV_FILE_DISPLAY="~/${ENV_FILE_DISPLAY#"$HOME"/}" + ;; +esac + +printf '=== derived from %s\n' "$ENV_FILE_DISPLAY" note "VPS_SSH_HOST $VPS_SSH_HOST" note "BACKUP_ARCHIVE_ROOT $BACKUP_ARCHIVE_ROOT" note "LOG_ARCHIVE_ROOT $LOG_ARCHIVE_ROOT" @@ -105,7 +114,7 @@ DROPIN_DEST=$DROPIN_DIR/local.conf ENV_BODY=$( cat <