From 5da071fddafccab564cefdd81b0ef495bc8d7ca1 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 28 Aug 2026 16:24:00 -0400 Subject: [PATCH] Stop the export aborting silently when a scrub finds nothing left to scrub 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- 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. --- tools/export-github.sh | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tools/export-github.sh b/tools/export-github.sh index e7eb2506..5c0bfadc 100755 --- a/tools/export-github.sh +++ b/tools/export-github.sh @@ -71,6 +71,17 @@ for stale in .pytest_cache .ruff_cache htmlcov .coverage instance/plugins.json \ rm -rf "${PUB:?}/$stale" done +# .env is excluded by name, but a stray copy BESIDE it is not: a hand-made +# .env.bak- 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 \ --exclude '.git' \ --exclude '.gitea' \ @@ -96,6 +107,8 @@ rsync -a --delete \ --exclude 'frontend/src/.plugins-staged' \ --exclude 'frontend/src/router/routes.gen.js' \ --exclude '/instance' \ + --include '.env.example' \ + --exclude '.env.*' \ --exclude '.env' \ --exclude '__pycache__' \ --exclude '.pytest_cache' \ @@ -130,8 +143,15 @@ cd "$PUB" # --- 2. re-apply the publication wording (idempotent) --- # docs/ lives only in the wiki on the GitHub side. -grep -rlZ 'docs/' --include='*.py' --include='*.md' --include='*.sh' \ - --include='*.tmpl' --include='*.vue' --include='*.example' . 2>/dev/null | +# NOTE the `|| true` on each scrub grep below. grep exits 1 when it matches +# 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 case "$f" in ./CHANGELOG.md) continue ;; esac sed -i -E \ @@ -145,11 +165,11 @@ sed -i 's|docs/GE-ENFORCE.md|the GE-ENFORCE page in the project wik # internal infra never named on GitHub; this repo's own URL maps to the # real GitHub home, anything else degrades to a placeholder. 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" \ -e 's|gitea\.proudtech\.net||g' "$f" 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' \ -e 's/Gitea Actions CI/CI/g' \ -e 's/Gitea Actions/CI/g' "$f"