diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index 444387b36..0965a0b8b 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -23,6 +23,14 @@ on: - release-* jobs: + check-nodocs: + runs-on: linux-amd64-cpu4 + steps: + - uses: actions/checkout@v7 + name: Check out code + - name: Check dnf transactions pass --nodocs + run: ./tests/check-nodocs.sh + image: runs-on: linux-amd64-cpu4 strategy: diff --git a/rhel10/Dockerfile b/rhel10/Dockerfile index f1277c3a1..831528755 100644 --- a/rhel10/Dockerfile +++ b/rhel10/Dockerfile @@ -35,7 +35,7 @@ ENV TARGETARCH=$TARGETARCH SHELL ["/bin/bash", "-c"] -RUN dnf update -y && dnf clean all +RUN dnf update -y --nodocs && dnf clean all #ARG BASE_URL=http://us.download.nvidia.com/XFree86/Linux-x86_64 ARG BASE_URL=https://us.download.nvidia.com/tesla @@ -108,7 +108,7 @@ LABEL description="See summary" # Install / upgrade packages here that are required to resolve CVEs ARG CVE_UPDATES RUN if [ -n "${CVE_UPDATES}" ]; then \ - dnf update -y ${CVE_UPDATES} && \ + dnf update -y --nodocs ${CVE_UPDATES} && \ dnf clean all; \ fi diff --git a/rhel10/install.sh b/rhel10/install.sh index 36a70b1ab..c5be0e45f 100755 --- a/rhel10/install.sh +++ b/rhel10/install.sh @@ -8,7 +8,7 @@ echo "DRIVER_ARCH is $DRIVER_ARCH" dep_installer () { if [ "$DRIVER_ARCH" = "x86_64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -19,7 +19,7 @@ dep_installer () { file \ kmod elif [ "$DRIVER_ARCH" = "ppc64le" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -30,7 +30,7 @@ dep_installer () { file \ kmod elif [ "$DRIVER_ARCH" = "aarch64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -42,8 +42,8 @@ dep_installer () { kmod fi - if ! dnf install -y 'dnf-command(config-manager)'; then - dnf install -y dnf5-plugins + if ! dnf install -y --nodocs 'dnf-command(config-manager)'; then + dnf install -y --nodocs dnf5-plugins fi OS_RELEASE_ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"') @@ -57,15 +57,15 @@ dep_installer () { # unzboot is only available on the EPEL RPM repo if [ "$DRIVER_ARCH" = "aarch64" ]; then rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-10 - dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm + dnf install -y --nodocs https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm dnf config-manager --enable epel # Try to install unzboot from EPEL. If it is not available yet, build it # from source because RHEL/Rocky 10 arm64 kernel images require it. - if ! dnf install -y unzboot; then + if ! dnf install -y --nodocs unzboot; then echo "unzboot package not available in current EPEL version; building from source." # Install meson build dependencies - if dnf install -y git gcc meson ninja-build glib2-devel zlib-devel libzstd-devel; then + if dnf install -y --nodocs git gcc meson ninja-build glib2-devel zlib-devel libzstd-devel; then if command -v meson >/dev/null 2>&1 && command -v ninja >/dev/null 2>&1; then if git clone https://github.com/eballetbo/unzboot.git /tmp/unzboot-src 2>/dev/null; then if meson setup /tmp/unzboot-src/build /tmp/unzboot-src && meson compile -C /tmp/unzboot-src/build; then @@ -73,7 +73,7 @@ dep_installer () { chmod +x /usr/bin/unzboot runtime_pkgs=$(ldd /usr/bin/unzboot | awk '/=> \// { print $3 } /^\// { print $1 }' | xargs -r rpm -q --whatprovides | sort -u) if [ -n "$runtime_pkgs" ]; then - dnf install -y $runtime_pkgs + dnf install -y --nodocs $runtime_pkgs fi echo "Built and installed unzboot from source" else @@ -152,35 +152,35 @@ nvidia_installer () { } fabricmanager_install() { - dnf install -y nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} dnf versionlock add nvidia-fabricmanager nvidia-fabric-manager-devel } nscq_install() { - dnf install -y libnvidia-nscq-${DRIVER_VERSION} + dnf install -y --nodocs libnvidia-nscq-${DRIVER_VERSION} dnf versionlock add libnvidia-nscq } # libnvsdm packages are not available for arm64 nvsdm_install() { if [ "$TARGETARCH" = "amd64" ]; then - dnf install -y libnvsdm-${DRIVER_VERSION} + dnf install -y --nodocs libnvsdm-${DRIVER_VERSION} dnf versionlock add libnvsdm fi } nvlink5_pkgs_install() { - dnf install -y infiniband-diags nvlsm + dnf install -y --nodocs infiniband-diags nvlsm } imex_install() { - dnf install -y nvidia-imex-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-imex-${DRIVER_VERSION} dnf versionlock add nvidia-imex } extra_pkgs_install() { if [ "$DRIVER_TYPE" != "vgpu" ]; then - dnf install -y 'dnf-command(versionlock)' + dnf install -y --nodocs 'dnf-command(versionlock)' fabricmanager_install nscq_install diff --git a/rhel8/Dockerfile b/rhel8/Dockerfile index efe12cb57..cff206fe3 100644 --- a/rhel8/Dockerfile +++ b/rhel8/Dockerfile @@ -34,7 +34,7 @@ ENV TARGETARCH=$TARGETARCH SHELL ["/bin/bash", "-c"] -RUN dnf update -y && dnf clean all +RUN dnf update -y --nodocs && dnf clean all #ARG BASE_URL=http://us.download.nvidia.com/XFree86/Linux-x86_64 ARG BASE_URL=https://us.download.nvidia.com/tesla @@ -106,7 +106,7 @@ LABEL description="See summary" # Install / upgrade packages here that are required to resolve CVEs ARG CVE_UPDATES RUN if [ -n "${CVE_UPDATES}" ]; then \ - dnf update -y ${CVE_UPDATES} && \ + dnf update -y --nodocs ${CVE_UPDATES} && \ dnf clean all; \ fi diff --git a/rhel8/install.sh b/rhel8/install.sh index 060bffe33..9a45b0887 100755 --- a/rhel8/install.sh +++ b/rhel8/install.sh @@ -8,7 +8,7 @@ echo "DRIVER_ARCH is $DRIVER_ARCH" dep_installer () { if [ "$DRIVER_ARCH" = "x86_64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl \ @@ -18,7 +18,7 @@ dep_installer () { cpio \ kmod elif [ "$DRIVER_ARCH" = "ppc64le" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl \ @@ -28,7 +28,7 @@ dep_installer () { cpio \ kmod elif [ "$DRIVER_ARCH" = "aarch64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl \ @@ -39,7 +39,7 @@ dep_installer () { kmod fi - dnf install -y 'dnf-command(config-manager)' + dnf install -y --nodocs 'dnf-command(config-manager)' rm -rf /var/cache/yum/* } @@ -93,35 +93,35 @@ nvidia_installer () { } fabricmanager_install() { - dnf install -y nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} dnf versionlock add nvidia-fabricmanager nvidia-fabric-manager-devel } nscq_install() { - dnf install -y libnvidia-nscq-${DRIVER_VERSION} + dnf install -y --nodocs libnvidia-nscq-${DRIVER_VERSION} dnf versionlock add libnvidia-nscq } nvsdm_install() { if [ "$TARGETARCH" = "amd64" ]; then - dnf install -y libnvsdm-${DRIVER_VERSION} + dnf install -y --nodocs libnvsdm-${DRIVER_VERSION} dnf versionlock add libnvsdm fi } nvlink5_pkgs_install() { - dnf install -y infiniband-diags nvlsm + dnf install -y --nodocs infiniband-diags nvlsm } imex_install() { - dnf install -y nvidia-imex-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-imex-${DRIVER_VERSION} dnf versionlock add nvidia-imex } extra_pkgs_install() { if [ "$DRIVER_TYPE" != "vgpu" ]; then dnf module enable -y nvidia-driver:${DRIVER_BRANCH}-dkms - dnf install -y 'dnf-command(versionlock)' + dnf install -y --nodocs 'dnf-command(versionlock)' fabricmanager_install nscq_install diff --git a/rhel9/Dockerfile b/rhel9/Dockerfile index ae1d0f37b..acd4d92cb 100644 --- a/rhel9/Dockerfile +++ b/rhel9/Dockerfile @@ -34,7 +34,7 @@ ENV TARGETARCH=$TARGETARCH SHELL ["/bin/bash", "-c"] -RUN dnf update -y && dnf clean all +RUN dnf update -y --nodocs && dnf clean all #ARG BASE_URL=http://us.download.nvidia.com/XFree86/Linux-x86_64 ARG BASE_URL=https://us.download.nvidia.com/tesla @@ -107,7 +107,7 @@ LABEL description="See summary" # Install / upgrade packages here that are required to resolve CVEs ARG CVE_UPDATES RUN if [ -n "${CVE_UPDATES}" ]; then \ - dnf update -y ${CVE_UPDATES} && \ + dnf update -y --nodocs ${CVE_UPDATES} && \ dnf clean all; \ fi diff --git a/rhel9/install.sh b/rhel9/install.sh index dabeba023..8da15cd0a 100755 --- a/rhel9/install.sh +++ b/rhel9/install.sh @@ -8,7 +8,7 @@ echo "DRIVER_ARCH is $DRIVER_ARCH" dep_installer () { if [ "$DRIVER_ARCH" = "x86_64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -18,7 +18,7 @@ dep_installer () { cpio \ kmod elif [ "$DRIVER_ARCH" = "ppc64le" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -28,7 +28,7 @@ dep_installer () { cpio \ kmod elif [ "$DRIVER_ARCH" = "aarch64" ]; then - dnf install -y \ + dnf install -y --nodocs \ libglvnd-glx \ ca-certificates \ curl-minimal \ @@ -42,9 +42,9 @@ dep_installer () { # Download unzboot as kernel images are compressed in the zboot format on RHEL 9 arm64 # unzboot is only available on the EPEL RPM repo rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 - dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + dnf install -y --nodocs https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm dnf config-manager --enable epel - dnf install -y unzboot + dnf install -y --nodocs unzboot rm -rf /var/cache/yum/* } @@ -99,35 +99,35 @@ nvidia_installer () { } fabricmanager_install() { - dnf install -y nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-fabricmanager-${DRIVER_VERSION} nvidia-fabric-manager-devel-${DRIVER_VERSION} dnf versionlock add nvidia-fabricmanager nvidia-fabric-manager-devel } nscq_install() { - dnf install -y libnvidia-nscq-${DRIVER_VERSION} + dnf install -y --nodocs libnvidia-nscq-${DRIVER_VERSION} dnf versionlock add libnvidia-nscq } # libnvsdm packages are not available for arm64 nvsdm_install() { if [ "$TARGETARCH" = "amd64" ]; then - dnf install -y libnvsdm-${DRIVER_VERSION} + dnf install -y --nodocs libnvsdm-${DRIVER_VERSION} dnf versionlock add libnvsdm fi } nvlink5_pkgs_install() { - dnf install -y infiniband-diags nvlsm + dnf install -y --nodocs infiniband-diags nvlsm } imex_install() { - dnf install -y nvidia-imex-${DRIVER_VERSION} + dnf install -y --nodocs nvidia-imex-${DRIVER_VERSION} dnf versionlock add nvidia-imex } extra_pkgs_install() { if [ "$DRIVER_TYPE" != "vgpu" ]; then dnf module enable -y nvidia-driver:${DRIVER_BRANCH}-dkms - dnf install -y 'dnf-command(versionlock)' + dnf install -y --nodocs 'dnf-command(versionlock)' # If running on a RockyLinux base image, we enable the Code Ready Builder RPM repo (crb) OS_RELEASE_ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"') diff --git a/tests/check-nodocs.sh b/tests/check-nodocs.sh new file mode 100755 index 000000000..280d545c4 --- /dev/null +++ b/tests/check-nodocs.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# Fail if a dnf transaction that installs into a RHEL image is missing --nodocs. +# +# Documentation installed at image build ends up in the layers we ship, where it +# grows the image and gets picked up by CI scanners. Every install and update in +# these build contexts therefore has to pass --nodocs, and this catches the ones +# that are added later without it. +# +# Continuation lines are joined first, so a command split across lines is still +# seen as one command. Each joined command is then split on &&, ||, ; and | so a +# chain only passes if every transaction in it carries the flag. +# +# Scope. Only the files that put content into the image are checked: +# +# - the RHEL driver and vGPU Manager Dockerfiles and install.sh +# - not rhel*/precompiled, which persists the same setting through +# `dnf config-manager --nodocs --save` instead of per-command flags +# - not nvidia-driver or ocp_dtk_entrypoint, whose dnf calls run in the +# started container rather than at image build +# +# Commands that do not install packages, such as module enable, versionlock, +# config-manager, remove, autoremove and clean, are not matched. +# +# Run from the repository root: +# ./tests/check-nodocs.sh + +set -eu + +cd "$(dirname "$0")/.." + +TARGETS=" +rhel8/Dockerfile +rhel9/Dockerfile +rhel10/Dockerfile +rhel8/install.sh +rhel9/install.sh +rhel10/install.sh +vgpu-manager/rhel8/Dockerfile +vgpu-manager/rhel9/Dockerfile +" + +find_offenders() { + awk ' + # dnf, any number of short or long flags, then a verb that opens a + # transaction. Applied to one command at a time. + function is_transaction(text) { + return text ~ /(^|[^-[:alnum:]_])dnf([[:space:]]+-[^[:space:]]+)*[[:space:]]+(install|update|upgrade|reinstall|downgrade)([[:space:]]|$)/ + } + + function report(command, lineno, parts, count, i) { + if (command ~ /^[[:space:]]*#/) + return + count = split(command, parts, /&&|\|\||;|\|/) + for (i = 1; i <= count; i++) + if (is_transaction(parts[i]) && parts[i] !~ /--nodocs/) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[i]) + print lineno ": " parts[i] + } + } + + { + if (buffer == "") + start = NR + text = $0 + continued = (text ~ /\\[[:space:]]*$/) + sub(/\\[[:space:]]*$/, "", text) + buffer = (buffer == "" ? text : buffer " " text) + if (continued) + next + report(buffer, start) + buffer = "" + } + + END { + if (buffer != "") + report(buffer, start) + } + ' "$1" +} + +status=0 + +for file in $TARGETS; do + [ -f "$file" ] || { echo "check-nodocs.sh: missing $file" >&2; status=1; continue; } + + offenders=$(find_offenders "$file") + + if [ -n "$offenders" ]; then + status=1 + while IFS= read -r line; do + printf '%s:%s\n' "$file" "$line" + done <<< "$offenders" + fi +done + +if [ "$status" -ne 0 ]; then + cat >&2 <<'EOF' + +dnf transactions above are missing --nodocs. + +Add it so the documentation is never written into the image: + + dnf install -y --nodocs + dnf update -y --nodocs + +If a command genuinely should keep documentation, exclude the file in +tests/check-nodocs.sh and say why. +EOF + exit 1 +fi + +echo "all dnf transactions in the RHEL build contexts pass --nodocs" diff --git a/vgpu-manager/rhel8/Dockerfile b/vgpu-manager/rhel8/Dockerfile index bb4f5b470..d18928ba9 100644 --- a/vgpu-manager/rhel8/Dockerfile +++ b/vgpu-manager/rhel8/Dockerfile @@ -23,7 +23,7 @@ RUN chmod +x NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}-vgpu-kvm.run COPY nvidia-driver /usr/local/bin COPY ocp_dtk_entrypoint /usr/local/bin -RUN dnf install -y pciutils && \ +RUN dnf install -y --nodocs pciutils && \ dnf clean all && \ rm -rf /var/cache/dnf/* @@ -39,7 +39,7 @@ LABEL description="See summary" # Install / upgrade packages here that are required to resolve CVEs ARG CVE_UPDATES RUN if [ -n "${CVE_UPDATES}" ]; then \ - dnf update -y ${CVE_UPDATES} && \ + dnf update -y --nodocs ${CVE_UPDATES} && \ dnf clean all; \ fi diff --git a/vgpu-manager/rhel9/Dockerfile b/vgpu-manager/rhel9/Dockerfile index 2a1ae8520..c43909822 100644 --- a/vgpu-manager/rhel9/Dockerfile +++ b/vgpu-manager/rhel9/Dockerfile @@ -36,7 +36,7 @@ RUN chmod +x NVIDIA-Linux-${DRIVER_ARCH}-${DRIVER_VERSION}-vgpu-kvm.run COPY nvidia-driver /usr/local/bin COPY ocp_dtk_entrypoint /usr/local/bin -RUN dnf install -y pciutils && \ +RUN dnf install -y --nodocs pciutils && \ dnf clean all && \ rm -rf /var/cache/dnf/* @@ -52,7 +52,7 @@ LABEL description="See summary" # Install / upgrade packages here that are required to resolve CVEs ARG CVE_UPDATES RUN if [ -n "${CVE_UPDATES}" ]; then \ - dnf update -y ${CVE_UPDATES} && \ + dnf update -y --nodocs ${CVE_UPDATES} && \ dnf clean all; \ fi