fix: manifest SHA256 from git blobs (CRLF/LF) — release 2.2.2-SAC

Manifest was hashed from Windows working tree while Linux checkout uses
git blobs; verify failed with sha256 mismatch. build-release-manifest.sh
now hashes :index/HEAD; .gitattributes enforces LF for agent scripts.
This commit is contained in:
PTah
2026-07-08 12:00:51 +10:00
parent 6df83f1838
commit 0399a6d384
7 changed files with 50 additions and 13 deletions
+27 -5
View File
@@ -1,5 +1,6 @@
#!/bin/bash
# Генерация release/manifest-VERSION.json (SHA256 файлов + git commit HEAD).
# Хеши считаются по содержимому git (HEAD), как после checkout на Linux-хосте.
# Запуск из корня репозитория: ./scripts/build-release-manifest.sh [VERSION]
set -euo pipefail
@@ -27,8 +28,8 @@ FILES=(
)
for f in "${FILES[@]}"; do
[ -f "$f" ] || {
echo "ERROR: нет файла $f" >&2
git rev-parse "HEAD:$f" >/dev/null 2>&1 || [ -f "$f" ] || {
echo "ERROR: нет файла $f (ни в git HEAD, ни на диске)" >&2
exit 1
}
done
@@ -51,6 +52,7 @@ python3 <<'PY'
import hashlib
import json
import os
import subprocess
root = os.environ["MANIFEST_ROOT"]
version = os.environ["MANIFEST_VERSION"]
@@ -58,21 +60,41 @@ git_commit = os.environ.get("MANIFEST_GIT_COMMIT", "")
files = os.environ["MANIFEST_FILES"].split()
out = os.environ["MANIFEST_OUT"]
def sha256_file(path: str) -> str:
def sha256_bytes(data: bytes) -> str:
h = hashlib.sha256()
h.update(data)
return h.hexdigest()
def file_bytes_from_git(name: str) -> bytes | None:
for ref in (f":{name}", f"HEAD:{name}"):
try:
return subprocess.check_output(["git", "-C", root, "show", ref])
except subprocess.CalledProcessError:
continue
return None
def sha256_release_file(name: str) -> str:
blob = file_bytes_from_git(name)
if blob is not None:
return sha256_bytes(blob)
path = os.path.join(root, name)
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(1024 * 1024), b""):
h.update(chunk)
return h.hexdigest()
manifest = {
"version": version,
"git_commit": git_commit,
"files": {},
}
for name in files:
path = os.path.join(root, name)
manifest["files"][name] = f"sha256:{sha256_file(path)}"
manifest["files"][name] = f"sha256:{sha256_release_file(name)}"
with open(out, "w", encoding="utf-8") as f:
json.dump(manifest, f, indent=2, ensure_ascii=False)