Skip to content

Commit 5bfa8e3

Browse files
Add CI workflow to run the test suite (#96)
* add CI workflow to run the test suite Runs make test on every push/PR. Kernel verifier tests need passwordless sudo and a kernel with BTF/BPF enabled, which isn't guaranteed on every runner, so the workflow probes for working sudo first and only attempts them if it's available. Also add ctypeslib2 to the test extra: make test now regenerates vmlinux.py via tools/vmlinux-gen.py, which needs clang2py. * fix CI: bpftool is a virtual package on Ubuntu, install linux-tools instead * fix CI: locate bpftool binary and add it to PATH manually linux-tools-generic's update-alternatives symlink for bpftool doesn't fire on GitHub-hosted runners, since their kernel version has no matching linux-tools-<version> package. * pin clang bindings to 16.0.6 to match Ubuntu's default libclang pip installs the latest 'clang' release by default, whose libclang API surface is newer than Ubuntu 24.04's apt libclang-16, causing a LibclangError about an undefined symbol. Older bindings against a newer libclang stay compatible, so pin the bindings low rather than the system library. * DEBUG: dump struct_vmbus_channel_offer_channel on test failure * remove debug step now that the bitfield issue is fixed * fix CI: install LLVM 19 from apt.llvm.org, Ubuntu's default is too old llvmlite>=0.49's ArgumentAttributes only recognizes the LLVM 19+ 'captures(none)' spelling of the renamed 'nocapture' attribute. Ubuntu noble's default llvm/clang packages are LLVM 18, whose llc can't parse that attribute in the emitted .ll text. * DEBUG: show real llc stderr on failure * fix YAML syntax in debug step * fix CI: install LLVM 22 (matching llvmlite's bundled version), not 19 Verified on CI: LLVM 19's llc still rejects 'captures(none)' as a parse error ('expected ) at end of argument list'). llvmlite 0.49 bundles LLVM 22.1.0 internally; match that generation instead. * remove debug step, LLVM 22 fix confirmed working on CI * avoid running CI twice per push: scope push trigger to master Branches live in this repo, not forks, so a push to a branch with an open PR fired both push and pull_request for the same commit. push now only fires for master (a post-merge check); pull_request already covers every commit on a feature branch.
1 parent 5c05b11 commit 5bfa8e3

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

.github/workflows/test.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Runs the pytest suite (IR generation + LLC compilation). Kernel verifier
2+
# tests additionally need passwordless sudo and a kernel with BTF/BPF
3+
# enabled, which isn't guaranteed on every runner, so we probe for working
4+
# sudo first and only attempt them if it's there.
5+
#
6+
# `push` is scoped to master only: branches here live in this repo rather
7+
# than forks, so a push to a branch with an open PR would otherwise fire
8+
# both `push` and `pull_request` for the same commit, running everything
9+
# twice. `pull_request` covers feature branches; `push` still gives master
10+
# a post-merge check.
11+
12+
name: Test
13+
14+
on:
15+
workflow_dispatch:
16+
push:
17+
branches: [master]
18+
pull_request:
19+
20+
jobs:
21+
test:
22+
name: Test
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v7
26+
27+
- uses: actions/setup-python@v7
28+
with:
29+
python-version: "3.12"
30+
31+
- name: Install system dependencies
32+
run: |
33+
sudo apt-get update
34+
sudo apt-get install -y lsb-release wget software-properties-common gnupg linux-tools-common linux-tools-generic
35+
36+
# Ubuntu's default `llvm`/`clang` packages (LLVM 18 on noble) are
37+
# too old to assemble the IR llvmlite>=0.49 emits: llvmlite's
38+
# ArgumentAttributes only knows the 'captures(none)' spelling of
39+
# the renamed 'nocapture' attribute, matching the LLVM 22.1.0 it
40+
# bundles internally - and an llc from an older LLVM (verified:
41+
# 19 still rejects it as a parse error) can't read that attribute
42+
# in the .ll text. Install a matching-generation LLVM from
43+
# apt.llvm.org instead of the distro default, and make its tools
44+
# the ones found on PATH.
45+
wget https://apt.llvm.org/llvm.sh
46+
chmod +x llvm.sh
47+
sudo ./llvm.sh 22 all
48+
sudo ln -sf /usr/bin/clang-22 /usr/local/bin/clang
49+
sudo ln -sf /usr/bin/llc-22 /usr/local/bin/llc
50+
clang --version
51+
llc --version
52+
53+
# bpftool isn't an installable package by itself on Ubuntu: it's a
54+
# virtual package provided by linux-tools-common + a kernel-flavor
55+
# linux-tools-<flavor> package. The runner's exact kernel version
56+
# has no matching linux-tools-<version> package, so the
57+
# update-alternatives symlink for `bpftool` doesn't get set up;
58+
# find whatever binary the generic-flavor package installed and
59+
# put it on PATH ourselves.
60+
bpftool_bin=$(sudo find /usr/lib/linux-tools* -name bpftool -type f 2>/dev/null | head -1)
61+
if [ -z "$bpftool_bin" ]; then
62+
echo "::error::Could not find a bpftool binary after installing linux-tools-generic"
63+
exit 1
64+
fi
65+
sudo ln -sf "$bpftool_bin" /usr/local/bin/bpftool
66+
bpftool version
67+
68+
- name: Install uv
69+
run: pip install uv
70+
71+
- name: Install project
72+
run: uv pip install --system -e ".[test]"
73+
74+
- name: Run test suite
75+
run: make test
76+
77+
- name: Check whether sudo is usable
78+
id: sudo-check
79+
run: |
80+
if sudo -n true 2>/dev/null; then
81+
echo "Passwordless sudo is available."
82+
echo "available=true" >> "$GITHUB_OUTPUT"
83+
else
84+
echo "No passwordless sudo on this runner; kernel verifier tests will be skipped."
85+
echo "available=false" >> "$GITHUB_OUTPUT"
86+
fi
87+
88+
- name: Run kernel verifier tests
89+
if: steps.sudo-check.outputs.available == 'true'
90+
run: |
91+
sudo -v
92+
make test-verifier

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ docs = [
4444
test = [
4545
"pytest>=8.0",
4646
"pytest-cov>=5.0",
47+
"ctypeslib2",
48+
# Pinned rather than left to ctypeslib2's own (unpinned) dependency: pip
49+
# installs the latest release by default, and its libclang API surface
50+
# can be newer than the system libclang (e.g. Ubuntu 24.04 ships
51+
# libclang-16), which fails with a LibclangError about an undefined
52+
# symbol. Older bindings against a newer libclang stay compatible, so
53+
# pin to an old-enough release instead of pinning apt's libclang.
54+
"clang==16.0.6",
4755
]
4856

4957
[tool.setuptools.packages.find]

0 commit comments

Comments
 (0)