diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 51b22e8..f4967cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -244,6 +244,10 @@ jobs: echo "Uploading checksums.txt..." gh release upload "${TAG}" release/checksums.txt + # Upload individual .sha256 files for backward compatibility + echo "Uploading .sha256 checksum files..." + gh release upload "${TAG}" release/*.sha256 + - name: Upload release assets env: GH_TOKEN: ${{ github.token }} diff --git a/scripts/build-release.sh b/scripts/build-release.sh index b0e0bfc..ae6d9c9 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -321,8 +321,15 @@ fi if [ ${#checksum_files[@]} -eq 0 ]; then echo "Warning: no release artifacts found to checksum." else - # Generate checksums.txt with sorted output for deterministic results (prevents #671 checksum mismatches) - sha256sum "${checksum_files[@]}" | sort -k 2 > checksums.txt + # Generate checksums from a single sha256sum run for deterministic results (prevents #671 checksum mismatches) + checksum_output="$(sha256sum "${checksum_files[@]}" | sort -k 2)" + printf '%s\n' "$checksum_output" > checksums.txt + + # Emit per-file .sha256 artifacts for backward compatibility while legacy installers transition off them + while IFS= read -r checksum filename; do + printf '%s %s\n' "$checksum" "$filename" > "${filename}.sha256" + done <<< "$checksum_output" + if [ -n "${SIGNING_KEY_ID:-}" ]; then if command -v gpg >/dev/null 2>&1; then echo "Signing checksums with GPG key ${SIGNING_KEY_ID}..." diff --git a/scripts/validate-release.sh b/scripts/validate-release.sh index 8e81d89..ba123c7 100755 --- a/scripts/validate-release.sh +++ b/scripts/validate-release.sh @@ -200,6 +200,28 @@ info "Validating checksums..." sha256sum -c checksums.txt >/dev/null 2>&1 || { error "checksums.txt validation failed"; exit 1; } success "checksums.txt validated" +# Validate individual .sha256 files exist and match checksums.txt +info "Validating individual .sha256 files..." +while IFS= read -r line; do + checksum=$(echo "$line" | awk '{print $1}') + filename=$(echo "$line" | awk '{print $2}') + + # Check .sha256 file exists + if [ ! -f "${filename}.sha256" ]; then + error "Missing ${filename}.sha256" + exit 1 + fi + + # Check .sha256 file content matches checksums.txt + sha256_content=$(cat "${filename}.sha256") + expected_content="${checksum} ${filename}" + if [ "$sha256_content" != "$expected_content" ]; then + error "${filename}.sha256 content mismatch" + exit 1 + fi +done < checksums.txt +success "Individual .sha256 files validated" + popd >/dev/null echo ""