Ctrl K
ComunidadGuías…

scripts/test-m2image-source-publish.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
set -euo pipefail
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
tmp=$(mktemp -d)
trap 'rm -rf -- "$tmp"' EXIT

dist="$tmp/dist"
mapfile -t aliases < <(python3 "$root/scripts/m2image-manifest.py" aliases)
mapfile -t architectures < <(python3 "$root/scripts/m2image-manifest.py" architectures)
expected_images=$((${#aliases[@]} * ${#architectures[@]}))

for arch in "${architectures[@]}"; do
  mkdir -p "$dist/$arch"
  for alias in "${aliases[@]}"; do
    printf 'binary %s %s\n' "$alias" "$arch" >"$dist/$arch/${alias}.tar.zst"
    printf 'source %s %s\n' "$alias" "$arch" >"$dist/$arch/${alias}.sources.tar.zst"
  done
  (
    cd "$dist/$arch"
    : >SHA256SUMS
    for alias in "${aliases[@]}"; do
      sha256sum "${alias}.tar.zst" "${alias}.sources.tar.zst" >>SHA256SUMS
    done
  )
done

DIST_DIR="$dist" "$root/scripts/publish-m2images-r2.sh" \
  --bucket firecrab-test --backend rclone --dry-run >"$tmp/publish.out"

# Every immutable binary must have an immutable source sibling in the dry-run.
for arch in "${architectures[@]}"; do
  for alias in "${aliases[@]}"; do
    binary_key=$(python3 "$root/scripts/m2image-manifest.py" registry-key "$alias" "$arch")
    source_key=$(python3 "$root/scripts/m2image-manifest.py" source-registry-key "$alias" "$arch")
    grep -Fq "${source_key}" "$tmp/publish.out"
    grep -Fq "${binary_key}" "$tmp/publish.out"
  done
done

# The strict catalog binds both hashes and refuses a missing source sibling.
python3 "$root/scripts/m2image-manifest.py" catalog \
  --dist-dir "$dist" --output "$tmp/catalog.json"
python3 - "$tmp/catalog.json" "$expected_images" <<'PY'
import json
import sys

with open(sys.argv[1], encoding='utf-8') as stream:
    catalog = json.load(stream)
expected = int(sys.argv[2])
images = catalog.get('images')
if not isinstance(images, list) or len(images) != expected:
    raise SystemExit(
        f"catalog image count mismatch: expected {expected}, got "
        f"{len(images) if isinstance(images, list) else type(images).__name__}"
    )
for image in images:
    if not isinstance(image, dict):
        raise SystemExit('catalog image entry is not an object')
    source = image.get('source')
    if not isinstance(source, str) or not source.endswith('.sources.tar.zst'):
        raise SystemExit(f"catalog source sibling is invalid: {source!r}")
    source_sha = image.get('sourceSha256')
    if not isinstance(source_sha, str) or len(source_sha) != 64:
        raise SystemExit('catalog sourceSha256 is not a 64-character digest')
    source_size = image.get('sourceSizeBytes')
    if not isinstance(source_size, int) or source_size <= 0:
        raise SystemExit('catalog sourceSizeBytes must be positive')
    binary_sha = image.get('sha256')
    if not isinstance(binary_sha, str) or len(binary_sha) != 64:
        raise SystemExit('catalog binary sha256 is not a 64-character digest')
PY

catalog_line=$(grep -nF '[INFO] publishing catalog last' "$tmp/publish.out" | tail -n1 | cut -d: -f1 || true)
last_source_line=$(grep -nF '[INFO] uploading exact source ' "$tmp/publish.out" | tail -n1 | cut -d: -f1 || true)
last_binary_line=$(grep -nE '^\[INFO\] uploading [^ ]+/[^ ]+ -> r2://' "$tmp/publish.out" | tail -n1 | cut -d: -f1 || true)
for value in "$catalog_line" "$last_source_line" "$last_binary_line"; do
  test -n "$value" || { echo 'expected publication ordering log line is missing' >&2; exit 1; }
done
test "$catalog_line" -gt "$last_source_line"
test "$catalog_line" -gt "$last_binary_line"

rm -f "$dist/x86_64/${aliases[0]}.sources.tar.zst"
if python3 "$root/scripts/m2image-manifest.py" catalog \
  --dist-dir "$dist" --output "$tmp/should-not-exist.json" \
  >"$tmp/missing.out" 2>&1; then
  echo 'catalog unexpectedly accepted a missing source archive' >&2
  exit 1
fi
grep -q 'source package not found' "$tmp/missing.out"

echo 'M2Image source publication contract passed'