From 9107923c5a24c612566d1bb2edf8a5251836996b Mon Sep 17 00:00:00 2001 From: Oleks Date: Tue, 2 Jun 2026 05:08:05 +0300 Subject: [PATCH] fix(devtag-guard): snapshot explicit VERSION at source time (#194 finding) The guard read $VERSION, but app bodies set VERSION to the derived default before calling it, so accidental local --publish without an explicit version or v* tag still pushed. Capture PARITY_VERSION_EXPLICIT at source time and gate on that instead. --- CHANGELOG.md | 7 +++++++ ci/parity-lib.sh | 13 ++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74da8e5..ed23cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ semantic versioning; the version is a conceptual tag (no git tag is created). ## Unreleased +- **Fix (safety): dev-tag guard was ineffective.** Every publish app body runs + `VERSION="$(parity_derive_version )"` before `parity_devtag_guard`, so + by the time the guard checked `$VERSION` it was always non-empty (the derived + default) and an accidental local `--publish` with no explicit version and no + `v*` tag still pushed (cluster #194 finding). The guard now reads a source-time + snapshot `PARITY_VERSION_EXPLICIT` captured before any clobber, so it correctly + blocks unless the caller set `$VERSION` or `$CI_COMMIT_TAG` matches `^v[0-9]`. - `pipeline-doctor` (cluster #191 security sweep): added a scoped per-file check asserting **no `set -x` in token-bearing `ci/*.sh` scripts** going forward — a script that references a registry token (`REGISTRY_TOKEN` / `CI_REGISTRY_TOKEN` diff --git a/ci/parity-lib.sh b/ci/parity-lib.sh index fe1e052..4b4fe37 100644 --- a/ci/parity-lib.sh +++ b/ci/parity-lib.sh @@ -22,6 +22,15 @@ PARITY_REGISTRY_OWNER="${PARITY_REGISTRY_OWNER:-oleks}" # Local on-disk stage. BUILD-parity artifacts land here; push-staged replays them. PARITY_STAGE_DIR="${PARITY_STAGE_DIR:-${PWD}/.parity-stage}" +# Snapshot whether the caller set $VERSION EXPLICITLY, captured at source time — +# BEFORE any app body overwrites VERSION with the derived default version +# (VERSION="$(parity_derive_version )"). parity_devtag_guard reads this +# snapshot, not the live $VERSION, so an accidental local `--publish` with no +# explicit version and no v* tag is still blocked instead of silently shipping +# the flake's default version. Set-once: re-sourcing won't clobber the capture. +: "${PARITY_VERSION_EXPLICIT=${VERSION:-}}" +export PARITY_VERSION_EXPLICIT + # --------------------------------------------------------------------------- # Token resolution: $REGISTRY_TOKEN -> `pass` fallback -> named hard fail. # Prints the token on stdout so a caller can `tok="$(parity_resolve_token)"`. @@ -75,7 +84,9 @@ parity_derive_version() { # the flake's default development version. # --------------------------------------------------------------------------- parity_devtag_guard() { - if [ -n "${VERSION:-}" ]; then + # Read the source-time snapshot, NOT the live $VERSION (which the app body + # has already set to the derived default by the time this runs). + if [ -n "${PARITY_VERSION_EXPLICIT:-}" ]; then return 0 fi if printf '%s' "${CI_COMMIT_TAG:-}" | grep -Eq '^v[0-9]'; then