Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-12 08:24:59

0001 #!/bin/sh
0002 # check_image_size IMAGE_REFERENCE LIMIT_GIB
0003 #
0004 # Inspects a single-arch OCI/Docker image manifest (or the first image
0005 # manifest in a multi-arch OCI/Docker image) that has already been pushed
0006 # to a registry and fails with a clear message if the total compressed layer
0007 # size exceeds LIMIT_GIB gibibytes.
0008 #
0009 # Requires: docker (with buildx), jq, bc
0010 # Usage:
0011 #   scripts/check_image_size ghcr.io/eic/eic_xl@sha256:abc... 10
0012 #   scripts/check_image_size ghcr.io/eic/eic_xl:master 10
0013 #
0014 # The caller is responsible for being logged in to the registry before calling
0015 # this script.
0016 
0017 set -e
0018 
0019 IMAGE_REF="${1:?Usage: $0 IMAGE_REFERENCE LIMIT_GIB}"
0020 LIMIT_GIB="${2:?Usage: $0 IMAGE_REFERENCE LIMIT_GIB}"
0021 
0022 echo "Checking compressed image size for ${IMAGE_REF} (limit: ${LIMIT_GIB} GiB) ..."
0023 
0024 MANIFEST=$(docker buildx imagetools inspect --raw "${IMAGE_REF}")
0025 
0026 # docker/build-push-action (v4+) wraps even single-platform pushes in an OCI
0027 # Image Index when provenance attestations are enabled (the default).  Detect
0028 # that case and resolve to the real per-platform Image Manifest before summing
0029 # layer sizes.
0030 MEDIA_TYPE=$(printf '%s' "${MANIFEST}" | jq -r '.mediaType // ""')
0031 case "${MEDIA_TYPE}" in
0032   *index* | *manifest.list*)
0033     DIGEST=$(printf '%s' "${MANIFEST}" | jq -r '
0034       .manifests[]
0035       | select(
0036           .artifactType == null
0037           and ((.annotations["vnd.docker.reference.type"] // "") != "attestation-manifest")
0038           and ((.annotations["vnd.docker.reference.digest"] // "") == "")
0039           and .platform != null
0040           and (.platform.os // "") != ""
0041           and (.platform.architecture // "") != ""
0042           and (.platform.os // "") != "unknown"
0043           and (.platform.architecture // "") != "unknown"
0044         )
0045       | .digest' | head -1)
0046     if [ -z "${DIGEST}" ]; then
0047       echo "ERROR: OCI Image Index contains no platform manifest."
0048       exit 1
0049     fi
0050     IMAGE_BASE="${IMAGE_REF%%@*}"
0051     # Strip :tag from the last path segment only (preserves registry host:port)
0052     _dir="${IMAGE_BASE%/*}"
0053     _name="${IMAGE_BASE##*/}"
0054     if [ "${_dir}" != "${IMAGE_BASE}" ]; then
0055       IMAGE_BASE="${_dir}/${_name%%:*}"
0056     else
0057       IMAGE_BASE="${_name%%:*}"
0058     fi
0059     MANIFEST=$(docker buildx imagetools inspect --raw "${IMAGE_BASE}@${DIGEST}")
0060     ;;
0061 esac
0062 
0063 SIZE_BYTES=$(printf '%s' "${MANIFEST}" | jq '[.layers[].size] | add // 0')
0064 
0065 if [ -z "${SIZE_BYTES}" ] || [ "${SIZE_BYTES}" = "null" ] || [ "${SIZE_BYTES}" -eq 0 ]; then
0066   echo "ERROR: Could not determine image size from manifest (got: ${SIZE_BYTES})."
0067   echo "       Manifest snippet: $(printf '%s' "${MANIFEST}" | head -c 500)"
0068   exit 1
0069 fi
0070 
0071 SIZE_CENTI_GIB=$(echo "(${SIZE_BYTES} * 100 + 1073741824 - 1) / 1073741824" | bc)
0072 SIZE_GIB="$(echo "${SIZE_CENTI_GIB} / 100" | bc).$(printf '%02d' "$(echo "${SIZE_CENTI_GIB} % 100" | bc)")"
0073 LIMIT_BYTES=$(echo "${LIMIT_GIB} * 1073741824 / 1" | bc)
0074 
0075 echo "  Compressed size : ${SIZE_GIB} GiB (${SIZE_BYTES} bytes)"
0076 echo "  Limit           : ${LIMIT_GIB} GiB (${LIMIT_BYTES} bytes)"
0077 
0078 if [ "${SIZE_BYTES}" -gt "${LIMIT_BYTES}" ]; then
0079   echo ""
0080   echo "ERROR: Image ${IMAGE_REF} exceeds the size cap!"
0081   echo "       ${SIZE_GIB} GiB > ${LIMIT_GIB} GiB"
0082   echo ""
0083   echo "To update the high-water mark after an intentional size increase:"
0084   echo "  1. Re-run this script to inspect the published image size:"
0085   echo "     scripts/check_image_size \"${IMAGE_REF}\" \"${LIMIT_GIB}\""
0086   echo "  2. Add ~15% buffer, and optionally round up to the next whole GiB"
0087   echo "  3. Update SIZE_LIMIT_*_GIB in .github/workflows/build-push.yml and .gitlab-ci.yml"
0088   exit 1
0089 fi
0090 
0091 echo "  OK: size is within the ${LIMIT_GIB} GiB limit."