#!/usr/bin/env bash set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" . "${repo_root}/scripts/apk/package-lib.sh" alpine_version="${ALPINE_VERSION:-3.24}" repo_name="${ALPINE_REPO_NAME:-local}" arch="${ALPINE_ARCH:-x86_64}" platform="${ALPINE_TEST_PLATFORM:-linux/amd64}" repo_dir="${repo_root}/packages/${repo_name}/${arch}" runtime_mode="${ALPINE_RUNTIME_TEST_MODE:-auto}" validate_repo() { if [[ ! -d "${repo_dir}" ]]; then printf 'missing local repository: packages/%s/%s\n' "${repo_name}" "${arch}" >&2 printf 'run: ALPINE_ARCH=%s mise run apk:build\n' "${arch}" >&2 exit 1 fi shopt -s nullglob repo_keys=("${repo_dir}"/*.rsa.pub) repo_indexes=("${repo_dir}"/APKINDEX.tar.gz) shopt -u nullglob if [[ "${#repo_keys[@]}" -eq 0 ]]; then printf 'missing repository key: packages/%s/%s/*.rsa.pub\n' "${repo_name}" "${arch}" >&2 exit 1 fi if [[ "${#repo_indexes[@]}" -eq 0 ]]; then printf 'missing repository index: packages/%s/%s/APKINDEX.tar.gz\n' "${repo_name}" "${arch}" >&2 exit 1 fi } in_alpine() { [[ -f /etc/alpine-release ]] && command -v apk >/dev/null 2>&1 } prepare_direct_runtime() { apk add --no-cache bash openrc >/dev/null cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/ printf '%s\n' "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories apk update mkdir -p /run/openrc touch /run/openrc/softlevel } run_hook_direct() { local hook_path="$1" local package_dir="$2" local package_name="$3" PACKAGE_DIR="${package_dir}" \ PACKAGE_NAME="${package_name}" \ "${hook_path}" } run_hook_docker() { local package_dir_rel="$1" docker run --rm --privileged --platform "${platform}" \ -e "ALPINE_ARCH=${arch}" \ -e "ALPINE_REPO_NAME=${repo_name}" \ -e "PACKAGE_DIR=/work/${package_dir_rel}" \ -e "PACKAGE_NAME=${package_name}" \ -v "${repo_root}:/work:ro" \ -v "${repo_root}/packages/${repo_name}:/repo:ro" \ "alpine:${alpine_version}" \ sh -lc ' set -e apk add --no-cache bash openrc >/dev/null cp "/repo/${ALPINE_ARCH}"/*.rsa.pub /etc/apk/keys/ printf "%s\n" /repo >> /etc/apk/repositories apk update mkdir -p /run/openrc touch /run/openrc/softlevel exec /bin/bash "${PACKAGE_DIR}/scripts/runtime-test.sh" ' } validate_repo case "${runtime_mode}" in auto) if in_alpine; then runtime_mode="direct" else runtime_mode="docker" fi ;; direct|docker) ;; *) printf 'unsupported ALPINE_RUNTIME_TEST_MODE: %s\n' "${runtime_mode}" >&2 printf 'expected: auto, direct, or docker\n' >&2 exit 2 ;; esac if [[ "${runtime_mode}" == "direct" ]]; then prepare_direct_runtime fi while IFS= read -r package_dir; do apk_validate_package_dir "${package_dir}" package_name="$(apk_package_name "${package_dir}")" hook_path="${package_dir}/scripts/runtime-test.sh" if [[ ! -e "${hook_path}" ]]; then printf 'Skipping %s: no runtime-test hook\n' "${package_name}" continue fi if [[ ! -x "${hook_path}" ]]; then printf 'package hook is not executable: %s\n' "${hook_path}" >&2 exit 1 fi if ! apk_package_supports_arch "${package_dir}" "${arch}"; then printf 'Skipping %s: unsupported arch %s\n' "${package_name}" "${arch}" continue fi case "${package_dir}" in "${repo_root}"/*) package_dir_rel="${package_dir#"${repo_root}/"}" ;; *) printf 'package directory must be inside repository: %s\n' "${package_dir}" >&2 exit 1 ;; esac printf 'Running runtime-test hook for %s\n' "${package_name}" if [[ "${runtime_mode}" == "direct" ]]; then run_hook_direct "${hook_path}" "${package_dir}" "${package_name}" else run_hook_docker "${package_dir_rel}" fi done < <(apk_package_dirs "${repo_root}")