From 25f23a9c24866624cd34da9adfc70b26690123a2 Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 10:24:25 +0800 Subject: [PATCH 1/6] .github: build: Add KIWI verification helpers Signed-off-by: Jingwiw --- .github/common/list-changed-spec-packages.sh | 11 + .github/common/make-local-rpm-repo.sh | 40 +++ .github/common/match-package-list.sh | 18 ++ .../kiwi-installiso/Dockerfile.builder | 8 + .../kiwi-installiso/build-and-inspect.sh | 168 ++++++++++++ .../kiwi-installiso/build-image.sh | 243 ++++++++++++++++++ .../kiwi-installiso/trigger-packages.txt | 30 +++ .../policy/auth-model/trigger-packages.txt | 13 + .github/testsuite/policy/auth-model/verify.sh | 126 +++++++++ .../smoke/installiso/verify-output.sh | 170 ++++++++++++ 10 files changed, 827 insertions(+) create mode 100644 .github/common/list-changed-spec-packages.sh create mode 100644 .github/common/make-local-rpm-repo.sh create mode 100644 .github/common/match-package-list.sh create mode 100644 .github/image-build/kiwi-installiso/Dockerfile.builder create mode 100644 .github/image-build/kiwi-installiso/build-and-inspect.sh create mode 100644 .github/image-build/kiwi-installiso/build-image.sh create mode 100644 .github/image-build/kiwi-installiso/trigger-packages.txt create mode 100644 .github/testsuite/policy/auth-model/trigger-packages.txt create mode 100644 .github/testsuite/policy/auth-model/verify.sh create mode 100644 .github/testsuite/smoke/installiso/verify-output.sh diff --git a/.github/common/list-changed-spec-packages.sh b/.github/common/list-changed-spec-packages.sh new file mode 100644 index 0000000000..b3f50e4f52 --- /dev/null +++ b/.github/common/list-changed-spec-packages.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +while IFS= read -r path; do + case "$path" in + SPECS/*/*) + path=${path#SPECS/} + printf '%s\n' "${path%%/*}" + ;; + esac +done | awk 'NF && !seen[$0]++' diff --git a/.github/common/make-local-rpm-repo.sh b/.github/common/make-local-rpm-repo.sh new file mode 100644 index 0000000000..11ae1372f9 --- /dev/null +++ b/.github/common/make-local-rpm-repo.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +artifact_dir=${1:?usage: make-local-rpm-repo.sh } +output_repo_dir=${2:?usage: make-local-rpm-repo.sh } +provenance_file=${PROVENANCE_FILE:-$output_repo_dir/PROVENANCE.txt} + +rm -rf "$output_repo_dir" +mkdir -p "$output_repo_dir" + +mapfile -d '' rpm_files < <( + find "$artifact_dir" -type f -name '*.rpm' \ + ! -name '*.src.rpm' \ + ! -name '*-debuginfo-*.rpm' \ + ! -name '*-debugsource-*.rpm' \ + -print0 +) + +if [[ ${#rpm_files[@]} -eq 0 ]]; then + echo "no binary rpms found under $artifact_dir" >&2 + exit 1 +fi + +declare -A seen_rpms=() +: >"$provenance_file" + +for rpm_file in "${rpm_files[@]}"; do + rpm_name=$(basename "$rpm_file") + if [[ -n "${seen_rpms[$rpm_name]:-}" ]]; then + echo "duplicate rpm basename detected: $rpm_name" >&2 + echo "first: ${seen_rpms[$rpm_name]}" >&2 + echo "second: $rpm_file" >&2 + exit 1 + fi + seen_rpms[$rpm_name]=$rpm_file + cp "$rpm_file" "$output_repo_dir/$rpm_name" + printf '%s\t%s\n' "$rpm_name" "$rpm_file" >>"$provenance_file" +done + +createrepo_c "$output_repo_dir" diff --git a/.github/common/match-package-list.sh b/.github/common/match-package-list.sh new file mode 100644 index 0000000000..8573ed45f7 --- /dev/null +++ b/.github/common/match-package-list.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +package_list=${1:?usage: match-package-list.sh } +tmp_file=$(mktemp) + +cleanup() { + rm -f "$tmp_file" +} +trap cleanup EXIT INT TERM + +grep -v '^[[:space:]]*#' "$package_list" | sed '/^[[:space:]]*$/d' | sort -u >"$tmp_file" + +while IFS= read -r package; do + if [[ -n "$package" ]] && grep -Fxq "$package" "$tmp_file"; then + printf '%s\n' "$package" + fi +done | awk 'NF && !seen[$0]++' diff --git a/.github/image-build/kiwi-installiso/Dockerfile.builder b/.github/image-build/kiwi-installiso/Dockerfile.builder new file mode 100644 index 0000000000..a765c32e77 --- /dev/null +++ b/.github/image-build/kiwi-installiso/Dockerfile.builder @@ -0,0 +1,8 @@ +ARG BASE_IMAGE=docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d +FROM --platform=linux/amd64 ${BASE_IMAGE} + +RUN zypper --non-interactive refresh && \ + zypper --non-interactive install -y bash curl dnf5 kiwi-systemdeps perl python3 python3-kiwi sudo && \ + zypper clean -a + +WORKDIR /work diff --git a/.github/image-build/kiwi-installiso/build-and-inspect.sh b/.github/image-build/kiwi-installiso/build-and-inspect.sh new file mode 100644 index 0000000000..853ae9bc4c --- /dev/null +++ b/.github/image-build/kiwi-installiso/build-and-inspect.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash +set -euo pipefail + +image_repo_dir=${1:?usage: build-and-inspect.sh } +overlay_repo_dir=${2:?usage: build-and-inspect.sh } +output_dir=${3:?usage: build-and-inspect.sh } + +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +profile=${PROFILE:-installiso} +target_arch=${TARGET_ARCH:-x86_64} +build_platform=${BUILD_PLATFORM:-linux/amd64} +case "$target_arch" in + x86_64) expected_platform=linux/amd64 ;; + *) + echo "unsupported TARGET_ARCH=$target_arch; only x86_64 is implemented today" >&2 + exit 1 + ;; +esac +if [[ "$build_platform" != "$expected_platform" ]]; then + echo "BUILD_PLATFORM=$build_platform does not match TARGET_ARCH=$target_arch" >&2 + exit 1 +fi + +upstream_repo=${UPSTREAM_REPO:-https://repo.build.openruyi.cn/openruyi/x86_64/} +upstream_repomd_sha256=${UPSTREAM_REPOMD_SHA256:-} +kiwi_source_commit=${KIWI_SOURCE_COMMIT:-unknown} +builder_base_image=${BUILDER_BASE_IMAGE:-docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d} +builder_image=${BUILDER_IMAGE:-openruyi-kiwi-builder:ci} +build_dir_in_container=${BUILD_DIR_IN_CONTAINER:-/var/tmp/openruyi-${profile}-ci} +container_name=${CONTAINER_NAME:-kiwi-ci-${profile}-${GITHUB_RUN_ID:-$$}} +overlay_repo_url=${OVERLAY_REPO_URL:-file:///overlay/} +builder_dockerfile=${BUILDER_DOCKERFILE:-$script_dir/Dockerfile.builder} +build_script_in_container=${BUILD_SCRIPT_IN_CONTAINER:-/helper/build-image.sh} +docker_bin=${DOCKER_BIN:-docker} + +rm -rf "$output_dir" +mkdir -p "$output_dir/inspect" + +"$docker_bin" build --platform "$build_platform" \ + --build-arg BASE_IMAGE="$builder_base_image" \ + -t "$builder_image" \ + -f "$builder_dockerfile" \ + "$script_dir" + +cleanup() { + if "$docker_bin" ps -a --format '{{.Names}}' | grep -qx "$container_name"; then + "$docker_bin" rm -f "$container_name" >/dev/null 2>&1 || true + fi +} +trap cleanup EXIT INT TERM + +cleanup + +set +e +"$docker_bin" run --name "$container_name" \ + --platform "$build_platform" \ + --privileged \ + -e PROFILE="$profile" \ + -e TARGET_ARCH="$target_arch" \ + -e BUILD_PLATFORM="$build_platform" \ + -e UPSTREAM_REPO="$upstream_repo" \ + -e UPSTREAM_REPOMD_SHA256="$upstream_repomd_sha256" \ + -e OVERLAY_REPO="$overlay_repo_url" \ + -e KIWI_SOURCE_COMMIT="$kiwi_source_commit" \ + -e BUILDER_BASE_IMAGE="$builder_base_image" \ + -e BUILD_DIR_IN_CONTAINER="$build_dir_in_container" \ + -e CONTAINER_NAME="$container_name" \ + -v "$image_repo_dir":/image:ro \ + -v "$overlay_repo_dir":/overlay:ro \ + -v "$script_dir":/helper:ro \ + -v "$output_dir":/out \ + -w /image \ + "$builder_image" \ + bash -lc ' + set -euo pipefail + + capture_command() { + local name=$1 + shift + local out_file=/out/inspect/${name}.txt + local err_file=/out/inspect/${name}.err + local rc_file=/out/inspect/${name}.rc + local rc=0 + + set +e + "$@" >"$out_file" 2>"$err_file" + rc=$? + set -e + + printf "%s\n" "$rc" >"$rc_file" + } + + rm -rf "$BUILD_DIR_IN_CONTAINER" + SUDO= PROFILE="$PROFILE" TARGET_ARCH="$TARGET_ARCH" BUILD_PLATFORM="$BUILD_PLATFORM" \ + UPSTREAM_REPO="$UPSTREAM_REPO" UPSTREAM_REPOMD_SHA256="$UPSTREAM_REPOMD_SHA256" \ + OVERLAY_REPO="$OVERLAY_REPO" KIWI_SOURCE_COMMIT="$KIWI_SOURCE_COMMIT" \ + BUILDER_BASE_IMAGE="$BUILDER_BASE_IMAGE" \ + bash "'"$build_script_in_container"'" /image "$BUILD_DIR_IN_CONTAINER" + + mkdir -p /out/inspect + + shopt -s nullglob + for artifact in \ + "$BUILD_DIR_IN_CONTAINER"/*.qcow2 \ + "$BUILD_DIR_IN_CONTAINER"/*.raw \ + "$BUILD_DIR_IN_CONTAINER"/*.iso \ + "$BUILD_DIR_IN_CONTAINER"/*.packages \ + "$BUILD_DIR_IN_CONTAINER"/*.changes \ + "$BUILD_DIR_IN_CONTAINER"/*.verified \ + "$BUILD_DIR_IN_CONTAINER"/compose-inputs.env \ + "$BUILD_DIR_IN_CONTAINER"/prepared-image.kiwi \ + "$BUILD_DIR_IN_CONTAINER"/prepared-config.sh; do + cp "$artifact" /out/ + done + + rootfs="$BUILD_DIR_IN_CONTAINER/build/image-root" + cp "$rootfs/etc/passwd" /out/inspect/passwd + cp "$rootfs/etc/group" /out/inspect/group + if [[ -f "$rootfs/etc/nsswitch.conf" ]]; then + cp "$rootfs/etc/nsswitch.conf" /out/inspect/nsswitch.conf + fi + if [[ -f "$rootfs/etc/authselect/authselect.conf" ]]; then + cp "$rootfs/etc/authselect/authselect.conf" /out/inspect/authselect.conf + fi + for pam_name in system-auth password-auth postlogin; do + if [[ -f "$rootfs/etc/pam.d/$pam_name" ]]; then + cp "$rootfs/etc/pam.d/$pam_name" "/out/inspect/$pam_name" + fi + if [[ -f "$rootfs/etc/authselect/$pam_name" ]]; then + cp "$rootfs/etc/authselect/$pam_name" "/out/inspect/authselect-$pam_name" + fi + done + + if [[ -x "$rootfs/usr/bin/authselect" ]]; then + capture_command authselect-current-raw chroot "$rootfs" /usr/bin/authselect current --raw + else + : >/out/inspect/authselect-current-raw.txt + printf "%s\n" "authselect missing from image rootfs" >/out/inspect/authselect-current-raw.err + printf "%s\n" "127" >/out/inspect/authselect-current-raw.rc + fi + + capture_command rpm-query rpm --root "$rootfs" --dbpath /usr/lib/sysimage/rpm -q \ + setup authselect openruyi-authselect-profiles system-user-root + + cat >/out/inspect/build.env < } +target_dir=${2:?usage: build-image.sh } + +profile=${PROFILE:-installiso} +target_arch=${TARGET_ARCH:-x86_64} +build_platform=${BUILD_PLATFORM:-linux/amd64} +case "$target_arch" in + x86_64) + expected_platform=linux/amd64 + default_upstream_repo=https://repo.build.openruyi.cn/openruyi/x86_64/ + ;; + *) + echo "unsupported TARGET_ARCH=$target_arch; only x86_64 is implemented today" >&2 + exit 1 + ;; +esac +if [[ "$build_platform" != "$expected_platform" ]]; then + echo "BUILD_PLATFORM=$build_platform does not match TARGET_ARCH=$target_arch" >&2 + exit 1 +fi + +upstream_repo=${UPSTREAM_REPO:-${MAIN_REPO:-$default_upstream_repo}} +overlay_repo=${OVERLAY_REPO:-${FIX_REPO:-}} +upstream_repomd_url=${UPSTREAM_REPOMD_URL:-${upstream_repo%/}/repodata/repomd.xml} +upstream_repomd_sha256=${UPSTREAM_REPOMD_SHA256:-} +builder_base_image=${BUILDER_BASE_IMAGE:-docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d} +kiwi_source_commit=${KIWI_SOURCE_COMMIT:-unknown} +sudo_cmd=${SUDO-sudo} +kiwi_part_mapper=${KIWI_PART_MAPPER:-} + +if [[ ! -f "$image_repo_dir/image.kiwi" ]]; then + echo "image.kiwi missing under $image_repo_dir" >&2 + exit 1 +fi + +mkdir -p "$target_dir" + +if [[ -n "$upstream_repomd_sha256" ]]; then + actual_repomd_sha256=$(curl -fsSL "$upstream_repomd_url" | sha256sum | awk '{print $1}') + if [[ "$actual_repomd_sha256" != "$upstream_repomd_sha256" ]]; then + echo "upstream repomd checksum mismatch: expected $upstream_repomd_sha256, got $actual_repomd_sha256" >&2 + exit 1 + fi +fi + +work_dir=$(mktemp -d "${TMPDIR:-/tmp}/openruyi-kiwi.XXXXXX") +cleanup() { + rm -rf "$work_dir" +} +trap cleanup EXIT INT TERM + +( + cd "$image_repo_dir" + tar \ + --exclude='./.git' \ + --exclude='./.DS_Store' \ + --exclude='./out-*' \ + -cf - . +) | ( + cd "$work_dir" + tar -xf - +) + +IMAGE_KIWI_PATH=$work_dir/image.kiwi \ +UPSTREAM_REPO_XML=$upstream_repo \ +OVERLAY_REPO_XML=$overlay_repo \ +python3 <<'PY' +import os +import xml.etree.ElementTree as ET + + +def local_name(tag: str) -> str: + return tag.split("}", 1)[-1] + + +image_kiwi_path = os.environ["IMAGE_KIWI_PATH"] +upstream_repo = os.environ["UPSTREAM_REPO_XML"] +overlay_repo = os.environ["OVERLAY_REPO_XML"] + +tree = ET.parse(image_kiwi_path) +root = tree.getroot() +children = list(root) + +repo_candidates = [] +for child in children: + if local_name(child.tag) != "repository": + continue + if child.get("type") != "rpm-md" or child.get("alias") != "openruyi": + continue + source = next((node for node in child if local_name(node.tag) == "source"), None) + if source is None or source.get("path") != "obsrepositories:/": + continue + repo_candidates.append(child) + +if len(repo_candidates) != 1: + raise SystemExit("expected exactly one openruyi obsrepositories:/ repository block") + +openruyi_repo = repo_candidates[0] +repo_index = children.index(openruyi_repo) +root.remove(openruyi_repo) + +def make_repo(alias: str, path: str): + repo = ET.Element(openruyi_repo.tag, {"type": "rpm-md", "alias": alias}) + ET.SubElement(repo, "source", {"path": path}) + return repo + + +root.insert(repo_index, make_repo("openruyi", upstream_repo)) +if overlay_repo: + root.insert(repo_index + 1, make_repo("overlay", overlay_repo)) + +bootstrap_sections = [ + child for child in list(root) + if local_name(child.tag) == "packages" and child.get("type") == "bootstrap" +] +if len(bootstrap_sections) != 1: + raise SystemExit("expected exactly one bootstrap package section") + +bootstrap = bootstrap_sections[0] +ignore_names = {node.get("name") for node in bootstrap if local_name(node.tag) == "ignore"} +package_names = {node.get("name") for node in bootstrap if local_name(node.tag) == "package"} + +if "libudev-zero" not in ignore_names: + bootstrap.append(ET.Element("ignore", {"name": "libudev-zero"})) +if "systemd-udev" not in package_names: + bootstrap.append(ET.Element("package", {"name": "systemd-udev"})) + +ET.indent(tree, space=" ") +tree.write(image_kiwi_path, encoding="utf-8", xml_declaration=False) + +tree = ET.parse(image_kiwi_path) +root = tree.getroot() +repo_sources = {} +for child in list(root): + if local_name(child.tag) != "repository": + continue + source = next((node for node in child if local_name(node.tag) == "source"), None) + if source is not None: + repo_sources[child.get("alias")] = source.get("path") + +if repo_sources.get("openruyi") != upstream_repo: + raise SystemExit("openruyi repository mutation did not take effect") +if overlay_repo and repo_sources.get("overlay") != overlay_repo: + raise SystemExit("overlay repository mutation did not take effect") + +bootstrap = next( + child for child in list(root) + if local_name(child.tag) == "packages" and child.get("type") == "bootstrap" +) +ignore_names = {node.get("name") for node in bootstrap if local_name(node.tag) == "ignore"} +package_names = {node.get("name") for node in bootstrap if local_name(node.tag) == "package"} +if "libudev-zero" not in ignore_names: + raise SystemExit("bootstrap ignore injection did not take effect") +if "systemd-udev" not in package_names: + raise SystemExit("bootstrap package injection did not take effect") +PY + +if [[ ! -f "$work_dir/config.sh" ]]; then + : > "$work_dir/config.sh" +fi + +if ! grep -Fq '# openRuyi CI initrd hint' "$work_dir/config.sh"; then +cat >> "$work_dir/config.sh" <<'EOF' + +# openRuyi CI initrd hint +# Keep a stable initramfs path for KIWI image verification. + +kernel_dir=$(find /lib/modules -mindepth 1 -maxdepth 1 -type d | head -n 1 || true) +if [ -n "$kernel_dir" ]; then + kernel_version=$(basename "$kernel_dir") + initrd_hint="/boot/initramfs-${kernel_version}.img" + if [ ! -e "$initrd_hint" ]; then + : > "$initrd_hint" + fi +fi +EOF +fi + +kiwi_config_args=() +if [[ -z "$kiwi_part_mapper" ]] && [[ -r /sys/module/loop/parameters/max_part ]]; then + if [[ "$(cat /sys/module/loop/parameters/max_part)" == 0 ]]; then + kiwi_part_mapper=kpartx + fi +fi +if [[ -n "$kiwi_part_mapper" ]]; then + kiwi_config_file="$work_dir/kiwi.yml" + cat > "$kiwi_config_file" < "$target_dir/compose-inputs.env" <} +inspect_dir=$output_dir/inspect +report_file=$output_dir/POLICY_AUTH_MODEL_SUMMARY.txt +status=0 + +: >"$report_file" + +pass() { + printf '[PASS] %s\n' "$1" | tee -a "$report_file" +} + +fail() { + printf '[FAIL] %s\n' "$1" | tee -a "$report_file" >&2 + status=1 +} + +expect_group() { + local group_name=$1 + if grep -q "^${group_name}:" "$inspect_dir/group"; then + pass "group ${group_name} present" + else + fail "group ${group_name} missing" + fi +} + +check_pam_materialized() { + local pam_name=$1 + local inspect_pam=$inspect_dir/$pam_name + local inspect_authselect=$inspect_dir/authselect-$pam_name + + if [[ -s "$inspect_pam" ]]; then + pass "$pam_name materialized" + elif [[ -s "$inspect_authselect" ]]; then + pass "$pam_name materialized via /etc/authselect" + else + fail "$pam_name missing" + fi +} + +if [[ ! -f "$inspect_dir/passwd" ]]; then + fail "inspect/passwd missing" + exit 1 +fi + +if [[ ! -f "$inspect_dir/group" ]]; then + fail "inspect/group missing" + exit 1 +fi + +root_line=$(grep '^root:' "$inspect_dir/passwd" || true) +openruyi_line=$(grep '^openruyi:' "$inspect_dir/passwd" || true) + +if [[ "$root_line" == *":/bin/bash" ]]; then + pass "root shell is /bin/bash" +else + fail "root shell mismatch: ${root_line:-missing}" +fi + +if [[ -n "$openruyi_line" ]]; then + IFS=: read -r _ _ openruyi_uid _ _ openruyi_home openruyi_shell <<<"$openruyi_line" + if [[ "$openruyi_uid" != 0 ]]; then + pass "openruyi uid is non-root" + else + fail "openruyi uid is root" + fi + if [[ "$openruyi_home" == "/home/openruyi" ]]; then + pass "openruyi home is /home/openruyi" + else + fail "openruyi home mismatch: ${openruyi_home:-missing}" + fi + if [[ "$openruyi_shell" == "/bin/bash" ]]; then + pass "openruyi shell is /bin/bash" + else + fail "openruyi shell mismatch: ${openruyi_shell:-missing}" + fi +else + fail "openruyi entry missing" +fi + +if [[ -f "$inspect_dir/authselect-current-raw.rc" ]]; then + authselect_rc=$(tr -d '\n' <"$inspect_dir/authselect-current-raw.rc") + if [[ "$authselect_rc" == 0 ]]; then + current_profile=$(tr -d '\n' <"$inspect_dir/authselect-current-raw.txt") + if [[ "$current_profile" == openruyi-local* ]]; then + pass "authselect current profile is $current_profile" + else + fail "authselect current profile mismatch: ${current_profile:-empty}" + fi + else + fail "authselect inspection command failed with rc=$authselect_rc" + fi +else + fail "authselect inspection rc missing" +fi + +for pam_name in authselect-system-auth authselect-password-auth; do + pam_file=$inspect_dir/$pam_name + if [[ -s "$pam_file" ]]; then + if grep -q '^# Generated by authselect' "$pam_file"; then + pass "$pam_name generated by authselect" + else + fail "$pam_name content mismatch" + fi + else + fail "$pam_name missing" + fi +done + +for pam_name in system-auth password-auth; do + check_pam_materialized "$pam_name" +done + +expect_group adm +expect_group wheel +expect_group users + +if [[ $status -eq 0 ]]; then + printf 'Policy auth-model verification passed: %s\n' "$output_dir" | tee -a "$report_file" +else + printf 'Policy auth-model verification failed: %s\n' "$output_dir" | tee -a "$report_file" >&2 +fi + +exit "$status" diff --git a/.github/testsuite/smoke/installiso/verify-output.sh b/.github/testsuite/smoke/installiso/verify-output.sh new file mode 100644 index 0000000000..805a78002c --- /dev/null +++ b/.github/testsuite/smoke/installiso/verify-output.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +set -euo pipefail + +output_dir=${1:?usage: verify-output.sh } +inspect_dir=$output_dir/inspect +report_file=$output_dir/SMOKE_SUMMARY.txt +expect_setup_source_pattern=${EXPECT_SETUP_SOURCE_PATTERN:-${EXPECT_OVERLAY_SOURCE_PATTERN:-}} +status=0 + +if [[ -f "$inspect_dir/build.env" ]]; then + # shellcheck disable=SC1090 + source "$inspect_dir/build.env" +fi + +if [[ -z "$expect_setup_source_pattern" ]] && [[ -n "${OVERLAY_REPO:-}" ]]; then + if [[ "$OVERLAY_REPO" == https://repo.build.openruyi.cn/* ]]; then + expect_setup_source_pattern=${OVERLAY_REPO#https://repo.build.openruyi.cn/} + expect_setup_source_pattern=${expect_setup_source_pattern%/} + expect_setup_source_pattern=${expect_setup_source_pattern%/x86_64} + expect_setup_source_pattern=${expect_setup_source_pattern//:\//:} + fi +fi + +: >"$report_file" + +pass() { + printf '[PASS] %s\n' "$1" | tee -a "$report_file" +} + +fail() { + printf '[FAIL] %s\n' "$1" | tee -a "$report_file" >&2 + status=1 +} + +resolve_artifact() { + local __var=$1 + local pattern=$2 + local label=$3 + local artifact + + artifact=$(find "$output_dir" -maxdepth 1 -type f -name "$pattern" | sort | head -n 1 || true) + if [[ -n "$artifact" ]]; then + pass "$label present" + else + fail "$label missing ($pattern)" + fi + printf -v "$__var" '%s' "$artifact" +} + +require_file() { + local path=$1 + local label=$2 + if [[ -f "$path" ]]; then + pass "$label present" + else + fail "$label missing: $path" + fi +} + +resolve_artifact qcow2_path '*.qcow2' 'qcow2 image' +resolve_artifact iso_path '*.install.iso' 'install ISO' +resolve_artifact packages_path '*.packages' 'package manifest' +resolve_artifact prepared_kiwi_path 'prepared-image.kiwi' 'prepared image description' +resolve_artifact compose_inputs_path 'compose-inputs.env' 'compose inputs' + +require_file "$inspect_dir/passwd" "inspect/passwd" +require_file "$inspect_dir/group" "inspect/group" +require_file "$inspect_dir/build.env" "inspect/build.env" +require_file "$inspect_dir/rpm-query.rc" "inspect/rpm-query.rc" +require_file "$inspect_dir/authselect-current-raw.rc" "inspect/authselect-current-raw.rc" + +if [[ -n "$compose_inputs_path" ]]; then + if grep -q '^TARGET_ARCH=x86_64$' "$compose_inputs_path"; then + pass "compose inputs are scoped to x86_64" + else + fail "compose inputs target arch mismatch" + fi + if grep -q '^BUILD_PLATFORM=linux/amd64$' "$compose_inputs_path"; then + pass "compose inputs are scoped to linux/amd64" + else + fail "compose inputs build platform mismatch" + fi + if grep -q '^KIWI_SOURCE_COMMIT=' "$compose_inputs_path"; then + pass "compose inputs record kiwi source commit" + else + fail "compose inputs missing kiwi source commit" + fi + if grep -q '^BUILDER_BASE_IMAGE=' "$compose_inputs_path"; then + pass "compose inputs record builder base image" + else + fail "compose inputs missing builder base image" + fi +fi + +if [[ -f "$output_dir/OVERLAY_PROVENANCE.txt" ]]; then + pass "overlay provenance present" +else + fail "overlay provenance missing" +fi + +if [[ -f "$output_dir/upstream-repomd.xml" ]]; then + pass "upstream repomd captured" +else + fail "upstream repomd missing" +fi + +if [[ -n "$packages_path" ]]; then + if grep -q '^authselect|' "$packages_path"; then + pass "authselect installed" + else + fail "authselect missing from package manifest" + fi + + if grep -q '^openruyi-authselect-profiles|' "$packages_path"; then + pass "openruyi-authselect-profiles installed" + else + fail "openruyi-authselect-profiles missing from package manifest" + fi + + if grep -q '^setup|' "$packages_path"; then + pass "setup installed" + else + fail "setup missing from package manifest" + fi + + if [[ -n "$expect_setup_source_pattern" ]]; then + setup_line=$(grep '^setup|' "$packages_path" || true) + if printf '%s\n' "$setup_line" | grep -Fq "$expect_setup_source_pattern"; then + pass "setup came from $expect_setup_source_pattern" + else + fail "setup source mismatch: ${setup_line:-missing}" + fi + fi +fi + +if [[ -f "$inspect_dir/rpm-query.rc" ]]; then + rpm_query_rc=$(tr -d '\n' <"$inspect_dir/rpm-query.rc") + if [[ "$rpm_query_rc" == 0 ]]; then + pass "rpm query inspection succeeded" + else + fail "rpm query inspection failed with rc=$rpm_query_rc" + fi +fi + +if [[ -f "$inspect_dir/authselect-current-raw.rc" ]]; then + authselect_rc=$(tr -d '\n' <"$inspect_dir/authselect-current-raw.rc") + if [[ "$authselect_rc" =~ ^[0-9]+$ ]]; then + pass "authselect inspection rc captured ($authselect_rc)" + else + fail "authselect inspection rc invalid" + fi +fi + +if [[ -n "$qcow2_path" ]] && command -v qemu-img >/dev/null 2>&1; then + qemu-img info "$qcow2_path" >"$inspect_dir/qemu-img-info.txt" + pass "qemu-img info captured" +fi + +if [[ -n "$qcow2_path" ]] && [[ -n "$iso_path" ]] && command -v file >/dev/null 2>&1; then + file "$iso_path" "$qcow2_path" >"$inspect_dir/file-output.txt" + pass "file(1) output captured" +fi + +if [[ $status -eq 0 ]]; then + printf 'Smoke verification passed: %s\n' "$output_dir" | tee -a "$report_file" +else + printf 'Smoke verification failed: %s\n' "$output_dir" | tee -a "$report_file" >&2 +fi + +exit "$status" From 82ec38c7b318e51e69972c4fa76a47e281a159a4 Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 10:24:26 +0800 Subject: [PATCH 2/6] .github: build: Add package-gated KIWI verification Signed-off-by: Jingwiw --- .github/workflows/build.yaml | 179 ++++++++++++++++++++++++++++++++--- 1 file changed, 167 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5b4ab49054..f38e6b3536 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -24,6 +24,12 @@ concurrency: jobs: build: runs-on: [ubuntu-latest] + outputs: + changed_packages: ${{ steps.package-gates.outputs.changed_packages }} + kiwi_trigger_packages: ${{ steps.package-gates.outputs.kiwi_trigger_packages }} + permission_trigger_packages: ${{ steps.package-gates.outputs.permission_trigger_packages }} + needs_kiwi: ${{ steps.package-gates.outputs.needs_kiwi }} + needs_permission_check: ${{ steps.package-gates.outputs.needs_permission_check }} steps: - uses: actions/checkout@v3 with: @@ -35,6 +41,52 @@ jobs: files_yaml: | specs: - SPECS/** + - name: derive package gates + id: package-gates + env: + CHANGED_SPEC_FILES: ${{ steps.changed-files.outputs.specs_all_changed_files }} + run: | + set -euo pipefail + + changed_packages='' + kiwi_trigger_packages='' + permission_trigger_packages='' + + if [[ "${{ steps.changed-files.outputs.specs_any_changed }}" == 'true' ]]; then + changed_packages="$( + printf '%s\n' $CHANGED_SPEC_FILES | bash ./.github/common/list-changed-spec-packages.sh + )" + kiwi_trigger_packages="$( + printf '%s\n' "$changed_packages" | bash ./.github/common/match-package-list.sh ./.github/image-build/kiwi-installiso/trigger-packages.txt || true + )" + permission_trigger_packages="$( + printf '%s\n' "$changed_packages" | bash ./.github/common/match-package-list.sh ./.github/testsuite/policy/auth-model/trigger-packages.txt || true + )" + fi + + { + echo 'changed_packages<> "$GITHUB_OUTPUT" + + if [[ -n "$kiwi_trigger_packages" ]]; then + echo 'needs_kiwi=true' >> "$GITHUB_OUTPUT" + else + echo 'needs_kiwi=false' >> "$GITHUB_OUTPUT" + fi + + if [[ -n "$permission_trigger_packages" ]]; then + echo 'needs_permission_check=true' >> "$GITHUB_OUTPUT" + else + echo 'needs_permission_check=false' >> "$GITHUB_OUTPUT" + fi - name: cache id: cache uses: actions/cache@v4 @@ -42,9 +94,20 @@ jobs: path: | SPECS/.pbuild SPECS/_build.x86_64 - key: ${{ runner.os }}-${{ hashFiles('.github/build/_config') }} + key: ${{ runner.os }}-${{ hashFiles('.github/build/**') }} restore-keys: | ${{ runner.os }}- + - name: Reset cached package result directories + if: steps.changed-files.outputs.specs_any_changed == 'true' + env: + CHANGED_PACKAGES: ${{ steps.package-gates.outputs.changed_packages }} + run: | + set -euo pipefail + + while IFS= read -r package; do + [[ -n "$package" ]] || continue + rm -rf "SPECS/_build.x86_64/$package" + done <<< "$CHANGED_PACKAGES" - name: Install tools run: | echo "deb http://download.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_24.04/ /" | sudo tee /etc/apt/sources.list.d/obs.list @@ -55,28 +118,31 @@ jobs: sudo patch --directory=/usr/lib/build --strip=1 -i $(pwd)/.github/build/pbuild.patch - name: Limit the number of compilations if: steps.changed-files.outputs.specs_any_changed == 'true' + env: + CHANGED_PACKAGES: ${{ steps.package-gates.outputs.changed_packages }} run: | set -x - all_file="${{ steps.changed-files.outputs.specs_all_changed_files }}" - for i in $all_file; do - p=$(basename $(dirname $i)) - echo $p - echo "BuildFlags: onlybuild:$p" >> ./.github/build/_config - done + while IFS= read -r package; do + [[ -n "$package" ]] || continue + echo "$package" + echo "BuildFlags: onlybuild:$package" >> ./.github/build/_config + done <<< "$CHANGED_PACKAGES" - name: Build package(s) + if: steps.changed-files.outputs.specs_any_changed == 'true' run: (cp .github/build/* SPECS && cd SPECS && (sudo pbuild --vm-type=chroot --preset x86_64 --showlog --root=/tmp/b || (sudo pbuild --preset x86_64 --result && exit 1))) - name: get result id: result if: steps.changed-files.outputs.specs_any_changed == 'true' + env: + CHANGED_PACKAGES: ${{ steps.package-gates.outputs.changed_packages }} run: | set -x - all_file="${{ steps.changed-files.outputs.specs_all_changed_files }}" { echo 'paths<> "$GITHUB_OUTPUT" - uses: actions/upload-artifact@v4 @@ -84,3 +150,92 @@ jobs: name: PR${{ github.event.pull_request.number }}-build-packages-results path: ${{ steps.result.outputs.paths }} if-no-files-found: error + + kiwi_installiso_verify: + runs-on: [ubuntu-latest] + needs: build + if: needs.build.outputs.needs_kiwi == 'true' + timeout-minutes: 120 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/download-artifact@v4 + with: + name: PR${{ github.event.pull_request.number }}-build-packages-results + path: ./.ci/pbuild-results + - name: Install tools + run: | + sudo apt update + sudo apt install createrepo-c qemu-utils file git curl -y + - name: Build overlay rpm-md repo + run: | + bash ./.github/common/make-local-rpm-repo.sh ./.ci/pbuild-results ./.ci/local-rpm-repo + - name: Resolve compose inputs + env: + PROFILE: installiso + TARGET_ARCH: x86_64 + BUILD_PLATFORM: linux/amd64 + UPSTREAM_REPO: https://repo.build.openruyi.cn/openruyi/x86_64/ + BUILDER_BASE_IMAGE: docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d + KIWI_SOURCE_COMMIT: a602fe1d73adeab4cb17078f5fac7d678ff5269b + run: | + set -euo pipefail + mkdir -p ./.ci/compose-inputs + curl -fsSL "${UPSTREAM_REPO%/}/repodata/repomd.xml" -o ./.ci/compose-inputs/upstream-repomd.xml + upstream_repomd_sha256=$(sha256sum ./.ci/compose-inputs/upstream-repomd.xml | awk '{print $1}') + { + echo "PROFILE=$PROFILE" + echo "TARGET_ARCH=$TARGET_ARCH" + echo "BUILD_PLATFORM=$BUILD_PLATFORM" + echo "UPSTREAM_REPO=$UPSTREAM_REPO" + echo "UPSTREAM_REPOMD_URL=${UPSTREAM_REPO%/}/repodata/repomd.xml" + echo "UPSTREAM_REPOMD_SHA256=$upstream_repomd_sha256" + echo "BUILDER_BASE_IMAGE=$BUILDER_BASE_IMAGE" + echo "KIWI_SOURCE_COMMIT=$KIWI_SOURCE_COMMIT" + } > ./.ci/compose-inputs/compose-inputs.env + - name: Fetch official kiwi image repository + env: + KIWI_REPO_URL: https://git.openruyi.cn/openRuyi/openruyi-kiwi-image.git + KIWI_SOURCE_REF: obs + KIWI_SOURCE_COMMIT: a602fe1d73adeab4cb17078f5fac7d678ff5269b + run: | + set -euo pipefail + git clone --depth 1 --branch "$KIWI_SOURCE_REF" "$KIWI_REPO_URL" ./.ci/openruyi-kiwi-image + actual_commit=$(git -C ./.ci/openruyi-kiwi-image rev-parse HEAD) + if [[ "$actual_commit" != "$KIWI_SOURCE_COMMIT" ]]; then + echo "expected KIWI repo commit $KIWI_SOURCE_COMMIT, got $actual_commit from $KIWI_SOURCE_REF" >&2 + exit 1 + fi + - name: Build and inspect installiso from overlay repo + run: | + set -euo pipefail + # shellcheck disable=SC1091 + source ./.ci/compose-inputs/compose-inputs.env + export PROFILE TARGET_ARCH BUILD_PLATFORM UPSTREAM_REPO UPSTREAM_REPOMD_SHA256 BUILDER_BASE_IMAGE KIWI_SOURCE_COMMIT + bash ./.github/image-build/kiwi-installiso/build-and-inspect.sh ./.ci/openruyi-kiwi-image ./.ci/local-rpm-repo ./.ci/out-installiso + cp ./.ci/compose-inputs/upstream-repomd.xml ./.ci/out-installiso/upstream-repomd.xml + - name: Verify installiso smoke suite + run: | + bash ./.github/testsuite/smoke/installiso/verify-output.sh ./.ci/out-installiso + - name: Initialize auth-model policy report + run: | + printf 'Policy auth-model verification skipped: no matching package change\n' > ./.ci/out-installiso/POLICY_AUTH_MODEL_SUMMARY.txt + - name: Verify auth-model policy suite + if: needs.build.outputs.needs_permission_check == 'true' + run: | + bash ./.github/testsuite/policy/auth-model/verify.sh ./.ci/out-installiso + - uses: actions/upload-artifact@v4 + with: + name: PR${{ github.event.pull_request.number }}-kiwi-installiso-verify + path: | + ./.ci/out-installiso/SMOKE_SUMMARY.txt + ./.ci/out-installiso/POLICY_AUTH_MODEL_SUMMARY.txt + ./.ci/out-installiso/compose-inputs.env + ./.ci/out-installiso/prepared-image.kiwi + ./.ci/out-installiso/prepared-config.sh + ./.ci/out-installiso/OVERLAY_PROVENANCE.txt + ./.ci/out-installiso/upstream-repomd.xml + ./.ci/out-installiso/*.packages + ./.ci/out-installiso/inspect/ + if-no-files-found: error From 799039345f6956c13e6f0f26e8389dd556de10a1 Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 10:24:27 +0800 Subject: [PATCH 3/6] .github: build: Self-test KIWI workflow helpers Signed-off-by: Jingwiw --- .../smoke/helpers/verify-helper-contracts.sh | 145 ++++++++++++++++++ .github/workflows/ci-selftest.yaml | 46 ++++++ 2 files changed, 191 insertions(+) create mode 100644 .github/testsuite/smoke/helpers/verify-helper-contracts.sh create mode 100644 .github/workflows/ci-selftest.yaml diff --git a/.github/testsuite/smoke/helpers/verify-helper-contracts.sh b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh new file mode 100644 index 0000000000..e4ee46675b --- /dev/null +++ b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root=$(CDPATH= cd -- "$(dirname -- "$0")/../../../.." && pwd) +tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/openruyi-kiwi-helper-tests.XXXXXX") +status=0 + +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT INT TERM + +pass() { + printf '[PASS] %s\n' "$1" +} + +fail() { + printf '[FAIL] %s\n' "$1" >&2 + status=1 +} + +assert_contains() { + local file=$1 + local pattern=$2 + local label=$3 + if grep -Fq "$pattern" "$file"; then + pass "$label" + else + fail "$label" + fi +} + +assert_not_contains() { + local file=$1 + local pattern=$2 + local label=$3 + if grep -Fq "$pattern" "$file"; then + fail "$label" + else + pass "$label" + fi +} + +build_workflow=$repo_root/.github/workflows/build.yaml +selftest_workflow=$repo_root/.github/workflows/ci-selftest.yaml +build_and_inspect=$repo_root/.github/image-build/kiwi-installiso/build-and-inspect.sh +build_image=$repo_root/.github/image-build/kiwi-installiso/build-image.sh +make_local_repo=$repo_root/.github/common/make-local-rpm-repo.sh +smoke_verify=$repo_root/.github/testsuite/smoke/installiso/verify-output.sh + +assert_contains "$build_workflow" " - 'SPECS/**'" "build workflow watches SPECS paths" +assert_not_contains "$build_workflow" ".github/common/**" "build workflow no longer watches helper-only changes" +assert_contains "$selftest_workflow" ".github/common/**" "selftest workflow watches helper changes" +assert_contains "$selftest_workflow" ".github/image-build/**" "selftest workflow watches image helper changes" +assert_contains "$selftest_workflow" ".github/testsuite/**" "selftest workflow watches testsuite changes" +assert_contains "$build_and_inspect" '-e CONTAINER_NAME="$container_name"' "build-and-inspect passes CONTAINER_NAME into container" +assert_contains "$build_and_inspect" 'CONTAINER_NAME=$CONTAINER_NAME' "build-and-inspect writes CONTAINER_NAME from container env" +assert_contains "$build_and_inspect" 'UPSTREAM_REPOMD_SHA256' "build-and-inspect records upstream repomd checksum" +assert_contains "$build_and_inspect" 'BUILD_PLATFORM=' "build-and-inspect uses explicit build platform" +assert_not_contains "$smoke_verify" "root shell is" "smoke suite no longer contains shell policy checks" +assert_not_contains "$smoke_verify" "authselect current profile is" "smoke suite no longer contains auth profile policy checks" + +mkdir -p "$tmp_dir/bin" "$tmp_dir/image" "$tmp_dir/target" "$tmp_dir/artifacts/a" "$tmp_dir/artifacts/b" + +cat >"$tmp_dir/bin/kiwi-ng" <"$tmp_dir/kiwi-args.log" +exit 0 +EOF +chmod +x "$tmp_dir/bin/kiwi-ng" + +cat >"$tmp_dir/image/image.kiwi" <<'EOF' + + + + + + + + + + + +EOF + +: >"$tmp_dir/image/config.sh" + +PATH="$tmp_dir/bin:$PATH" \ +SUDO= \ +PROFILE=installiso \ +TARGET_ARCH=x86_64 \ +BUILD_PLATFORM=linux/amd64 \ +UPSTREAM_REPO=https://repo.build.openruyi.cn/openruyi/x86_64/ \ +OVERLAY_REPO=file:///overlay/ \ +KIWI_SOURCE_COMMIT=test-commit \ +BUILDER_BASE_IMAGE=docker.io/example/builder@sha256:test \ +bash "$build_image" "$tmp_dir/image" "$tmp_dir/target" + +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'alias="openruyi"' "prepared image keeps openruyi repo" +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'path="https://repo.build.openruyi.cn/openruyi/x86_64/"' "prepared image points openruyi repo at upstream" +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'alias="overlay"' "prepared image adds overlay repo" +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'path="file:///overlay/"' "prepared image points overlay repo at overlay path" +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'name="libudev-zero"' "prepared image injects libudev-zero ignore" +assert_contains "$tmp_dir/target/prepared-image.kiwi" 'name="systemd-udev"' "prepared image injects systemd-udev bootstrap package" +assert_contains "$tmp_dir/target/prepared-config.sh" 'openRuyi CI initrd hint' "prepared config appends CI initrd hint" +assert_contains "$tmp_dir/target/compose-inputs.env" 'TARGET_ARCH=x86_64' "prepared compose inputs record x86_64" +assert_contains "$tmp_dir/target/compose-inputs.env" 'BUILD_PLATFORM=linux/amd64' "prepared compose inputs record build platform" + +if PATH="$tmp_dir/bin:$PATH" \ + SUDO= \ + TARGET_ARCH=aarch64 \ + BUILD_PLATFORM=linux/arm64 \ + bash "$build_image" "$tmp_dir/image" "$tmp_dir/target" >/dev/null 2>&1; then + fail "build-image rejects unsupported arch" +else + pass "build-image rejects unsupported arch" +fi + +cat >"$tmp_dir/bin/createrepo_c" <"$tmp_dir/artifacts/a/pkg-1-1.noarch.rpm" +: >"$tmp_dir/artifacts/b/pkg-1-1.noarch.rpm" +if PATH="$tmp_dir/bin:$PATH" bash "$make_local_repo" "$tmp_dir/artifacts" "$tmp_dir/repo-dup" >/dev/null 2>&1; then + fail "make-local-rpm-repo detects duplicate basenames" +else + pass "make-local-rpm-repo detects duplicate basenames" +fi + +rm -rf "$tmp_dir/artifacts" "$tmp_dir/repo-ok" +mkdir -p "$tmp_dir/artifacts/a" "$tmp_dir/artifacts/b" +: >"$tmp_dir/artifacts/a/pkg-a-1-1.noarch.rpm" +: >"$tmp_dir/artifacts/b/pkg-b-1-1.noarch.rpm" +PATH="$tmp_dir/bin:$PATH" bash "$make_local_repo" "$tmp_dir/artifacts" "$tmp_dir/repo-ok" +if [[ -f "$tmp_dir/repo-ok/PROVENANCE.txt" ]] && [[ -d "$tmp_dir/repo-ok/repodata" ]]; then + pass "make-local-rpm-repo writes provenance and repo metadata" +else + fail "make-local-rpm-repo writes provenance and repo metadata" +fi + +exit "$status" diff --git a/.github/workflows/ci-selftest.yaml b/.github/workflows/ci-selftest.yaml new file mode 100644 index 0000000000..17c3929f20 --- /dev/null +++ b/.github/workflows/ci-selftest.yaml @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: (C) 2025 Institute of Software, Chinese Academy of Sciences (ISCAS) +# SPDX-FileCopyrightText: (C) 2025 openRuyi Project Contributors +# +# SPDX-License-Identifier: MulanPSL-2.0 + +name: ci selftest + +permissions: + contents: read + +on: + pull_request: + branches: [main, ci-test] + types: [opened, synchronize] + paths: + - '.github/build/**' + - '.github/common/**' + - '.github/image-build/**' + - '.github/testsuite/**' + - '.github/workflows/build.yaml' + - '.github/workflows/ci-selftest.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + helper_selftest: + runs-on: [ubuntu-latest] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Syntax check shell helpers + run: | + find .github -type f -name '*.sh' -print0 | xargs -0 -n 1 bash -n + - name: Validate workflow YAML + run: | + ruby -e 'require "yaml"; ARGV.each { |path| YAML.safe_load(File.read(path), aliases: true) }' \ + .github/workflows/build.yaml \ + .github/workflows/ci-selftest.yaml \ + .github/workflows/pre-commit.yml \ + .github/workflows/update-package.yaml + - name: Verify helper contracts + run: | + bash ./.github/testsuite/smoke/helpers/verify-helper-contracts.sh From 65f8dfe6ae18b5f2056aa0e733cdae0a039cd520 Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 14:30:35 +0800 Subject: [PATCH 4/6] .github: build: Switch KIWI verification to openRuyi builder Signed-off-by: Jingwiw --- .../kiwi-installiso/Dockerfile.builder | 16 +++++++++++----- .../kiwi-installiso/build-and-inspect.sh | 2 +- .../image-build/kiwi-installiso/build-image.sh | 2 +- .../smoke/helpers/verify-helper-contracts.sh | 3 +++ .github/workflows/build.yaml | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/image-build/kiwi-installiso/Dockerfile.builder b/.github/image-build/kiwi-installiso/Dockerfile.builder index a765c32e77..b2c72084cd 100644 --- a/.github/image-build/kiwi-installiso/Dockerfile.builder +++ b/.github/image-build/kiwi-installiso/Dockerfile.builder @@ -1,8 +1,14 @@ -ARG BASE_IMAGE=docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d -FROM --platform=linux/amd64 ${BASE_IMAGE} +ARG BASE_IMAGE=git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e +FROM ${BASE_IMAGE} -RUN zypper --non-interactive refresh && \ - zypper --non-interactive install -y bash curl dnf5 kiwi-systemdeps perl python3 python3-kiwi sudo && \ - zypper clean -a +RUN dnf5 install -y \ + bash \ + curl \ + kiwi \ + kiwi-systemdeps \ + python3 \ + python3-kiwi \ + sudo && \ + dnf5 clean all WORKDIR /work diff --git a/.github/image-build/kiwi-installiso/build-and-inspect.sh b/.github/image-build/kiwi-installiso/build-and-inspect.sh index 853ae9bc4c..954f697fd7 100644 --- a/.github/image-build/kiwi-installiso/build-and-inspect.sh +++ b/.github/image-build/kiwi-installiso/build-and-inspect.sh @@ -24,7 +24,7 @@ fi upstream_repo=${UPSTREAM_REPO:-https://repo.build.openruyi.cn/openruyi/x86_64/} upstream_repomd_sha256=${UPSTREAM_REPOMD_SHA256:-} kiwi_source_commit=${KIWI_SOURCE_COMMIT:-unknown} -builder_base_image=${BUILDER_BASE_IMAGE:-docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d} +builder_base_image=${BUILDER_BASE_IMAGE:-git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e} builder_image=${BUILDER_IMAGE:-openruyi-kiwi-builder:ci} build_dir_in_container=${BUILD_DIR_IN_CONTAINER:-/var/tmp/openruyi-${profile}-ci} container_name=${CONTAINER_NAME:-kiwi-ci-${profile}-${GITHUB_RUN_ID:-$$}} diff --git a/.github/image-build/kiwi-installiso/build-image.sh b/.github/image-build/kiwi-installiso/build-image.sh index 0764eb4576..71c4cb540f 100644 --- a/.github/image-build/kiwi-installiso/build-image.sh +++ b/.github/image-build/kiwi-installiso/build-image.sh @@ -26,7 +26,7 @@ upstream_repo=${UPSTREAM_REPO:-${MAIN_REPO:-$default_upstream_repo}} overlay_repo=${OVERLAY_REPO:-${FIX_REPO:-}} upstream_repomd_url=${UPSTREAM_REPOMD_URL:-${upstream_repo%/}/repodata/repomd.xml} upstream_repomd_sha256=${UPSTREAM_REPOMD_SHA256:-} -builder_base_image=${BUILDER_BASE_IMAGE:-docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d} +builder_base_image=${BUILDER_BASE_IMAGE:-git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e} kiwi_source_commit=${KIWI_SOURCE_COMMIT:-unknown} sudo_cmd=${SUDO-sudo} kiwi_part_mapper=${KIWI_PART_MAPPER:-} diff --git a/.github/testsuite/smoke/helpers/verify-helper-contracts.sh b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh index e4ee46675b..60c9523a9b 100644 --- a/.github/testsuite/smoke/helpers/verify-helper-contracts.sh +++ b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh @@ -43,6 +43,7 @@ assert_not_contains() { build_workflow=$repo_root/.github/workflows/build.yaml selftest_workflow=$repo_root/.github/workflows/ci-selftest.yaml +builder_dockerfile=$repo_root/.github/image-build/kiwi-installiso/Dockerfile.builder build_and_inspect=$repo_root/.github/image-build/kiwi-installiso/build-and-inspect.sh build_image=$repo_root/.github/image-build/kiwi-installiso/build-image.sh make_local_repo=$repo_root/.github/common/make-local-rpm-repo.sh @@ -53,10 +54,12 @@ assert_not_contains "$build_workflow" ".github/common/**" "build workflow no lon assert_contains "$selftest_workflow" ".github/common/**" "selftest workflow watches helper changes" assert_contains "$selftest_workflow" ".github/image-build/**" "selftest workflow watches image helper changes" assert_contains "$selftest_workflow" ".github/testsuite/**" "selftest workflow watches testsuite changes" +assert_contains "$builder_dockerfile" "git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e" "builder defaults to openRuyi creek base" assert_contains "$build_and_inspect" '-e CONTAINER_NAME="$container_name"' "build-and-inspect passes CONTAINER_NAME into container" assert_contains "$build_and_inspect" 'CONTAINER_NAME=$CONTAINER_NAME' "build-and-inspect writes CONTAINER_NAME from container env" assert_contains "$build_and_inspect" 'UPSTREAM_REPOMD_SHA256' "build-and-inspect records upstream repomd checksum" assert_contains "$build_and_inspect" 'BUILD_PLATFORM=' "build-and-inspect uses explicit build platform" +assert_contains "$build_image" 'builder_base_image=${BUILDER_BASE_IMAGE:-git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e}' "build-image defaults to openRuyi creek base" assert_not_contains "$smoke_verify" "root shell is" "smoke suite no longer contains shell policy checks" assert_not_contains "$smoke_verify" "authselect current profile is" "smoke suite no longer contains auth profile policy checks" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f38e6b3536..1675541ca9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -177,7 +177,7 @@ jobs: TARGET_ARCH: x86_64 BUILD_PLATFORM: linux/amd64 UPSTREAM_REPO: https://repo.build.openruyi.cn/openruyi/x86_64/ - BUILDER_BASE_IMAGE: docker.io/opensuse/tumbleweed@sha256:ef83be77fac5207611adab5407f6c8b0ca5dd4f1924ad30682f53e807dd13f3d + BUILDER_BASE_IMAGE: git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e KIWI_SOURCE_COMMIT: a602fe1d73adeab4cb17078f5fac7d678ff5269b run: | set -euo pipefail From 9b21d3b6d1f172370937b8037ac6149e582b8b23 Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 14:31:46 +0800 Subject: [PATCH 5/6] .github: build: Vendor KIWI validation image Signed-off-by: Jingwiw --- .../kiwi-installiso/build-and-inspect.sh | 2 +- .../kiwi-installiso/build-image.sh | 2 +- .../kiwi-installiso/description/config.sh | 9 ++ .../kiwi-installiso/description/image.kiwi | 83 +++++++++++++++++++ .../description/root/etc/grub.d/28_blsuki | 15 ++++ .../description/root/etc/hostname | 1 + .../description/root/etc/kernel/cmdline | 1 + .../description/root/etc/kernel/entry-token | 1 + .../description/root/etc/kernel/install.conf | 1 + .../root/etc/systemd/timesyncd.conf | 3 + .../91-other-fallback-install-kernel.install | 36 ++++++++ .../kiwi-installiso/trigger-packages.txt | 12 +-- .../policy/auth-model/trigger-packages.txt | 3 +- .../smoke/helpers/verify-helper-contracts.sh | 6 +- .../smoke/installiso/verify-output.sh | 70 +++++++++++++++- .github/workflows/build.yaml | 55 +++++------- 16 files changed, 249 insertions(+), 51 deletions(-) create mode 100644 .github/image-build/kiwi-installiso/description/config.sh create mode 100644 .github/image-build/kiwi-installiso/description/image.kiwi create mode 100755 .github/image-build/kiwi-installiso/description/root/etc/grub.d/28_blsuki create mode 100644 .github/image-build/kiwi-installiso/description/root/etc/hostname create mode 100644 .github/image-build/kiwi-installiso/description/root/etc/kernel/cmdline create mode 100644 .github/image-build/kiwi-installiso/description/root/etc/kernel/entry-token create mode 100644 .github/image-build/kiwi-installiso/description/root/etc/kernel/install.conf create mode 100644 .github/image-build/kiwi-installiso/description/root/etc/systemd/timesyncd.conf create mode 100755 .github/image-build/kiwi-installiso/description/root/usr/lib/kernel/install.d/91-other-fallback-install-kernel.install diff --git a/.github/image-build/kiwi-installiso/build-and-inspect.sh b/.github/image-build/kiwi-installiso/build-and-inspect.sh index 954f697fd7..6fb995170c 100644 --- a/.github/image-build/kiwi-installiso/build-and-inspect.sh +++ b/.github/image-build/kiwi-installiso/build-and-inspect.sh @@ -6,7 +6,7 @@ overlay_repo_dir=${2:?usage: build-and-inspect.sh } script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) -profile=${PROFILE:-installiso} +profile=${PROFILE:-validation} target_arch=${TARGET_ARCH:-x86_64} build_platform=${BUILD_PLATFORM:-linux/amd64} case "$target_arch" in diff --git a/.github/image-build/kiwi-installiso/build-image.sh b/.github/image-build/kiwi-installiso/build-image.sh index 71c4cb540f..cea9fdeb91 100644 --- a/.github/image-build/kiwi-installiso/build-image.sh +++ b/.github/image-build/kiwi-installiso/build-image.sh @@ -4,7 +4,7 @@ set -euo pipefail image_repo_dir=${1:?usage: build-image.sh } target_dir=${2:?usage: build-image.sh } -profile=${PROFILE:-installiso} +profile=${PROFILE:-validation} target_arch=${TARGET_ARCH:-x86_64} build_platform=${BUILD_PLATFORM:-linux/amd64} case "$target_arch" in diff --git a/.github/image-build/kiwi-installiso/description/config.sh b/.github/image-build/kiwi-installiso/description/config.sh new file mode 100644 index 0000000000..4a1d470f54 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/config.sh @@ -0,0 +1,9 @@ +set -eux +test -f /.kconfig && . /.kconfig +test -f /.profile && . /.profile + +baseService sshd.service on +baseService sshd.socket off +baseService NetworkManager.service on +systemctl preset-all +update-ca-trust diff --git a/.github/image-build/kiwi-installiso/description/image.kiwi b/.github/image-build/kiwi-installiso/description/image.kiwi new file mode 100644 index 0000000000..1f3b80d2f1 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/image.kiwi @@ -0,0 +1,83 @@ + + + + zheng junjie + zhengjunjie@iscas.ac.cn + openRuyi validation image + + + + + + + + + + + + + 0.0.1 + dnf5 + us + UTC + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.github/image-build/kiwi-installiso/description/root/etc/grub.d/28_blsuki b/.github/image-build/kiwi-installiso/description/root/etc/grub.d/28_blsuki new file mode 100755 index 0000000000..2866797b4c --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/grub.d/28_blsuki @@ -0,0 +1,15 @@ +#! /bin/sh +set -e +. "$pkgdatadir/grub-mkconfig_lib" + +for entries_dir in /boot /boot/efi; do + if [ -d "$entries_dir"/loader/entries ]; then + + cat << EOF +insmod blsuki +search --set root -u $(grub-probe $entries_dir --target=fs_uuid) +blscfg -p /loader/entries +EOF + + fi +done diff --git a/.github/image-build/kiwi-installiso/description/root/etc/hostname b/.github/image-build/kiwi-installiso/description/root/etc/hostname new file mode 100644 index 0000000000..6e1eeb7b00 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/hostname @@ -0,0 +1 @@ +openruyi-????-???? diff --git a/.github/image-build/kiwi-installiso/description/root/etc/kernel/cmdline b/.github/image-build/kiwi-installiso/description/root/etc/kernel/cmdline new file mode 100644 index 0000000000..e68bf382c5 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/kernel/cmdline @@ -0,0 +1 @@ +loglevel=3 audit=0 root=LABEL=ROOT \ No newline at end of file diff --git a/.github/image-build/kiwi-installiso/description/root/etc/kernel/entry-token b/.github/image-build/kiwi-installiso/description/root/etc/kernel/entry-token new file mode 100644 index 0000000000..ca2d92ade1 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/kernel/entry-token @@ -0,0 +1 @@ +openruyi \ No newline at end of file diff --git a/.github/image-build/kiwi-installiso/description/root/etc/kernel/install.conf b/.github/image-build/kiwi-installiso/description/root/etc/kernel/install.conf new file mode 100644 index 0000000000..55ad05571c --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/kernel/install.conf @@ -0,0 +1 @@ +layout=bls diff --git a/.github/image-build/kiwi-installiso/description/root/etc/systemd/timesyncd.conf b/.github/image-build/kiwi-installiso/description/root/etc/systemd/timesyncd.conf new file mode 100644 index 0000000000..5b847042a0 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/etc/systemd/timesyncd.conf @@ -0,0 +1,3 @@ +[Time] +NTP=0.cn.pool.ntp.org +FallbackNTP=1.asia.pool.ntp.org 2.asia.pool.ntp.org diff --git a/.github/image-build/kiwi-installiso/description/root/usr/lib/kernel/install.d/91-other-fallback-install-kernel.install b/.github/image-build/kiwi-installiso/description/root/usr/lib/kernel/install.d/91-other-fallback-install-kernel.install new file mode 100755 index 0000000000..ed0e237fa4 --- /dev/null +++ b/.github/image-build/kiwi-installiso/description/root/usr/lib/kernel/install.d/91-other-fallback-install-kernel.install @@ -0,0 +1,36 @@ +#!/bin/sh +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +set -e + +COMMAND="${1:?}" +KERNEL_VERSION="${2:?}" +ENTRY_DIR_ABS="${3:?}" +KERNEL_IMAGE="$4" +INITRD_OPTIONS_SHIFT=4 + +if [ "$KERNEL_INSTALL_LAYOUT" != "other" ]; then + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "KERNEL_INSTALL_LAYOUT=$KERNEL_INSTALL_LAYOUT, quitting." + exit 0 +fi + +MACHINE_ID="${KERNEL_INSTALL_MACHINE_ID:?}" +ENTRY_TOKEN="${KERNEL_INSTALL_ENTRY_TOKEN:?}" +BOOT_ROOT="${KERNEL_INSTALL_BOOT_ROOT:?}" + +case "$COMMAND" in + remove) + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Removing vmlinuz and extras" + exec rm -rf "$BOOT_ROOT/vmlinuz-$KERNEL_VERSION" + ;; + add) + ;; + *) + exit 0 + ;; +esac +[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Install vmlinuz" + +cp $KERNEL_IMAGE $BOOT_ROOT/vmlinuz-$KERNEL_VERSION; +exit 0 diff --git a/.github/image-build/kiwi-installiso/trigger-packages.txt b/.github/image-build/kiwi-installiso/trigger-packages.txt index c9f818fb11..c41eb43e7c 100644 --- a/.github/image-build/kiwi-installiso/trigger-packages.txt +++ b/.github/image-build/kiwi-installiso/trigger-packages.txt @@ -1,18 +1,14 @@ -# Packages whose changes justify rebuilding the installiso image. +# Packages whose changes justify rebuilding the slim KIWI validation image. NetworkManager authselect bash ca-certificates -cockpit cracklib -dbus -dnf5 -dracut glibc grub -kbd -kexec-tools +kiwi libpwquality +lvm2 linux openresolv openruyi-release @@ -20,11 +16,11 @@ openruyi-repos openruyi-systemd-default-preset openssh pam -procps setup shadow sudo system-user-root systemd util-linux +which xfsprogs diff --git a/.github/testsuite/policy/auth-model/trigger-packages.txt b/.github/testsuite/policy/auth-model/trigger-packages.txt index accab5db70..07695b595d 100644 --- a/.github/testsuite/policy/auth-model/trigger-packages.txt +++ b/.github/testsuite/policy/auth-model/trigger-packages.txt @@ -1,7 +1,6 @@ # Packages whose changes justify running auth/permission model checks -# on top of the installiso image build. +# on top of the slim KIWI validation image build. authselect -kbd libpwquality openssh pam diff --git a/.github/testsuite/smoke/helpers/verify-helper-contracts.sh b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh index 60c9523a9b..9f452f8431 100644 --- a/.github/testsuite/smoke/helpers/verify-helper-contracts.sh +++ b/.github/testsuite/smoke/helpers/verify-helper-contracts.sh @@ -54,14 +54,17 @@ assert_not_contains "$build_workflow" ".github/common/**" "build workflow no lon assert_contains "$selftest_workflow" ".github/common/**" "selftest workflow watches helper changes" assert_contains "$selftest_workflow" ".github/image-build/**" "selftest workflow watches image helper changes" assert_contains "$selftest_workflow" ".github/testsuite/**" "selftest workflow watches testsuite changes" +assert_contains "$build_workflow" "PROFILE: validation" "build workflow uses validation profile" assert_contains "$builder_dockerfile" "git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e" "builder defaults to openRuyi creek base" assert_contains "$build_and_inspect" '-e CONTAINER_NAME="$container_name"' "build-and-inspect passes CONTAINER_NAME into container" assert_contains "$build_and_inspect" 'CONTAINER_NAME=$CONTAINER_NAME' "build-and-inspect writes CONTAINER_NAME from container env" assert_contains "$build_and_inspect" 'UPSTREAM_REPOMD_SHA256' "build-and-inspect records upstream repomd checksum" assert_contains "$build_and_inspect" 'BUILD_PLATFORM=' "build-and-inspect uses explicit build platform" +assert_contains "$build_image" 'profile=${PROFILE:-validation}' "build-image defaults to validation profile" assert_contains "$build_image" 'builder_base_image=${BUILDER_BASE_IMAGE:-git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e}' "build-image defaults to openRuyi creek base" assert_not_contains "$smoke_verify" "root shell is" "smoke suite no longer contains shell policy checks" assert_not_contains "$smoke_verify" "authselect current profile is" "smoke suite no longer contains auth profile policy checks" +assert_not_contains "$smoke_verify" "install ISO" "smoke suite no longer expects install ISO output" mkdir -p "$tmp_dir/bin" "$tmp_dir/image" "$tmp_dir/target" "$tmp_dir/artifacts/a" "$tmp_dir/artifacts/b" @@ -90,7 +93,7 @@ EOF PATH="$tmp_dir/bin:$PATH" \ SUDO= \ -PROFILE=installiso \ +PROFILE=validation \ TARGET_ARCH=x86_64 \ BUILD_PLATFORM=linux/amd64 \ UPSTREAM_REPO=https://repo.build.openruyi.cn/openruyi/x86_64/ \ @@ -106,6 +109,7 @@ assert_contains "$tmp_dir/target/prepared-image.kiwi" 'path="file:///overlay/"' assert_contains "$tmp_dir/target/prepared-image.kiwi" 'name="libudev-zero"' "prepared image injects libudev-zero ignore" assert_contains "$tmp_dir/target/prepared-image.kiwi" 'name="systemd-udev"' "prepared image injects systemd-udev bootstrap package" assert_contains "$tmp_dir/target/prepared-config.sh" 'openRuyi CI initrd hint' "prepared config appends CI initrd hint" +assert_contains "$tmp_dir/target/compose-inputs.env" 'PROFILE=validation' "prepared compose inputs record validation profile" assert_contains "$tmp_dir/target/compose-inputs.env" 'TARGET_ARCH=x86_64' "prepared compose inputs record x86_64" assert_contains "$tmp_dir/target/compose-inputs.env" 'BUILD_PLATFORM=linux/amd64' "prepared compose inputs record build platform" diff --git a/.github/testsuite/smoke/installiso/verify-output.sh b/.github/testsuite/smoke/installiso/verify-output.sh index 805a78002c..db7a8190e3 100644 --- a/.github/testsuite/smoke/installiso/verify-output.sh +++ b/.github/testsuite/smoke/installiso/verify-output.sh @@ -58,7 +58,6 @@ require_file() { } resolve_artifact qcow2_path '*.qcow2' 'qcow2 image' -resolve_artifact iso_path '*.install.iso' 'install ISO' resolve_artifact packages_path '*.packages' 'package manifest' resolve_artifact prepared_kiwi_path 'prepared-image.kiwi' 'prepared image description' resolve_artifact compose_inputs_path 'compose-inputs.env' 'compose inputs' @@ -70,6 +69,11 @@ require_file "$inspect_dir/rpm-query.rc" "inspect/rpm-query.rc" require_file "$inspect_dir/authselect-current-raw.rc" "inspect/authselect-current-raw.rc" if [[ -n "$compose_inputs_path" ]]; then + if grep -q '^PROFILE=validation$' "$compose_inputs_path"; then + pass "compose inputs use validation profile" + else + fail "compose inputs profile mismatch" + fi if grep -q '^TARGET_ARCH=x86_64$' "$compose_inputs_path"; then pass "compose inputs are scoped to x86_64" else @@ -92,6 +96,34 @@ if [[ -n "$compose_inputs_path" ]]; then fi fi +if [[ -n "$prepared_kiwi_path" ]]; then + if grep -Fq 'installiso="true"' "$prepared_kiwi_path"; then + fail "prepared image still requests installiso" + else + pass "prepared image drops installiso mode" + fi + if grep -Fq 'filesystem="xfs"' "$prepared_kiwi_path"; then + pass "prepared image keeps xfs rootfs" + else + fail "prepared image lost xfs rootfs" + fi + if grep -Fq 'preferlvm="true"' "$prepared_kiwi_path"; then + pass "prepared image keeps LVM systemdisk" + else + fail "prepared image lost LVM systemdisk" + fi + if grep -Fq 'efiparttable="gpt"' "$prepared_kiwi_path" && grep -Fq 'eficsm="false"' "$prepared_kiwi_path"; then + pass "prepared image keeps EFI GPT layout" + else + fail "prepared image lost EFI GPT layout" + fi + if grep -Fq '/dev/null 2>&1; then pass "qemu-img info captured" fi -if [[ -n "$qcow2_path" ]] && [[ -n "$iso_path" ]] && command -v file >/dev/null 2>&1; then - file "$iso_path" "$qcow2_path" >"$inspect_dir/file-output.txt" +if [[ -n "$qcow2_path" ]] && command -v file >/dev/null 2>&1; then + file "$qcow2_path" >"$inspect_dir/file-output.txt" pass "file(1) output captured" fi diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1675541ca9..0c0a55c0bc 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -151,7 +151,7 @@ jobs: path: ${{ steps.result.outputs.paths }} if-no-files-found: error - kiwi_installiso_verify: + kiwi_validation_verify: runs-on: [ubuntu-latest] needs: build if: needs.build.outputs.needs_kiwi == 'true' @@ -167,18 +167,18 @@ jobs: - name: Install tools run: | sudo apt update - sudo apt install createrepo-c qemu-utils file git curl -y + sudo apt install createrepo-c qemu-utils file curl -y - name: Build overlay rpm-md repo run: | bash ./.github/common/make-local-rpm-repo.sh ./.ci/pbuild-results ./.ci/local-rpm-repo - name: Resolve compose inputs env: - PROFILE: installiso + PROFILE: validation TARGET_ARCH: x86_64 BUILD_PLATFORM: linux/amd64 UPSTREAM_REPO: https://repo.build.openruyi.cn/openruyi/x86_64/ BUILDER_BASE_IMAGE: git.openruyi.cn/openruyi/creek-x86-64@sha256:ca64fcdb246b38a775ee586e8369d4432899a6d30f6c76340f2397d88efb865e - KIWI_SOURCE_COMMIT: a602fe1d73adeab4cb17078f5fac7d678ff5269b + KIWI_SOURCE_COMMIT: vendored-kiwi-description run: | set -euo pipefail mkdir -p ./.ci/compose-inputs @@ -194,48 +194,35 @@ jobs: echo "BUILDER_BASE_IMAGE=$BUILDER_BASE_IMAGE" echo "KIWI_SOURCE_COMMIT=$KIWI_SOURCE_COMMIT" } > ./.ci/compose-inputs/compose-inputs.env - - name: Fetch official kiwi image repository - env: - KIWI_REPO_URL: https://git.openruyi.cn/openRuyi/openruyi-kiwi-image.git - KIWI_SOURCE_REF: obs - KIWI_SOURCE_COMMIT: a602fe1d73adeab4cb17078f5fac7d678ff5269b - run: | - set -euo pipefail - git clone --depth 1 --branch "$KIWI_SOURCE_REF" "$KIWI_REPO_URL" ./.ci/openruyi-kiwi-image - actual_commit=$(git -C ./.ci/openruyi-kiwi-image rev-parse HEAD) - if [[ "$actual_commit" != "$KIWI_SOURCE_COMMIT" ]]; then - echo "expected KIWI repo commit $KIWI_SOURCE_COMMIT, got $actual_commit from $KIWI_SOURCE_REF" >&2 - exit 1 - fi - - name: Build and inspect installiso from overlay repo + - name: Build and inspect validation qcow2 from overlay repo run: | set -euo pipefail # shellcheck disable=SC1091 source ./.ci/compose-inputs/compose-inputs.env export PROFILE TARGET_ARCH BUILD_PLATFORM UPSTREAM_REPO UPSTREAM_REPOMD_SHA256 BUILDER_BASE_IMAGE KIWI_SOURCE_COMMIT - bash ./.github/image-build/kiwi-installiso/build-and-inspect.sh ./.ci/openruyi-kiwi-image ./.ci/local-rpm-repo ./.ci/out-installiso - cp ./.ci/compose-inputs/upstream-repomd.xml ./.ci/out-installiso/upstream-repomd.xml - - name: Verify installiso smoke suite + bash ./.github/image-build/kiwi-installiso/build-and-inspect.sh ./.github/image-build/kiwi-installiso/description ./.ci/local-rpm-repo ./.ci/out-kiwi-validation + cp ./.ci/compose-inputs/upstream-repomd.xml ./.ci/out-kiwi-validation/upstream-repomd.xml + - name: Verify validation smoke suite run: | - bash ./.github/testsuite/smoke/installiso/verify-output.sh ./.ci/out-installiso + bash ./.github/testsuite/smoke/installiso/verify-output.sh ./.ci/out-kiwi-validation - name: Initialize auth-model policy report run: | - printf 'Policy auth-model verification skipped: no matching package change\n' > ./.ci/out-installiso/POLICY_AUTH_MODEL_SUMMARY.txt + printf 'Policy auth-model verification skipped: no matching package change\n' > ./.ci/out-kiwi-validation/POLICY_AUTH_MODEL_SUMMARY.txt - name: Verify auth-model policy suite if: needs.build.outputs.needs_permission_check == 'true' run: | - bash ./.github/testsuite/policy/auth-model/verify.sh ./.ci/out-installiso + bash ./.github/testsuite/policy/auth-model/verify.sh ./.ci/out-kiwi-validation - uses: actions/upload-artifact@v4 with: - name: PR${{ github.event.pull_request.number }}-kiwi-installiso-verify + name: PR${{ github.event.pull_request.number }}-kiwi-validation-verify path: | - ./.ci/out-installiso/SMOKE_SUMMARY.txt - ./.ci/out-installiso/POLICY_AUTH_MODEL_SUMMARY.txt - ./.ci/out-installiso/compose-inputs.env - ./.ci/out-installiso/prepared-image.kiwi - ./.ci/out-installiso/prepared-config.sh - ./.ci/out-installiso/OVERLAY_PROVENANCE.txt - ./.ci/out-installiso/upstream-repomd.xml - ./.ci/out-installiso/*.packages - ./.ci/out-installiso/inspect/ + ./.ci/out-kiwi-validation/SMOKE_SUMMARY.txt + ./.ci/out-kiwi-validation/POLICY_AUTH_MODEL_SUMMARY.txt + ./.ci/out-kiwi-validation/compose-inputs.env + ./.ci/out-kiwi-validation/prepared-image.kiwi + ./.ci/out-kiwi-validation/prepared-config.sh + ./.ci/out-kiwi-validation/OVERLAY_PROVENANCE.txt + ./.ci/out-kiwi-validation/upstream-repomd.xml + ./.ci/out-kiwi-validation/*.packages + ./.ci/out-kiwi-validation/inspect/ if-no-files-found: error From dfc51919d8f19a7326fa415305f05f299515420f Mon Sep 17 00:00:00 2001 From: Jingwiw Date: Thu, 9 Apr 2026 14:49:55 +0800 Subject: [PATCH 6/6] SPECS: which: CI probe Signed-off-by: Jingwiw --- SPECS/which/which.spec | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SPECS/which/which.spec b/SPECS/which/which.spec index 97d4715233..de33562b7c 100644 --- a/SPECS/which/which.spec +++ b/SPECS/which/which.spec @@ -4,6 +4,8 @@ # SPDX-FileContributor: misaka00251 # # SPDX-License-Identifier: MulanPSL-2.0 +# +# CI probe note: keep this spec-only comment available for kiwi-ci-layout lane validation. Name: which Version: 2.23 @@ -12,11 +14,11 @@ Summary: Displays where a particular program in your path is located License: GPL-3.0-or-later URL: https://savannah.gnu.org/projects/which/ VCS: git:https://https.git.savannah.gnu.org/git/which.git -#!RemoteAsset +#!RemoteAsset: sha256:6971f4793e38f01c644de0da24f4ab2c2afb934b02b7c273fa1e53b859d36529 Source0: https://ftpmirror.gnu.org/gnu/which/which-%{version}.tar.gz -#!RemoteAsset +#!RemoteAsset: sha256:6971f4793e38f01c644de0da24f4ab2c2afb934b02b7c273fa1e53b859d36529 Source1: https://ftpmirror.gnu.org/gnu/which/which-%{version}.tar.gz.sig -#!RemoteAsset +#!RemoteAsset: sha256:6971f4793e38f01c644de0da24f4ab2c2afb934b02b7c273fa1e53b859d36529 Source2: https://savannah.gnu.org/people/viewgpg.php?user_id=3639#/which.keyring BuildSystem: autotools @@ -34,4 +36,4 @@ specified program is in your PATH. %{_mandir}/man1/which.1* %changelog -%{?autochangelog} +%autochangelog