From 8e9499780e6d1da7a052f631a3fb977908ce5208 Mon Sep 17 00:00:00 2001 From: boban Date: Mon, 22 Jun 2026 21:18:44 +0200 Subject: [PATCH] =?UTF-8?q?fix(release):=20review=20polish=20=E2=80=94=20p?= =?UTF-8?q?romote=20idempotency,=20CI=20hardening,=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - promote.sh: fail fast before mutating the public tree if the tag was already promoted (avoids a half-commit left on the runner on re-dispatch). - ci-staging.yml: pass STAGING_PROJECT_DIR via env + :? guard instead of a ${{ }} expression in run: (clears the template-injection lint, fails loudly on misconfig). - README: PUBLIC_REPO_URL was never read by any workflow — keep only the slug. - set-repository-url.test.sh: chmod +x for mode parity with promote.test.sh. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci-staging.yml | 4 +++- README.md | 3 ++- scripts/promote.sh | 7 +++++++ scripts/set-repository-url.test.sh | 0 4 files changed, 12 insertions(+), 2 deletions(-) mode change 100644 => 100755 scripts/set-repository-url.test.sh diff --git a/.github/workflows/ci-staging.yml b/.github/workflows/ci-staging.yml index 928470a..37e4ce3 100644 --- a/.github/workflows/ci-staging.yml +++ b/.github/workflows/ci-staging.yml @@ -37,6 +37,8 @@ jobs: environment: staging steps: - name: Update the staging stack + env: + STAGING_PROJECT_DIR: ${{ vars.STAGING_PROJECT_DIR }} run: | - cd "${{ vars.STAGING_PROJECT_DIR }}" + cd "${STAGING_PROJECT_DIR:?STAGING_PROJECT_DIR not set}" sudo ./update.sh diff --git a/README.md b/README.md index 97d0cf0..e305bd4 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,8 @@ staging at GitHub-private, and public users at GitHub-public — automatically. - Gitea push-mirror → the GitHub-private URL + a GitHub PAT. - GitHub-private repo settings: - - Variable `PUBLIC_REPO_SLUG` = `owner/repo` of the public repo; `PUBLIC_REPO_URL` if needed. + - Variable `PUBLIC_REPO_SLUG` = `owner/repo` of the public repo (the only variable the promotion + workflows read). - Secret `PUBLIC_REPO_TOKEN` = a token with push to the public repo. - (Optional staging) Variable `STAGING_ENABLED=true`, `STAGING_PROJECT_DIR`, and a self-hosted runner labelled `clusev-staging` on the internal network (GitHub-hosted runners cannot reach an diff --git a/scripts/promote.sh b/scripts/promote.sh index b145780..8c3800c 100755 --- a/scripts/promote.sh +++ b/scripts/promote.sh @@ -12,6 +12,13 @@ msg="${4:?commit message required}" git -C "$src" rev-parse "$tag" >/dev/null 2>&1 || { echo "unknown tag: $tag" >&2; exit 1; } +# Fail fast BEFORE mutating the public tree if this release was already promoted — re-promoting a +# published release must be deliberate, not a silent half-commit left on the runner. +if git -C "$pub" rev-parse -q --verify "refs/tags/$tag" >/dev/null 2>&1; then + echo "tag already promoted in public repo: $tag" >&2 + exit 1 +fi + # Clear the public working tree but KEEP its .git. find "$pub" -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} + diff --git a/scripts/set-repository-url.test.sh b/scripts/set-repository-url.test.sh old mode 100644 new mode 100755