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
28 changes: 23 additions & 5 deletions scripts/publish-platform-index.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,35 @@ test "$(podman image inspect --format '{{.Architecture}}' "$amd_image")" = amd64
test "$(podman image inspect --format '{{.Architecture}}' "$arm_image")" = arm64
# A push may convert the archive's manifest and update its storage metadata. Do
# not reuse an index assembled from those local instances before the pushes.
podman push "${options[@]}" --format=v2s2 --digestfile "$scratch/amd.digest" "$amd_image" "docker://$repository-amd:latest"
podman push "${options[@]}" --format=v2s2 --digestfile "$scratch/arm.digest" "$arm_image" "docker://$repository-arm:latest"
# Retain legacy architecture repositories for existing consumers.
podman push "${options[@]}" --format=v2s2 "$amd_image" "docker://$repository-amd:latest"
podman push "${options[@]}" --format=v2s2 "$arm_image" "docker://$repository-arm:latest"
# Registries require every index child manifest in the index's own repository.
podman push "${options[@]}" --format=v2s2 --digestfile "$scratch/amd.digest" "$amd_image" "docker://$repository:amd64"
podman push "${options[@]}" --format=v2s2 --digestfile "$scratch/arm.digest" "$arm_image" "docker://$repository:arm64"
amd_digest=$(cat "$scratch/amd.digest")
arm_digest=$(cat "$scratch/arm.digest")
for digest in "$amd_digest" "$arm_digest"; do
[[ "$digest" =~ ^sha256:[0-9a-f]{64}$ ]] || { echo 'Invalid pushed image digest' >&2; exit 1; }
done
# Fetch by immutable digest from the destination repository before publishing.
for digest in "$amd_digest" "$arm_digest"; do
if ! podman manifest inspect "${options[@]}" "$repository@$digest" > /dev/null; then
echo "Missing child manifest in destination repository: $repository@$digest" >&2
exit 1
fi
done
podman manifest create "$manifest"
podman manifest add "${options[@]}" "$manifest" "docker://$repository-amd@$amd_digest"
podman manifest add "${options[@]}" "$manifest" "docker://$repository-arm@$arm_digest"
podman manifest push --all "${options[@]}" --format=docker "$manifest" "docker://$destination"
podman manifest add "${options[@]}" "$manifest" "docker://$repository@$amd_digest"
podman manifest add "${options[@]}" "$manifest" "docker://$repository@$arm_digest"
# Child manifests and blobs already exist in this repository. Copying them again
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
# can recompress layers and replace the exact digests pinned above. Publish only
# the index with --all=false; Podman 5 defaults --all to true. Keep both pinned
# child digests unchanged. Child publication and index publication are separate.
if ! podman manifest push --all=false "${options[@]}" --format=docker "$manifest" "docker://$destination"; then
echo "Failed to publish platform index: $destination" >&2
exit 1
fi
podman manifest inspect "${options[@]}" "$destination" > "$scratch/index.json"
python3 - "$scratch/index.json" "$amd_digest" "$arm_digest" <<'PYTHON'
import json
Expand Down
35 changes: 35 additions & 0 deletions tests/integration/publishing/test-platform-publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,38 @@ for arch in amd64 arm64; do
done
podman manifest inspect --tls-verify=false 127.0.0.1:5000/fetchit-test:latest > /tmp/retagged-index.json
cmp /tmp/original-index.json /tmp/retagged-index.json

# Recompression must not rewrite the already-published child manifests. Force
# different gzip levels for the architecture pushes and any attempted index-side
# child copies. This reproduces the main-branch failure with tiny test images.
wrapper_dir=$(mktemp -d)
real_podman=$(command -v podman)
export FETCHIT_TEST_REAL_PODMAN="$real_podman"
cat > "$wrapper_dir/podman" <<'WRAPPER'
#!/usr/bin/env bash
set -euo pipefail
if [[ ${FETCHIT_TEST_MISSING_CHILD:-false} == true && ${1:-} == manifest && ${2:-} == inspect && "$*" == *@sha256:* ]]; then
echo 'Simulated missing destination child manifest' >&2
exit 125
fi
if [[ ${1:-} == push ]]; then
shift
exec "$FETCHIT_TEST_REAL_PODMAN" push --compression-format=gzip --compression-level=1 --force-compression "$@"
elif [[ ${1:-} == manifest && ${2:-} == push ]]; then
shift 2
exec "$FETCHIT_TEST_REAL_PODMAN" manifest push --compression-format=gzip --compression-level=9 --force-compression "$@"
fi
exec "$FETCHIT_TEST_REAL_PODMAN" "$@"
WRAPPER
chmod +x "$wrapper_dir/podman"
PATH="$wrapper_dir:$PATH" FETCHIT_REGISTRY_TLS_VERIFY=false bash scripts/publish-platform-index.sh \
127.0.0.1:5000/fetchit-recompression:latest localhost/publish-source:amd64 localhost/publish-source:arm64
# If a destination child cannot be read, fail before creating a public index.
expect_failure env PATH="$wrapper_dir:$PATH" FETCHIT_TEST_MISSING_CHILD=true FETCHIT_REGISTRY_TLS_VERIFY=false \
bash scripts/publish-platform-index.sh 127.0.0.1:5000/fetchit-missing-child:latest localhost/publish-source:amd64 localhost/publish-source:arm64
expect_failure podman manifest inspect --tls-verify=false 127.0.0.1:5000/fetchit-missing-child:latest
rm -rf "$wrapper_dir"
for arch in amd64 arm64; do
loaded=$(podman pull --quiet --tls-verify=false --policy=always --platform "linux/$arch" 127.0.0.1:5000/fetchit-recompression:latest)
test "$(podman image inspect --format '{{.Architecture}}' "$loaded")" = "$arch"
done
Loading