Skip to content

CXL test runner

CXL test runner #38

Workflow file for this run

---
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 apt cache dirs exist
run: |
mkdir -p kernel/qbuild/mkosi.cache/{cache/apt,lib/apt}
# Cache only mkosi's apt caches (safe + small; avoids rootfs/ssh key permission issues)
- 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: 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
# Helper to drop the leading kernel timestamp + "foo.log:" prefix for readability.
strip_prefix() {
sed -E 's/^\[[[:space:]]*[0-9]+\.[0-9]+\][[:space:]]+[^:]+:[[: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"
# Print only the FIRST contiguous block of "N/M ndctl:cxl / ..." lines.
strip_prefix < "$CLEAN" | awk '
/======= meson-test\.log =======/ {exit}
/^[[:space:]]*[0-9]+\/[0-9]+[[:space:]]+ndctl:cxl[[:space:]]*\// {
printing=1
print
next
}
printing { exit } # stop after first block ends
' || echo "(no per-test lines found in /tmp/rq_0.log)"
echo
echo "## Totals"
# Print the FIRST scoreboard block only, then stop.
strip_prefix < "$CLEAN" | awk '
/======= meson-test\.log =======/ {exit}
/^[[:space:]]*Ok:[[:space:]]/ {p=1}
p && /^[[:space:]]*(Ok:|Expected Fail:|Fail:|Unexpected Pass:|Skipped:|Timeout:)[[:space:]]/ {print; next}
p { exit } # stop after first totals block ends
' || 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