Skip to content

Commit 3c3e776

Browse files
committed
ci: add end-to-end job exercising the controller on a kind cluster
The check job proves the code compiles and is clean; this job proves the operator actually works in a cluster. On an ephemeral kind cluster it: installs the CRD, runs the operator against it, applies a VllmService, and verifies the full lifecycle — the owned Deployment is created, the status converges to Ready (warm), the owner reference is set, and deleting the VllmService garbage-collects the Deployment. Waits use bounded polling with diagnostic output on failure, not fixed sleeps, so the test asserts convergence without being timing-flaky.
1 parent 2e806d0 commit 3c3e776

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,95 @@ jobs:
4242

4343
- name: Build release
4444
run: cargo build --release
45+
46+
e2e:
47+
name: end-to-end on kind
48+
runs-on: ubuntu-latest
49+
steps:
50+
- uses: actions/checkout@v4
51+
52+
- name: Install Rust toolchain
53+
uses: dtolnay/rust-toolchain@stable
54+
55+
- name: Cache cargo registry and target
56+
uses: actions/cache@v4
57+
with:
58+
path: |
59+
~/.cargo/registry
60+
~/.cargo/git
61+
target
62+
key: ${{ runner.os }}-cargo-e2e-${{ hashFiles('**/Cargo.lock') }}
63+
64+
- name: Build operator and crdgen
65+
run: cargo build --bins
66+
67+
- name: Create kind cluster
68+
uses: helm/kind-action@v1
69+
with:
70+
cluster_name: e2e
71+
72+
- name: Install CRD
73+
run: |
74+
cargo run --bin crdgen > deploy/crd.yaml
75+
kubectl apply -f deploy/crd.yaml
76+
kubectl wait --for=condition=Established crd/vllmservices.inference.michelecampi.dev --timeout=30s
77+
78+
- name: Start operator in background
79+
run: |
80+
./target/debug/vllm-coldstart-operator > operator.log 2>&1 &
81+
echo $! > operator.pid
82+
sleep 3
83+
echo "operator started (pid $(cat operator.pid))"
84+
85+
- name: Apply a VllmService
86+
run: kubectl apply -f deploy/examples/qwen-7b.yaml
87+
88+
- name: Wait for Deployment to be created
89+
run: |
90+
for i in $(seq 1 30); do
91+
if kubectl get deployment qwen-7b >/dev/null 2>&1; then
92+
echo "Deployment created after ${i}s"
93+
exit 0
94+
fi
95+
sleep 1
96+
done
97+
echo "ERROR: Deployment not created within 30s"
98+
kubectl get all
99+
cat operator.log
100+
exit 1
101+
102+
- name: Wait for status to reach Ready
103+
run: |
104+
for i in $(seq 1 60); do
105+
phase=$(kubectl get vllmservice qwen-7b -o jsonpath='{.status.phase}' 2>/dev/null || true)
106+
echo "[$i] phase=${phase:-<none>}"
107+
if [ "$phase" = "Ready" ]; then
108+
echo "VllmService reached Ready after ${i}s"
109+
kubectl get vllmservice qwen-7b -o jsonpath='{.status.message}'
110+
exit 0
111+
fi
112+
sleep 2
113+
done
114+
echo "ERROR: VllmService did not reach Ready within 120s"
115+
kubectl get vllmservice qwen-7b -o yaml
116+
cat operator.log
117+
exit 1
118+
119+
- name: Verify owner reference and garbage collection
120+
run: |
121+
owner=$(kubectl get deployment qwen-7b -o jsonpath='{.metadata.ownerReferences[0].kind}')
122+
[ "$owner" = "VllmService" ] || { echo "ERROR: bad owner ref: $owner"; exit 1; }
123+
kubectl delete vllmservice qwen-7b
124+
for i in $(seq 1 30); do
125+
if ! kubectl get deployment qwen-7b >/dev/null 2>&1; then
126+
echo "Deployment garbage-collected after ${i}s"
127+
exit 0
128+
fi
129+
sleep 1
130+
done
131+
echo "ERROR: Deployment not garbage-collected within 30s"
132+
exit 1
133+
134+
- name: Stop operator
135+
if: always()
136+
run: kill "$(cat operator.pid)" 2>/dev/null || true

0 commit comments

Comments
 (0)