Stop the export aborting silently when a scrub finds nothing left to scrub
All checks were successful
CI / naming (push) Successful in 3s
CI / frontend (push) Successful in 12s
CI / migrations-mysql (push) Successful in 40s
CI / backend (push) Successful in 3m58s

The export died with no output and no dists, exit 1, having committed nothing.
grep exits 1 when it matches NOTHING, and under set -euo pipefail that failing
pipeline takes the script with it. Once every internal reference had already
been scrubbed, the gitea grep matched nothing, and the SUCCESS case became the
abort. It printed not one line explaining itself, which is what made it cost an
afternoon: the run looked like it had worked.

All three scrub greps are guarded now. This is the third failure of this shape
in this file, after the two fetch/push tag omissions.

Also excludes a stray .env copy from the sync. A hand-made .env.bak-<date>
reached the publication tree, because rsync walks the WORKING TREE and
.gitignore does not apply. The scrub gate caught it, which is what that gate is
for, and it never reached a commit or a bundle - but a file of live credentials
should not get that far. --include '.env.example' comes first so the example
still publishes.

Both verified by planting a violation: a no-match grep under pipefail, and a
planted .env.bak file that the sync now leaves behind.
This commit is contained in:
cproudlock
2026-08-28 16:24:00 -04:00
parent 2aea2bd818
commit 5da071fdda

View File

@@ -71,6 +71,17 @@ for stale in .pytest_cache .ruff_cache htmlcov .coverage instance/plugins.json \
rm -rf "${PUB:?}/$stale" rm -rf "${PUB:?}/$stale"
done done
# .env is excluded by name, but a stray copy BESIDE it is not: a hand-made
# .env.bak-<date> was picked up by this sync, because it walks the WORKING TREE
# and .gitignore does not apply to it. It got no further than the scrub gate,
# which is what that gate is for, but a file holding live credentials should
# never reach the publication tree at all. Hence --exclude '.env.*', with
# --include '.env.example' BEFORE it: rsync takes the first matching rule, and
# .env.example does publish.
#
# Keep flags on their own lines. A comment inside this backslash-continued
# command is not a comment - bash hands the text to rsync as arguments, and it
# dies with a usage dump rather than anything that names the real problem.
rsync -a --delete \ rsync -a --delete \
--exclude '.git' \ --exclude '.git' \
--exclude '.gitea' \ --exclude '.gitea' \
@@ -96,6 +107,8 @@ rsync -a --delete \
--exclude 'frontend/src/.plugins-staged' \ --exclude 'frontend/src/.plugins-staged' \
--exclude 'frontend/src/router/routes.gen.js' \ --exclude 'frontend/src/router/routes.gen.js' \
--exclude '/instance' \ --exclude '/instance' \
--include '.env.example' \
--exclude '.env.*' \
--exclude '.env' \ --exclude '.env' \
--exclude '__pycache__' \ --exclude '__pycache__' \
--exclude '.pytest_cache' \ --exclude '.pytest_cache' \
@@ -130,8 +143,15 @@ cd "$PUB"
# --- 2. re-apply the publication wording (idempotent) --- # --- 2. re-apply the publication wording (idempotent) ---
# docs/ lives only in the wiki on the GitHub side. # docs/ lives only in the wiki on the GitHub side.
grep -rlZ 'docs/' --include='*.py' --include='*.md' --include='*.sh' \ # NOTE the `|| true` on each scrub grep below. grep exits 1 when it matches
--include='*.tmpl' --include='*.vue' --include='*.example' . 2>/dev/null | # NOTHING, and under `set -euo pipefail` that failing pipeline aborts the whole
# script - silently, because grep prints nothing to say so. That is exactly what
# happened once every internal reference had been scrubbed: the gitea grep found
# no matches, the export died before committing or rebuilding the dists, and it
# exited without a single line of output. A scrub that finds nothing left to
# scrub is the SUCCESS case, so it must not be an error.
{ grep -rlZ 'docs/' --include='*.py' --include='*.md' --include='*.sh' \
--include='*.tmpl' --include='*.vue' --include='*.example' . 2>/dev/null || true; } |
while IFS= read -r -d '' f; do while IFS= read -r -d '' f; do
case "$f" in ./CHANGELOG.md) continue ;; esac case "$f" in ./CHANGELOG.md) continue ;; esac
sed -i -E \ sed -i -E \
@@ -145,11 +165,11 @@ sed -i 's|<code>docs/GE-ENFORCE.md</code>|the GE-ENFORCE page in the project wik
# internal infra never named on GitHub; this repo's own URL maps to the # internal infra never named on GitHub; this repo's own URL maps to the
# real GitHub home, anything else degrades to a placeholder. # real GitHub home, anything else degrades to a placeholder.
GITHUB_URL='https://github.com/ge-aero/shopdb-flask' GITHUB_URL='https://github.com/ge-aero/shopdb-flask'
grep -rlZ 'gitea\.proudtech\.net' . 2>/dev/null | while IFS= read -r -d '' f; do { grep -rlZ 'gitea\.proudtech\.net' . 2>/dev/null || true; } | while IFS= read -r -d '' f; do
sed -i -e "s|https://gitea\.proudtech\.net/ge-aerospace/shopdb-flask|$GITHUB_URL|g" \ sed -i -e "s|https://gitea\.proudtech\.net/ge-aerospace/shopdb-flask|$GITHUB_URL|g" \
-e 's|gitea\.proudtech\.net|<git-host>|g' "$f" -e 's|gitea\.proudtech\.net|<git-host>|g' "$f"
done done
grep -rlZi 'gitea' --exclude-dir=.git . 2>/dev/null | while IFS= read -r -d '' f; do { grep -rlZi 'gitea' --exclude-dir=.git . 2>/dev/null || true; } | while IFS= read -r -d '' f; do
sed -i -e 's/the GE Aerospace Gitea/the internal GE Aerospace git server/g' \ sed -i -e 's/the GE Aerospace Gitea/the internal GE Aerospace git server/g' \
-e 's/Gitea Actions CI/CI/g' \ -e 's/Gitea Actions CI/CI/g' \
-e 's/Gitea Actions/CI/g' "$f" -e 's/Gitea Actions/CI/g' "$f"