Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions scripts/generate-checksums.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ mkdir -p "${OUT_DIR}"
# Find all release files (.tar.gz and .deb)
raw_files="$(cd "${DIST_DIR}" && find . -maxdepth 3 -type f \( -name '*.tar.gz' -o -name '*.deb' \) -print)"
cleaned_files="${raw_files//.\//}"
sorted_files="$(echo "${cleaned_files}" | sort)"
sorted_files="$(echo "${cleaned_files}" | LC_ALL=C sort)"
mapfile -t files <<< "${sorted_files}"

if [[ ${#files[@]} -eq 0 ]]; then
Expand All @@ -97,10 +97,13 @@ echo "Release assets:"
printf '%s\n' "${files[@]}"

# Compute checksums in GNU coreutils format (checksum first, compatible with sha256sum -c)
# Output uses basenames only for cleaner checksums.txt
# Output uses basenames only for cleaner checksums.txt. Sort by the
# filename field (-k2,2) under LC_ALL=C so output is byte-for-byte
# reproducible across environments; bare `sort` would order lines by
# the leading sha256 prefix, which isn't meaningful.
(cd "${DIST_DIR}" && sha256sum "${files[@]}") | while read -r sum file; do
echo "${sum} $(basename "${file}")"
done | sort > "${OUT_DIR}/checksums.txt"
done | LC_ALL=C sort -k2,2 > "${OUT_DIR}/checksums.txt"

echo ""
echo "${OUT_DIR}/checksums.txt:"
Expand Down
34 changes: 25 additions & 9 deletions tests/bats/scripts/generate-checksums.bats
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,39 @@ _make_artifacts() {
assert_success
}

@test "checksums.txt records every artifact found in the dist dir" {
# Note: the script's final `| sort` sorts lines by the sha256
# prefix (the first column on each line), not by filename, so we
# assert only the *set* of records — pinning the buggy hash-order
# would lock in a quirk that shouldn't be load-bearing.
@test "checksums.txt is sorted alphabetically by filename" {
local dist="${FAKE_REPO}/dist"
# Stage in non-alphabetical order to prove the sort actually
# reorders. The script sorts under LC_ALL=C, so the assertion is
# locale-independent.
_make_artifacts "${dist}" \
"ci-tools_1.0.0_osx-x64.tar.gz" \
"ci-tools_1.0.0_amd64.deb" \
"ci-tools_1.0.0_linux-x64.tar.gz"
run "${SCRIPT}" "${dist}"
assert_success
run awk '{print $2}' "${OUT_DIR}/checksums.txt"
assert_line "ci-tools_1.0.0_osx-x64.tar.gz"
assert_line "ci-tools_1.0.0_amd64.deb"
assert_line "ci-tools_1.0.0_linux-x64.tar.gz"
assert_equal "${#lines[@]}" 3
assert_output "ci-tools_1.0.0_amd64.deb
ci-tools_1.0.0_linux-x64.tar.gz
ci-tools_1.0.0_osx-x64.tar.gz"
}

@test "checksums.txt sort is locale-independent (script pins LC_ALL=C)" {
# Filenames where C and en_US.UTF-8 collation differ: under C,
# uppercase letters sort before lowercase (byte order); under
# en_US.UTF-8, sort is case-insensitive alphabetical. The
# ci-tools image generates en_US.UTF-8 for exactly this kind of
# check (see images/ci-tools/Dockerfile). If a future refactor
# drops the in-script LC_ALL=C, this test fails — output would
# come back as A.deb, b.deb, C.deb instead of the C-order below.
local dist="${FAKE_REPO}/dist"
_make_artifacts "${dist}" "A.deb" "b.deb" "C.deb"
run env LC_ALL=en_US.UTF-8 "${SCRIPT}" "${dist}"
assert_success
run awk '{print $2}' "${OUT_DIR}/checksums.txt"
assert_output "A.deb
C.deb
b.deb"
}

@test "checksums.txt records basenames only, even for nested artifacts" {
Expand Down