Skip to content

Commit 776206e

Browse files
committed
chore(ci): add CI tests
1 parent 284afe2 commit 776206e

5 files changed

Lines changed: 1579 additions & 5 deletions

File tree

.github/workflows/ci.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
merge_group:
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
RUSTFLAGS: -Dwarnings
14+
RUST_BACKTRACE: 1
15+
16+
jobs:
17+
test:
18+
name: Test (Rust ${{matrix.toolchain}}, target ${{matrix.target}})
19+
runs-on: ubuntu-latest
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
toolchain: ["nightly", "beta", "stable", "1.83.0"]
24+
target: ["x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl"]
25+
timeout-minutes: 45
26+
steps:
27+
- uses: actions/checkout@v4
28+
with:
29+
persist-credentials: false
30+
- uses: dtolnay/rust-toolchain@master
31+
with:
32+
toolchain: ${{matrix.toolchain}}
33+
components: llvm-tools, clippy, rust-src
34+
- uses: taiki-e/install-action@v2
35+
with:
36+
tool: just,cargo-llvm-cov,cargo-nextest
37+
- name: Enable type layout randomization
38+
if: matrix.toolchain == 'nightly'
39+
run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV
40+
- run: sudo apt-get update && sudo apt-get install -y musl-tools
41+
if: endsWith(matrix.target, 'musl')
42+
- run: rustup target add ${{matrix.target}}
43+
- run: just ci-test --target ${{matrix.target}}
44+
45+
docs:
46+
name: Documentation
47+
runs-on: ubuntu-latest
48+
timeout-minutes: 45
49+
env:
50+
RUSTDOCFLAGS: -Dwarnings
51+
steps:
52+
- uses: actions/checkout@v4
53+
with:
54+
persist-credentials: false
55+
- uses: dtolnay/rust-toolchain@nightly
56+
- uses: dtolnay/install@cargo-docs-rs
57+
- run: cargo docs-rs --package ktls-core
58+
- run: cargo docs-rs --package ktls-stream
59+
60+
clippy:
61+
name: Clippy
62+
runs-on: ubuntu-latest
63+
if: github.event_name != 'pull_request'
64+
timeout-minutes: 45
65+
steps:
66+
- uses: actions/checkout@v4
67+
with:
68+
persist-credentials: false
69+
- uses: dtolnay/rust-toolchain@master
70+
with:
71+
toolchain: 1.83.0
72+
components: clippy
73+
- uses: taiki-e/install-action@v2
74+
with:
75+
tool: just
76+
- run: just clippy
77+
78+
coverage:
79+
name: Coverage
80+
runs-on: ubuntu-latest
81+
steps:
82+
- uses: actions/checkout@v4
83+
with:
84+
persist-credentials: false
85+
- uses: dtolnay/rust-toolchain@master
86+
with:
87+
toolchain: nightly
88+
components: llvm-tools, clippy, rust-src
89+
- uses: taiki-e/install-action@v2
90+
with:
91+
tool: just,cargo-llvm-cov,cargo-nextest
92+
- run: just ci-test
93+
- name: Upload coverage reports to Codecov
94+
uses: codecov/codecov-action@v5
95+
with:
96+
token: ${{ secrets.CODECOV_TOKEN }}
97+
slug: hanyu-dev/ktls
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
# Credits: https://github.com/tokio-rs/io-uring/blob/master/.github/workflows/kernel-version-test.yml
2+
#
3+
# Tests kTLS functionality across multiple kernel versions.
4+
# Manual trigger supports custom space-separated version list.
5+
6+
name: Kernel Compatibility Test
7+
8+
on:
9+
push:
10+
branches: ["main"]
11+
pull_request:
12+
merge_group:
13+
schedule:
14+
# Every day at 04:00 UTC
15+
- cron: "0 4 * * *"
16+
workflow_dispatch:
17+
inputs:
18+
kernel-versions:
19+
description: "Space-separated list of Linux kernel versions to test"
20+
required: true
21+
22+
permissions:
23+
contents: read
24+
25+
jobs:
26+
prepare-kernel-versions:
27+
name: Prepare kernel versions matrix
28+
runs-on: ubuntu-latest
29+
outputs:
30+
matrix: ${{ steps.set-matrix.outputs.matrix }}
31+
steps:
32+
- name: Install dependencies
33+
run: |
34+
sudo apt-get update
35+
sudo apt-get install -y jq curl
36+
37+
- name: Set matrix
38+
id: set-matrix
39+
run: |
40+
if [ -n "${GITHUB_EVENT_INPUTS_KERNEL_VERSIONS}" ]; then
41+
# Manual trigger with custom versions
42+
versions="${GITHUB_EVENT_INPUTS_KERNEL_VERSIONS}"
43+
echo "Using manual input versions: $versions"
44+
else
45+
# Get from https://www.kernel.org/releases.json
46+
echo "Fetching latest kernel versions from kernel.org..."
47+
48+
# Fetch releases data
49+
releases_json=$(curl -s https://www.kernel.org/releases.json)
50+
51+
if [ -z "$releases_json" ]; then
52+
echo "Failed to fetch kernel releases data"
53+
exit 1
54+
fi
55+
56+
# Extract versions for specific kernel series
57+
mainline=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "mainline") | .version')
58+
stable=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "stable") | .version')
59+
60+
# Extract latest longterm versions for specific series
61+
lts_6_12=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("6.12."))) | .version' | head -1)
62+
lts_6_6=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("6.6."))) | .version' | head -1)
63+
lts_6_1=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("6.1."))) | .version' | head -1)
64+
lts_5_15=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("5.15."))) | .version' | head -1)
65+
lts_5_10=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("5.10."))) | .version' | head -1)
66+
lts_5_4=$(echo "$releases_json" | jq -r '.releases[] | select(.moniker == "longterm" and (.version | startswith("5.4."))) | .version' | head -1)
67+
68+
# Build versions list with fallbacks for missing LTS versions
69+
versions=""
70+
[ -n "$mainline" ] && versions="$versions $mainline"
71+
[ -n "$stable" ] && versions="$versions $stable"
72+
[ -n "$lts_6_12" ] && versions="$versions $lts_6_12"
73+
[ -n "$lts_6_6" ] && versions="$versions $lts_6_6"
74+
[ -n "$lts_6_1" ] && versions="$versions $lts_6_1"
75+
[ -n "$lts_5_15" ] && versions="$versions $lts_5_15"
76+
[ -n "$lts_5_10" ] && versions="$versions $lts_5_10"
77+
[ -n "$lts_5_4" ] && versions="$versions $lts_5_4"
78+
fi
79+
80+
# Convert space-separated list to JSON array
81+
json_array=$(echo "$versions" | xargs | tr ' ' '\n' | grep -v '^$' | jq -R . | jq -s -c .)
82+
echo "matrix=$json_array" >> $GITHUB_OUTPUT
83+
echo "Generated matrix: $json_array"
84+
env:
85+
GITHUB_EVENT_INPUTS_KERNEL_VERSIONS: ${{ github.event.inputs.kernel-versions }}
86+
87+
build-test-binary:
88+
name: Build test binary
89+
runs-on: ubuntu-latest
90+
steps:
91+
- name: Checkout repository
92+
uses: actions/checkout@v4
93+
with:
94+
persist-credentials: false
95+
96+
- name: Install dependencies
97+
run: |
98+
sudo apt-get update
99+
sudo apt-get install -y musl-tools
100+
101+
- name: Install Rust 1.83.0
102+
uses: dtolnay/rust-toolchain@master
103+
with:
104+
toolchain: 1.83.0
105+
targets: x86_64-unknown-linux-musl
106+
107+
- name: Build test binary
108+
run: |
109+
cargo build --package ktls-tests --bin ktls-test-echo --release --target x86_64-unknown-linux-musl
110+
111+
- name: Upload artifact
112+
uses: actions/upload-artifact@v4
113+
with:
114+
name: ktls-test-echo
115+
path: target/x86_64-unknown-linux-musl/release/ktls-test-echo
116+
retention-days: 1
117+
compression-level: 0
118+
overwrite: true
119+
120+
build-kernel:
121+
name: Build kernel - ${{ matrix.kernel-version }}
122+
needs: prepare-kernel-versions
123+
runs-on: ubuntu-latest
124+
strategy:
125+
matrix:
126+
kernel-version: ${{fromJson(needs.prepare-kernel-versions.outputs.matrix)}}
127+
fail-fast: false
128+
env:
129+
KERNEL_VERSION: ${{ matrix.kernel-version }}
130+
steps:
131+
- name: Install dependencies
132+
run: |
133+
sudo apt-get update
134+
sudo apt-get install -y \
135+
bison flex libelf-dev \
136+
xz-utils wget
137+
138+
- name: Cache Linux source
139+
id: cache-kernel
140+
uses: actions/cache@v4
141+
with:
142+
path: linux-${{ env.KERNEL_VERSION }}
143+
key: linux-${{ env.KERNEL_VERSION }}-cache-v1
144+
145+
- name: Build Linux kernel
146+
if: steps.cache-kernel.outputs.cache-hit != 'true'
147+
run: |
148+
MAJOR=${KERNEL_VERSION%%.*}
149+
wget https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${KERNEL_VERSION}.tar.xz
150+
tar xf linux-${KERNEL_VERSION}.tar.xz
151+
cd linux-${KERNEL_VERSION}
152+
153+
# Generate the default config
154+
make defconfig
155+
156+
# Enable essentials as built-ins
157+
scripts/config --enable CONFIG_DEVTMPFS
158+
scripts/config --enable CONFIG_DEVTMPFS_MOUNT
159+
160+
# Enable virtio drivers
161+
scripts/config --enable CONFIG_VIRTIO
162+
scripts/config --enable CONFIG_VIRTIO_PCI
163+
scripts/config --enable CONFIG_VIRTIO_BLK
164+
165+
# Enable kTLS support
166+
scripts/config --enable CONFIG_TLS
167+
scripts/config --enable CONFIG_TLS_DEVICE
168+
169+
# Generate the updated config
170+
make olddefconfig
171+
172+
make -j$(nproc)
173+
174+
- name: Upload kernel artifact
175+
uses: actions/upload-artifact@v4
176+
with:
177+
name: linux-kernel-${{ env.KERNEL_VERSION }}
178+
path: linux-${{ env.KERNEL_VERSION }}/arch/x86/boot/bzImage
179+
retention-days: 1
180+
compression-level: 6
181+
overwrite: true
182+
183+
test:
184+
name: Test - ${{ matrix.kernel-version }} @ ${{ matrix.arg-termination }} ${{ matrix.arg-cipher }}
185+
needs: [prepare-kernel-versions, build-test-binary, build-kernel]
186+
runs-on: ubuntu-latest
187+
strategy:
188+
matrix:
189+
kernel-version: ${{fromJson(needs.prepare-kernel-versions.outputs.matrix)}}
190+
arg-termination: ["client", "server"]
191+
arg-cipher:
192+
[
193+
"TLS13_AES_128_GCM_SHA256",
194+
"TLS13_AES_256_GCM_SHA384",
195+
"TLS13_CHACHA20_POLY1305_SHA256",
196+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
197+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
198+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
199+
]
200+
fail-fast: false
201+
env:
202+
KERNEL_VERSION: ${{ matrix.kernel-version }}
203+
TEST_ARG_TERMINATION: ${{ matrix.arg-termination }}
204+
TEST_ARG_CIPHER: ${{ matrix.arg-cipher }}
205+
steps:
206+
- name: Install dependencies
207+
run: |
208+
sudo apt-get update
209+
sudo apt-get install -y \
210+
qemu-system-x86 busybox-static cpio e2fsprogs
211+
212+
- name: Download test binary artifact
213+
uses: actions/download-artifact@v4
214+
with:
215+
name: ktls-test-echo
216+
path: .
217+
218+
- name: Download kernel artifact
219+
uses: actions/download-artifact@v4
220+
with:
221+
name: linux-kernel-${{ env.KERNEL_VERSION }}
222+
path: .
223+
224+
- name: Prepare initramfs + tests binaries
225+
run: |
226+
rm -rf initramfs && mkdir -p initramfs/{bin,sbin,proc,sys,tmp}
227+
228+
# Copy the test binary (downloaded from artifact)
229+
chmod +x ktls-test-echo
230+
cp ktls-test-echo initramfs/bin/
231+
232+
# Add necessary binaries from busybox
233+
cp /usr/bin/busybox initramfs/bin/
234+
for cmd in sh mount ip ifconfig cat; do ln -sf busybox initramfs/bin/$cmd; done
235+
ln -sf ../bin/busybox initramfs/sbin/poweroff
236+
237+
# Generate init script
238+
cat > initramfs/init << EOF
239+
#!/bin/sh
240+
set -e
241+
242+
# Activating the loopback interface (it's required for some network tests)
243+
ip link set lo up
244+
245+
mkdir -p /dev
246+
247+
# Enable necessary devices
248+
# https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
249+
mknod /dev/port c 1 4
250+
mknod /dev/null c 1 3
251+
mknod /dev/zero c 1 5
252+
mknod /dev/tty c 5 0
253+
254+
mkdir -p /tmp && mount -t tmpfs -o mode=1777 tmpfs /tmp
255+
256+
# Bring up ext4 test volume at /mnt
257+
mount -t devtmpfs devtmpfs /dev
258+
259+
exit_code=0
260+
261+
# Run the test binary
262+
RUST_BACKTRACE=1 /bin/ktls-test-echo -t "${TEST_ARG_TERMINATION}" -c "${TEST_ARG_CIPHER}" || exit_code=1
263+
264+
# If the test binary exited with a non-zero code, write it to /dev/port.
265+
# This lets QEMU exit with non-zero exit-code, triggering a CI error.
266+
[ \$exit_code -eq 0 ] || printf '\x01' \\
267+
| dd of=/dev/port bs=1 seek=244 count=1 2>/dev/null
268+
269+
/sbin/poweroff -f
270+
271+
EOF
272+
273+
chmod +x initramfs/init
274+
275+
# Pack into a CPIO archive
276+
(cd initramfs && find . -print0 \
277+
| cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz)
278+
279+
- name: Run tests in QEMU
280+
run: |
281+
qemu-system-x86_64 \
282+
-device isa-debug-exit,iobase=0xf4,iosize=0x04 \
283+
-kernel bzImage \
284+
-initrd initramfs.cpio.gz \
285+
-netdev user,id=net0 \
286+
-device e1000,netdev=net0 \
287+
-append "console=ttyS0 rootfstype=ramfs panic=1" \
288+
-nographic -no-reboot -m 1024 -action panic=exit-failure
289+
290+
if [ $? -ne 0 ]; then
291+
echo "tests failed (QEMU exited abnormally)"
292+
exit 1
293+
else
294+
echo "all tests passed"
295+
fi

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
/target
2-
/Cargo.lock
32
*coverage*

0 commit comments

Comments
 (0)