ndctl-test runner #39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: CXL test runner | |
| # yamllint disable-line rule:truthy | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| kernel_repo: | |
| description: "Kernel repo: owner/name OR full git URL" | |
| required: true | |
| default: "AlisonSchofield/linux-kernel" | |
| kernel_branch: | |
| description: "Kernel branch (or tag/SHA)" | |
| required: true | |
| default: "cxl-testme" | |
| ndctl_repo: | |
| description: "ndctl repo: owner/name OR full git URL" | |
| required: true | |
| default: "pmem/ndctl" | |
| ndctl_branch: | |
| description: "ndctl branch (or tag/SHA)" | |
| required: true | |
| default: "pending" | |
| timeout_min: | |
| description: "Guest timeout (minutes)" | |
| required: true | |
| default: "35" | |
| jobs: | |
| build: | |
| runs-on: ubuntu-24.04 | |
| env: | |
| # Inputs | |
| KERNEL_REPO: ${{ inputs.kernel_repo }} | |
| KERNEL_BRANCH: ${{ inputs.kernel_branch }} | |
| NDCTL_REPO: ${{ inputs.ndctl_repo }} | |
| NDCTL_BRANCH: ${{ inputs.ndctl_branch }} | |
| RUN_TIMEOUT_MIN: ${{ inputs.timeout_min }} | |
| # Pinned runner behavior (not user-configurable ATM) | |
| RUN_OPTS: --cxl-test-run --ndctl-build | |
| # Pinned image selection | |
| MKOSI_DISTRO: ubuntu | |
| MKOSI_RELEASE: noble | |
| # Pinned runner identity strings (for output / cache keys) | |
| RUNNER_OS_LABEL: ubuntu-24.04 | |
| ARCH_LABEL: x86_64 | |
| steps: | |
| - name: checkout run_qemu (this repo) | |
| uses: actions/checkout@v4 | |
| with: | |
| path: run_qemu | |
| # Free disk space on GitHub runner | |
| - name: apt-get remove for disk space | |
| run: | | |
| df -h | |
| sudo apt-get remove -y '^aspnetcore-.*' '^dotnet-.*' | |
| sudo apt-get remove -y 'php.*' '^mongodb-.*' '^mysql-.*' | |
| sudo apt-get remove -y azure-cli '^google-cloud*' | |
| sudo apt-get remove -y '^llvm-.*' | |
| sudo apt-get autoremove -y | |
| sudo apt-get install -y bc | |
| df -h | |
| - name: rm -rf for disk space | |
| run: | | |
| df -h | |
| sudo docker image prune --all --force || true | |
| df -h | |
| _dirs=( /usr/local/lib/android /usr/share/dotnet /usr/local/.ghcup ) | |
| sudo du -shc "${_dirs[@]}" || true | |
| sudo rm -rf "${_dirs[@]}" | |
| df -h | |
| - name: apt install mkosi and run_qemu requirements | |
| run: | | |
| sudo apt-get update | |
| # Kernel build deps | |
| sudo apt install -y build-essential flex bison libelf-dev libssl-dev ccache | |
| # run_qemu deps | |
| sudo apt install -y mkosi | |
| sudo apt install -y dracut-core qemu-utils ovmf mtools qemu-system-x86 | |
| pip3 install qemu.qmp | |
| - name: mkosi v20 fixes on Ubuntu 24.04 | |
| run: | | |
| cd /usr/lib/python3/dist-packages | |
| sudo git apply "${{ github.workspace }}/run_qemu/Patches/ubuntu/24.04/mkosi/"*.patch | |
| - name: apt install Ubuntu 24.04 requirements for mkosi | |
| run: | | |
| sudo apt install -y systemd-ukify systemd-boot | |
| - name: apt install ndctl build dependencies | |
| run: | | |
| grep -vE '^[[:blank:]]*#' .github/workflows/ubuntu-ndctl-build-deps | \ | |
| xargs sudo apt install -y | |
| - name: argbash | |
| run: | | |
| AB_VER=2.10.0 | |
| wget https://github.com/matejak/argbash/archive/refs/tags/${AB_VER}.tar.gz | |
| tar xf ${AB_VER}.tar.gz | |
| sudo apt install -y autoconf | |
| sudo make -C argbash-${AB_VER}/resources install PREFIX=/usr/local/ | |
| - name: set week number for caches | |
| id: weeks | |
| run: | | |
| printf 'now=%s\n' "$(date +%Y-w%U)" >> "$GITHUB_OUTPUT" | |
| printf 'previous=%s\n' "$(date +%Y-w%U -d '7 days ago')" >> "$GITHUB_OUTPUT" | |
| - name: compute cache key suffixes | |
| id: cachekeys | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| k="$(printf '%s\n' "$KERNEL_REPO@$KERNEL_BRANCH" | sha256sum | awk '{print $1}')" | |
| n="$(printf '%s\n' "$NDCTL_REPO@$NDCTL_BRANCH" | sha256sum | awk '{print $1}')" | |
| echo "kernel_key=$k" >> "$GITHUB_OUTPUT" | |
| echo "ndctl_key=$n" >> "$GITHUB_OUTPUT" | |
| - name: Fetch ccache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ccache/ | |
| key: ccache_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ steps.cachekeys.outputs.kernel_key }}_${{ steps.weeks.outputs.now }} | |
| restore-keys: | | |
| ccache_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ steps.cachekeys.outputs.kernel_key }}_${{ steps.weeks.outputs.previous }} | |
| ccache_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ steps.cachekeys.outputs.kernel_key }} | |
| ccache_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }} | |
| - name: ensure clean checkout dirs | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| rm -rf ndctl kernel | |
| # Checkout that supports either "owner/name" OR full git URL. | |
| - name: checkout ndctl | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ "$NDCTL_REPO" =~ ^https?://|^git://|^ssh://|^git@ ]]; then | |
| git clone --depth 1 --branch "$NDCTL_BRANCH" "$NDCTL_REPO" ndctl | |
| else | |
| git clone --depth 1 --branch "$NDCTL_BRANCH" "https://github.com/${NDCTL_REPO}.git" ndctl | |
| fi | |
| - name: checkout kernel | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ "$KERNEL_REPO" =~ ^https?://|^git://|^ssh://|^git@ ]]; then | |
| git clone --depth 1 --branch "$KERNEL_BRANCH" "$KERNEL_REPO" kernel | |
| else | |
| git clone --depth 1 --branch "$KERNEL_BRANCH" "https://github.com/${KERNEL_REPO}.git" kernel | |
| fi | |
| - name: Ensure mkosi cache dirs exist | |
| run: | | |
| mkdir -p kernel/qbuild/mkosi.cache | |
| mkdir -p kernel/qbuild/mkosi.cache/{cache/apt,lib/apt} | |
| # Cache mkosi's tree caches (big win: avoids re-installing packages into a fresh rootfs tree) | |
| - name: Restore mkosi tree cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| kernel/qbuild/mkosi.cache/ubuntu~noble~x86-64.cache | |
| kernel/qbuild/mkosi.cache/ubuntu~noble~x86-64.manifest | |
| kernel/qbuild/mkosi.cache/ubuntu~noble~x86-64~default-initrd.cache | |
| kernel/qbuild/mkosi.cache/ubuntu~noble~x86-64~default-initrd.manifest | |
| key: mkositree_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }}_${{ steps.weeks.outputs.now }} | |
| restore-keys: | | |
| mkositree_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }}_${{ steps.weeks.outputs.previous }} | |
| mkositree_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }} | |
| mkositree_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }} | |
| fail-on-cache-miss: false | |
| # Cache only mkosi's apt caches (nice-to-have) | |
| - name: Restore mkosi apt cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| kernel/qbuild/mkosi.cache/cache/apt | |
| kernel/qbuild/mkosi.cache/lib/apt | |
| key: mkosiapt_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }}_${{ steps.weeks.outputs.now }} | |
| restore-keys: | | |
| mkosiapt_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }}_${{ steps.weeks.outputs.previous }} | |
| mkosiapt_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }}_${{ env.MKOSI_DISTRO }}_${{ env.MKOSI_RELEASE }} | |
| mkosiapt_${{ env.RUNNER_OS_LABEL }}_${{ env.ARCH_LABEL }} | |
| fail-on-cache-miss: false | |
| - name: Normalize mkosi cache permissions | |
| run: | | |
| sudo chmod -R a+rX kernel/qbuild/mkosi.cache || true | |
| - name: show revisions under test | |
| run: | | |
| echo "Kernel repo: $KERNEL_REPO" | |
| echo "Kernel branch: $KERNEL_BRANCH" | |
| git -C kernel rev-parse HEAD | |
| git -C kernel log -1 --oneline | |
| echo | |
| echo "ndctl repo: $NDCTL_REPO" | |
| echo "ndctl branch: $NDCTL_BRANCH" | |
| git -C ndctl rev-parse HEAD | |
| git -C ndctl log -1 --oneline | |
| echo | |
| echo "Runner: $RUNNER_OS_LABEL" | |
| echo "Arch: $ARCH_LABEL" | |
| echo "mkosi image: $MKOSI_DISTRO $MKOSI_RELEASE" | |
| echo "run_qemu opts: $RUN_OPTS" | |
| echo "timeout (min): $RUN_TIMEOUT_MIN" | |
| - name: defconfig | |
| working-directory: ${{ github.workspace }}/kernel | |
| run: | | |
| make defconfig ARCH=x86_64 | |
| ./scripts/kconfig/merge_config.sh .config ../run_qemu/.github/workflows/cxl-test.cfg | |
| - name: disable AppArmor | |
| run: | | |
| if test -e /proc/sys/kernel/apparmor_restrict_unprivileged_unconfined; then | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0 | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| fi | |
| - name: build kernel | |
| run: | | |
| ccache --show-stats | |
| cd kernel | |
| PATH=/usr/lib/ccache:"$PATH" make -j $(nproc) | |
| - name: run_qemu.sh | |
| run: | | |
| set -x | |
| mkosi --version | |
| qemu-system-x86_64 --version || true | |
| which qemu-system-x86_64 || true | |
| ccache --show-stats | |
| cp run_qemu/contrib/tmpfs_workspace.tmpl run_qemu/mkosi_tmpl_portable/ | |
| rm -f /tmp/rq_0.log | |
| touch /tmp/rq_0.log | |
| chmod a+rw /tmp/rq_0.log | |
| cd kernel | |
| ( | |
| PATH=/usr/lib/ccache:"$PATH" \ | |
| distro=${MKOSI_DISTRO} rev=${MKOSI_RELEASE} \ | |
| ndctl='${{ github.workspace }}/ndctl' \ | |
| ../run_qemu/run_qemu.sh -v ${RUN_OPTS} \ | |
| --rebuild=kmod \ | |
| --no-kvm \ | |
| --timeout=${RUN_TIMEOUT_MIN} \ | |
| --debug | |
| ) 2>&1 | tee -a /tmp/rq_0.log | |
| exit ${PIPESTATUS[0]} | |
| - name: check if qemu died early | |
| if: ${{ always() }} | |
| run: | | |
| echo "=== qemu processes ===" | |
| ps -ef | grep -v grep | grep qemu-system-x86_64 || echo "no qemu process" | |
| echo "=== QMP socket ===" | |
| ls -la /tmp/run_qemu_qmp_0 || true | |
| - name: show bios and serial logs | |
| if: ${{ always() }} | |
| run: | | |
| echo "=== /tmp/rq_0.log tail ===" | |
| tail -n 200 /tmp/rq_0.log || true | |
| echo "=== bios_debug.log ===" | |
| tail -n 200 kernel/bios_debug.log 2>/dev/null || tail -n 200 bios_debug.log 2>/dev/null || true | |
| - name: summarize test results | |
| if: ${{ always() }} | |
| run: | | |
| set -euo pipefail | |
| RAW=/tmp/rq_0.log | |
| CLEAN=/tmp/rq_0.clean.log | |
| # Remove ANSI escapes + CRs so matching is reliable. | |
| perl -pe 's/\e\[[0-9;]*[A-Za-z]//g; s/\r$//;' "$RAW" > "$CLEAN" || true | |
| normalize_line() { | |
| # Remove optional leading kernel timestamp: "[ 123.456789] " | |
| # Then remove optional "<anything>.log: " prefix (covers cxl-test-*.log:). | |
| sed -E \ | |
| -e 's/^\[[[:space:]]*[0-9]+\.[0-9]+\][[:space:]]+//' \ | |
| -e 's/^[[:space:]]*[^:]+\.log:[[:space:]]+//' \ | |
| -e 's/^[[:space:]]+//' | |
| } | |
| { | |
| echo "# CXL test results" | |
| echo | |
| echo "## Inputs" | |
| echo "- Kernel: ${KERNEL_REPO} @ ${KERNEL_BRANCH}" | |
| echo "- ndctl: ${NDCTL_REPO} @ ${NDCTL_BRANCH}" | |
| echo "- Runner: ${RUNNER_OS_LABEL}" | |
| echo "- mkosi: ${MKOSI_DISTRO} ${MKOSI_RELEASE}" | |
| echo "- timeout: ${RUN_TIMEOUT_MIN} min" | |
| echo | |
| echo "## Revisions" | |
| echo "Kernel:" | |
| git -C kernel log -1 --oneline || true | |
| echo | |
| echo "ndctl:" | |
| git -C ndctl log -1 --oneline || true | |
| echo | |
| echo "## Per-test results" | |
| normalize_line < "$CLEAN" | awk ' | |
| /======= meson-test\.log =======/ {exit} | |
| /^[0-9]+\/[0-9]+[[:space:]]+ndctl:cxl[[:space:]]*\// { | |
| printing=1 | |
| found=1 | |
| next | |
| } | |
| printing { exit } # stop after first block ends | |
| END { if (!found) print "(no per-test lines found in /tmp/rq_0.log)" } | |
| ' | |
| echo | |
| echo "## Totals" | |
| normalize_line < "$CLEAN" | awk ' | |
| /======= meson-test\.log =======/ {exit} | |
| /^Ok:[[:space:]]/ {p=1} | |
| p && /^(Ok:|Expected Fail:|Fail:|Unexpected Pass:|Skipped:|Timeout:)[[:space:]]/ {print; next} | |
| p { exit } | |
| ' || true | |
| echo | |
| echo "See the uploaded artifact: /tmp/rq_0.log" | |
| } | tee /tmp/cxl-test-summary.md | |
| cat /tmp/cxl-test-summary.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: upload logs | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: logs | |
| if-no-files-found: warn | |
| path: | | |
| /tmp/rq_0.log | |
| kernel/bios_debug.log | |
| bios_debug.log | |
| - name: ccache stats | |
| run: | | |
| ccache --show-stats | |
| ccache --show-config | grep dir || true |