NDCTL Test Runner is a GitHub Actions workflow that builds a Linux kernel, boots it in QEMU using run_qemu_ci.sh, and executes the ndctl test suites for CXL, NVDIMM, and DAX. It runs entirely on GitHub-hosted infrastructure with no special hardware required.
This repository serves two purposes:
Scheduled testing of upstream kernel branches — five workflows run daily against the major CXL, NVDIMM, and linux-next kernel trees, each tested against ndctl/pending. See Scheduled Runs.
A reusable test runner for kernel developers — fork this repository to run tests against your own kernel branches. Tests can be launched four ways:
- From the Actions tab in your fork — Quick Start
- From the command line using the GitHub CLI — Running From The Command Line
- Using the included run-test.sh wrapper — Using run-test.sh
- Automatically on push, triggered from your kernel repository — Automatically Trigger Tests
Five workflows run automatically each day at 01:00 UTC (6pm PDT / 5pm PST), one per branch under test:
cxl/next— cxl/cxl.git, cxl testscxl/fixes— cxl/cxl.git, cxl testslibnvdimm/for-next— nvdimm/nvdimm.git, nvdimm and dax testslibnvdimm/fixes— nvdimm/nvdimm.git, nvdimm and dax testslinux-next/master— next/linux-next.git, cxl, nvdimm, and dax tests
View nightly results: https://pmem.github.io/ndctl-test-runner/
TODO: Add a weekly workflow to test new Linus release candidate tags (mainline).
Each workflow appears as a separate entry in the Actions tab. Scheduled
runs are labeled (schedule) in the run list.
All five workflows use SHA deduplication: if neither the kernel branch nor ndctl/pending has changed since the last successful run, the test is skipped and no runner time is consumed.
Each workflow can also be triggered manually at any time from the Actions tab using the Run workflow button.
When a scheduled run has test failures or skips, the full rq_0.log is
uploaded as a workflow artifact and can be downloaded from the run page for
detailed per-test analysis.
-
Fork this repository.
-
Open the Actions tab in your fork.
-
Select ndctl-test runner.
-
Click Run workflow.
-
Provide your kernel repository and branch.
Repository inputs may be either:
- a GitHub repository in
owner/nameform - a full git URL (for example a kernel.org maintainer tree)
You can immediately test the current CXL maintainer tree.
Example inputs:
kernel_repo: https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git
kernel_branch: next
ndctl_repo: pmem/ndctl
ndctl_branch: pending
test_suite: cxl
timeout_min: 35
This runs the ndctl CXL test suite against the current CXL maintainer next branch in QEMU.
| Input | Description | Default |
|---|---|---|
kernel_repo |
Kernel repo: owner/name or full git URL |
(required) |
kernel_branch |
Kernel branch, tag, or SHA | (required) |
ndctl_repo |
ndctl repo: owner/name or full git URL |
pmem/ndctl |
ndctl_branch |
ndctl branch, tag, or SHA | pending |
test_suite |
Test suites to run (see below) | all |
timeout_min |
Guest timeout in minutes | 35 |
| Value | Test suites run |
|---|---|
all |
CXL, NVDIMM, and DAX tests |
cxl |
CXL unit tests only |
nvdimm |
NVDIMM (nfit) tests only |
dax |
DAX tests only |
Space-separated combinations are also accepted (for example nvdimm dax).
Example using a GitHub kernel repository (CXL testing):
kernel_repo: yourname/linux
kernel_branch: cxl-feature-branch
ndctl_repo: pmem/ndctl
ndctl_branch: pending
test_suite: cxl
timeout_min: 35
Example using a kernel.org maintainer tree (all suites):
kernel_repo: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
kernel_branch: master
ndctl_repo: pmem/ndctl
ndctl_branch: pending
test_suite: all
timeout_min: 45
Tests can be triggered from the command line using either the GitHub CLI
directly or the run-test.sh wrapper script included in this repository.
Both require the GitHub CLI to be installed and authenticated:
gh auth login
gh workflow run "ndctl-test runner" \
--repo yourname/ndctl-test-runner \
-f kernel_repo=https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git \
-f kernel_branch=next \
-f test_suite=cxl
gh workflow run "ndctl-test runner" \
--repo yourname/ndctl-test-runner \
-f kernel_repo=https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git \
-f kernel_branch=libnvdimm-for-next \
-f test_suite="nvdimm dax"
gh workflow run "ndctl-test runner" \
--repo yourname/ndctl-test-runner \
-f kernel_repo=yourname/linux \
-f kernel_branch=my-feature-branch \
-f test_suite=cxl
Watch the run:
gh run watch --repo yourname/ndctl-test-runner
run-test.sh is a wrapper around the GitHub CLI that shortens common
invocations. Edit the REPO variable at the top of the script to point
to your fork before using it.
# CXL next branch
./run-test.sh -k https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git \
-b next -s cxl
# NVDIMM for-next branch
./run-test.sh -k https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git \
-b libnvdimm-for-next -s "nvdimm dax"
# Your own kernel branch
./run-test.sh -k yourname/linux -b my-feature-branch -s cxl
Trigger and watch in one step:
./run-test.sh -k yourname/linux -b my-feature-branch -s cxl --watch
The workflow summary displays the results of each test. Example CXL output:
1/16 ndctl:cxl / cxl-topology.sh OK 3.21s
2/16 ndctl:cxl / cxl-region-sysfs.sh OK 8.43s
3/16 ndctl:cxl / cxl-labels.sh OK 4.17s
4/16 ndctl:cxl / cxl-create-region.sh OK 12.85s
5/16 ndctl:cxl / cxl-xor-region.sh OK 18.62s
...
16/16 ndctl:cxl / cxl-poison.sh OK 5.30s
Ok: 16
Fail: 0
Skipped: 0
Timeout: 0
When tests fail, a summary of failures is shown in the workflow step log,
and the full rq_0.log is uploaded as an artifact for detailed analysis.
Developers may configure their kernel repository to automatically trigger the NDCTL Test Runner whenever commits are pushed.
This works with your fork of ndctl-test-runner. You cannot trigger
runs in pmem/ndctl-test-runner directly. If you have a public branch
you would like added to the nightly runs in pmem/ndctl-test-runner
(temporarily or long-term), open an issue in this repository and ask.
Create the file .github/workflows/ndctl-test.yml in your kernel repo:
name: run ndctl tests
on:
push:
branches:
- cxl-*
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger NDCTL Test Runner
env:
GH_TOKEN: ${{ secrets.NDCTL_RUNNER_TOKEN }}
run: |
gh workflow run "ndctl-test runner" \
--repo yourname/ndctl-test-runner \
-f kernel_repo=${{ github.repository }} \
-f kernel_branch=${{ github.ref_name }} \
-f test_suite=cxlThis project packages the run_qemu_ci.sh testing environment into a reproducible GitHub Actions workflow for automated ndctl test execution.
The runner performs the following steps:
- Checkout the requested kernel repository and branch
- Checkout the requested ndctl repository and branch
- Build the kernel with ccache using a unified config for all test suites
- Boot the kernel in QEMU using run_qemu_ci.sh
- Execute the selected ndctl test suites (CXL, NVDIMM, DAX, or all)
- Publish a test summary and upload logs when failures or skips occur
A unified kernel configuration (ci-base.cfg + cxl-test.cfg + nfit-test.cfg) is always applied regardless of which test suite is selected. This maximizes ccache hits: switching suites reuses the same binary, and iterating on kernel patches only recompiles changed files rather than triggering config-driven rebuilds across the tree.
The workflow currently runs with the following configuration:
GitHub runner: ubuntu-24.04
Architecture: x86_64
mkosi image: ubuntu noble
https://github.com/pmem/run_qemu
This project builds on the run_qemu infrastructure originally developed by Vishal Verma and expanded upon by Marc Herbert.
run_qemu_ci.sh is a CI-focused derivative of the upstream run_qemu.sh.
It retains the kernel build, rootfs image creation, and automated QEMU
boot and test execution, while removing all interactive features (SSH
access, networking setup, GDB integration, and developer convenience
tools) that are not needed for automated CI runs.