From 46f0b7724d96e175d95d47269c7f78194d27ef1a Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 22 May 2026 19:26:51 +0200 Subject: [PATCH] fix(release): atomic JSON writes, CHANGELOG marker guard, --message validation --- scripts/release.sh | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 8a49606..a931ed4 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -11,7 +11,14 @@ shift || true while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN=1 ;; - --message) MESSAGE="$2"; shift ;; + --message) + if [[ $# -lt 2 || -z "${2:-}" ]]; then + echo "ERROR: --message требует непустой аргумент" + exit 1 + fi + MESSAGE="$2" + shift + ;; *) echo "Unknown arg: $1"; exit 1 ;; esac shift @@ -63,17 +70,22 @@ import json, sys version = sys.argv[1] plugin_json, mcp_json, marketplace_json = sys.argv[2], sys.argv[3], sys.argv[4] +# Phase 1: load all files (fail fast if anything is broken) with open(plugin_json) as f: p = json.load(f) -p["version"] = version -with open(plugin_json, "w") as f: json.dump(p, f, indent=2, ensure_ascii=False); f.write("\n") - with open(mcp_json) as f: m = json.load(f) -m["mcpServers"]["222a-seo-audit"]["headers"]["X-Plugin-Version"] = version -with open(mcp_json, "w") as f: json.dump(m, f, indent=2, ensure_ascii=False); f.write("\n") - with open(marketplace_json) as f: mk = json.load(f) + +# Phase 2: mutate in memory +p["version"] = version +m["mcpServers"]["222a-seo-audit"]["headers"]["X-Plugin-Version"] = version mk["plugins"][0]["version"] = version -with open(marketplace_json, "w") as f: json.dump(mk, f, indent=2, ensure_ascii=False); f.write("\n") + +# Phase 3: write all files (still not fully atomic across files, but all loads succeeded +# so each individual write is a clean replace of a parsed structure) +for path, data in [(plugin_json, p), (mcp_json, m), (marketplace_json, mk)]: + with open(path, "w") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + f.write("\n") print(f"Updated version to {version} in 3 files") PY @@ -82,6 +94,13 @@ PY CHANGELOG="plugins/222a-seo-audit/CHANGELOG.md" TODAY="$(date +%Y-%m-%d)" +# Проверка, что в CHANGELOG есть якорь [Unreleased] +if ! grep -q '^## \[Unreleased\]' "$CHANGELOG"; then + echo "ERROR: в $CHANGELOG нет секции '## [Unreleased]' — релиз остановлен" + echo "Восстановите якорь и запустите снова." + exit 1 +fi + if [[ -n "$MESSAGE" ]]; then # Вставить новую секцию после "## [Unreleased]" TMP="$(mktemp)"