Ctrl K
ComunidadGuías…

scripts/build-m2images.sh

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

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
# Build and package Firecracker M2Images from packaging/m2images.json.

set -euo pipefail

unset CDPATH
script_dir=$(cd -- "$(dirname -- "$0")" && pwd -P)
repo_dir=$(cd -- "${script_dir}/.." && pwd -P)
manifest=${M2IMAGE_MANIFEST:-${repo_dir}/packaging/m2images.json}
dist_dir=${DIST_DIR:-${repo_dir}/dist/m2images}
out_dir=${OUT_DIR:-}
compliance_dir=${M2IMAGE_COMPLIANCE_DIR:-${repo_dir}/images/compliance}
alias_filter=all
architecture=${M2IMAGE_ARCH:-}
package_images=1

usage() {
  cat <<'EOF'
Usage: ./scripts/build-m2images.sh [options]

Options:
  --alias <alias|all>         Build one manifest alias or all aliases (default: all)
  --arch <x86_64|aarch64>    Target architecture (default: uname -m)
  --manifest <path>          Alternate release manifest
  --dist-dir <path>          Package root (default: dist/m2images)
  --no-package               Build image files without packaging them
  --list                     List configured aliases and exit
  -h, --help                 Show this help

The manifest pins distribution versions, builders, artifact paths, internal
revisions, and Cloudflare R2 object keys. Build each architecture on a native
host of that architecture; package outputs are written below <dist-dir>/<arch>.
EOF
}

info() { printf '[INFO] %s\n' "$*"; }
fail() { printf '[FAIL] %s\n' "$*" >&2; exit 1; }
require_command() { command -v "$1" >/dev/null 2>&1 || fail "$1 is required"; }

normalize_architecture() {
  case "$1" in
    x86_64|amd64) printf '%s\n' x86_64 ;;
    aarch64|arm64) printf '%s\n' aarch64 ;;
    *) fail "unsupported architecture: $1 (want x86_64 or aarch64)" ;;
  esac
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help) usage; exit 0 ;;
    --alias) [ "$#" -ge 2 ] || fail 'missing value for --alias'; alias_filter=$2; shift 2 ;;
    --alias=*) alias_filter=${1#--alias=}; shift ;;
    --arch) [ "$#" -ge 2 ] || fail 'missing value for --arch'; architecture=$2; shift 2 ;;
    --arch=*) architecture=${1#--arch=}; shift ;;
    --manifest) [ "$#" -ge 2 ] || fail 'missing value for --manifest'; manifest=$2; shift 2 ;;
    --manifest=*) manifest=${1#--manifest=}; shift ;;
    --dist-dir) [ "$#" -ge 2 ] || fail 'missing value for --dist-dir'; dist_dir=$2; shift 2 ;;
    --dist-dir=*) dist_dir=${1#--dist-dir=}; shift ;;
    --no-package) package_images=0; shift ;;
    --list)
      require_command python3
      python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" aliases
      exit 0
      ;;
    *) fail "unknown argument: $1" ;;
  esac
done

require_command python3
require_command sha256sum
python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" validate >/dev/null
architecture=$(normalize_architecture "${architecture:-$(uname -m)}")
export M2IMAGE_ARCH=$architecture
mkdir -p "$compliance_dir"

if [ -z "$out_dir" ]; then
  out_dir="${dist_dir}/${architecture}"
fi

mapfile -t known_aliases < <(
  python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" aliases
)
selected_aliases=()
if [ "$alias_filter" = all ]; then
  selected_aliases=("${known_aliases[@]}")
else
  for alias in "${known_aliases[@]}"; do
    if [ "$alias" = "$alias_filter" ]; then
      selected_aliases=("$alias")
      break
    fi
  done
  [ "${#selected_aliases[@]}" -eq 1 ] || fail "unknown --alias: $alias_filter"
fi

for alias in "${selected_aliases[@]}"; do
  builder=$(python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" \
    field "$alias" builder.script)
  version=$(python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" \
    field "$alias" version)
  [ -x "${repo_dir}/${builder}" ] || fail "builder is not executable: ${repo_dir}/${builder}"

  while IFS= read -r command; do
    [ -n "$command" ] && require_command "$command"
  done < <(python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" requires "$alias")

  builder_environment=()
  while IFS=$'\t' read -r key value; do
    [ -n "$key" ] || continue
    builder_environment+=("${key}=${value}")
  done < <(python3 "${script_dir}/m2image-manifest.py" --manifest "$manifest" environment "$alias")

  sbom_output="${compliance_dir}/${alias}-${architecture}.spdx.json"
  rm -f -- "$sbom_output"
  info "building ${alias} (distribution ${version}, ${architecture})"
  env "M2IMAGE_ALIAS=${alias}" "M2IMAGE_SBOM_OUTPUT=${sbom_output}" \
    "${builder_environment[@]}" "${repo_dir}/${builder}"
  [ -s "$sbom_output" ] || fail "builder did not produce M2Image SBOM: $sbom_output"
  python3 - "$sbom_output" "$alias" <<'PY_VALIDATE'
import json
import sys

path, expected_alias = sys.argv[1:3]
try:
    with open(path, encoding="utf-8") as stream:
        doc = json.load(stream)
except (OSError, json.JSONDecodeError) as exc:
    raise SystemExit(f"invalid M2Image SBOM {path}: {exc}") from exc

if doc.get("spdxVersion") != "SPDX-2.3":
    raise SystemExit(
        f"invalid M2Image SBOM {path}: expected SPDX-2.3, "
        f"got {doc.get('spdxVersion')!r}"
    )
packages = doc.get("packages")
if not isinstance(packages, list) or not packages:
    raise SystemExit(f"invalid M2Image SBOM {path}: packages must be a non-empty list")
actual_alias = packages[0].get("name") if isinstance(packages[0], dict) else None
if actual_alias != expected_alias:
    raise SystemExit(
        f"invalid M2Image SBOM {path}: expected image alias {expected_alias!r}, "
        f"got {actual_alias!r}"
    )
PY_VALIDATE
  M2IMAGE_MANIFEST="$manifest" IMAGE_ROOT="${repo_dir}/images" \
    M2IMAGE_COMPLIANCE_DIR="$compliance_dir" \
    bash "${script_dir}/collect-m2image-compliance.sh" "$alias" "$architecture"
  [ -s "${compliance_dir}/${alias}-${architecture}/bundle.json" ] \
    || fail "builder did not produce M2Image compliance bundle for ${alias}/${architecture}"
done

if [ "$package_images" -eq 1 ]; then
  package_alias=$alias_filter
  info "packaging ${package_alias} into ${out_dir}"
  IMAGE_ROOT="${repo_dir}/images" OUT_DIR="$out_dir" DIST_DIR="$dist_dir" \
    M2IMAGE_ARCH="$architecture" M2IMAGE_MANIFEST="$manifest" \
    "${script_dir}/package-m2images.sh" --alias "$package_alias" --arch "$architecture"

  info "verifying ${out_dir}/SHA256SUMS"
  (cd "$out_dir" && sha256sum -c SHA256SUMS)
fi

info 'M2Image build complete'