-
Notifications
You must be signed in to change notification settings - Fork 8
337 lines (287 loc) · 13.2 KB
/
Copy pathci.yaml
File metadata and controls
337 lines (287 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# ---------------------------------------------------------------------------
# Linux: compile KVM hypervisor backend (cfg(target_os = "linux"))
# ---------------------------------------------------------------------------
test-linux:
runs-on: ubuntu-24.04-arm
env:
# Hosted ARM runners can expose /dev/kvm but hang in nested/restricted
# KVM ioctls. PR CI compiles the Linux KVM backend and test binaries.
# The release pipeline owns real-KVM coverage.
CAPSEM_SKIP_KVM_TESTS: "1"
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools
- name: Normalize cargo proxy
run: bash scripts/ci/normalize-cargo.sh
- uses: Swatinem/rust-cache@v2
# Collect KVM diagnostics only. GitHub-hosted runners don't always expose
# nested virt -- and when they do, restricted ioctls can hang. PR CI
# compiles the KVM backend with CAPSEM_SKIP_KVM_TESTS=1; the release
# pipeline owns real-KVM coverage.
- name: Collect KVM diagnostics
run: |
if echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules >/dev/null; then
sudo udevadm control --reload-rules || echo "::notice::udev reload failed; keeping KVM diagnostics non-blocking"
sudo udevadm trigger --name-match=kvm || echo "::notice::udev trigger failed; keeping KVM diagnostics non-blocking"
else
echo "::notice::could not write KVM udev rule; keeping KVM diagnostics non-blocking"
fi
if [ -e /dev/kvm ]; then
ls -l /dev/kvm
else
echo "::notice::/dev/kvm is not present on this runner"
fi
# Compile Linux library + service crate tests without executing them. The
# macOS job owns runtime unit coverage for portable code; this job proves
# the Linux-only/KVM cfg surface and test binaries compile on aarch64.
# capsem-app (Tauri shell) and capsem-tray (macOS muda menu-bar) are macOS-only; every
# other host crate is portable and compiles here for Linux-specific regression coverage.
- name: Compile tests (KVM backend, no live KVM)
timeout-minutes: 15
run: |
cargo test --no-run --all-targets -p capsem-core -p capsem-agent -p capsem-logger -p capsem-proto -p capsem-guard -p capsem-gateway -p capsem-service -p capsem -p capsem-mcp -p capsem-mcp-aggregator -p capsem-mcp-builtin -p capsem-process
# Note KVM exercise status. Hosted ARM runners may lack /dev/kvm or
# expose restricted nested KVM; PR CI keeps this compile/no-run and
# release CI owns live-KVM coverage. Surfacing as a warning keeps CI
# honest without false-failing or hanging on a runner-fleet limitation.
- name: Note KVM exercise status
run: |
if [ "${CAPSEM_SKIP_KVM_TESTS:-}" = "1" ]; then
echo "::warning::CAPSEM_SKIP_KVM_TESTS=1 -- PR CI compiled the KVM backend but did not exercise live KVM. Real-KVM coverage runs in release pipeline."
elif [ -e /dev/kvm ]; then
echo "KVM is available at /dev/kvm -- KVM-backed tests exercised."
else
echo "::warning::/dev/kvm not available on this runner -- compile + non-KVM tests only. Real-KVM coverage runs in release pipeline."
fi
- name: Test summary
if: always()
run: |
KVM_STATUS="available"
if [ "${CAPSEM_SKIP_KVM_TESTS:-}" = "1" ]; then
KVM_STATUS="skipped in PR CI"
elif [ ! -e /dev/kvm ]; then
KVM_STATUS="not available"
fi
cat >> "$GITHUB_STEP_SUMMARY" << EOF
## Linux Test Results
| Metric | Result |
|--------|--------|
| Runner | ubuntu-24.04-arm (aarch64) |
| /dev/kvm | $KVM_STATUS |
| Test execution | no-run in PR CI |
| KVM backend | compiled with test binaries (real-KVM tests run in release pipeline) |
EOF
# T5: preserve test artifacts on failure (Linux job).
- name: Upload test artifacts on failure (Linux)
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-artifacts-linux-${{ github.run_attempt }}
path: |
test-artifacts/
frontend/test-artifacts/
target/build.log
retention-days: 7
if-no-files-found: ignore
# ---------------------------------------------------------------------------
# macOS: full test suite (Apple VZ backend, frontend, Python, coverage)
# ---------------------------------------------------------------------------
test:
runs-on: macos-14
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-musl,x86_64-unknown-linux-musl
components: llvm-tools
- name: Normalize cargo proxy
run: bash scripts/ci/normalize-cargo.sh
- uses: Swatinem/rust-cache@v2
- uses: pnpm/action-setup@v5
with:
version: 10
- uses: actions/setup-node@v5
with:
node-version: 24
cache: pnpm
cache-dependency-path: frontend/pnpm-lock.yaml
- run: cd frontend && pnpm install --frozen-lockfile
- uses: astral-sh/setup-uv@v5
- run: uv sync
- name: Normalize cargo proxy after Python setup
run: bash scripts/ci/normalize-cargo.sh
- name: Dependency audit
run: |
cargo install cargo-audit --locked
cargo audit
cd frontend && pnpm audit
- name: Install tools
run: |
cargo install cargo-llvm-cov --locked
cargo install cargo-nextest --locked
- name: Create frontend dist for Tauri test build
run: |
mkdir -p frontend/dist
printf '<!doctype html><html><body></body></html>\n' > frontend/dist/index.html
# Unit tests: all crates with coverage + JUnit XML for test analytics.
# capsem-app (Tauri bin) is macOS-only; capsem-mcp-aggregator and
# capsem-mcp-builtin are thin binaries that pull capsem-core logic.
- name: Unit tests with coverage
run: |
set -o pipefail
cargo llvm-cov nextest --no-cfg-coverage --profile ci --codecov --output-path codecov-unit.json --fail-under-lines 65 -p capsem-core -p capsem-agent -p capsem-logger -p capsem-proto -p capsem-guard -p capsem-gateway -p capsem-service -p capsem -p capsem-mcp -p capsem-mcp-aggregator -p capsem-mcp-builtin -p capsem-tray -p capsem-app -p capsem-process
cargo llvm-cov report --summary-only -p capsem-core -p capsem-agent -p capsem-logger -p capsem-proto -p capsem-guard -p capsem-gateway -p capsem-service -p capsem -p capsem-mcp -p capsem-mcp-aggregator -p capsem-mcp-builtin -p capsem-tray -p capsem-app -p capsem-process 2>&1 | tee coverage-summary.txt
# Integration tests (tests/ directory, cross-crate)
- name: Integration tests with coverage
run: |
cargo llvm-cov nextest --no-cfg-coverage --profile ci --codecov --output-path codecov-integration.json -p capsem-core --test '*'
# Frontend tests with coverage + JUnit output
- name: Frontend type-check, test, and build
run: |
cd frontend
pnpm run check
npx vitest run --coverage --reporter=default --reporter=junit --outputFile=../frontend-junit.xml
pnpm run build
# Python schema tests with coverage
- name: Python schema tests with coverage
run: uv run python -m pytest tests/test_*.py --cov=src/capsem --cov-report=xml:codecov-python.xml --cov-fail-under=89 --junitxml=python-junit.xml
# Python integration tests that need no VM and no generated assets.
# Bootstrap/codesign suites are artifact-dependent: full `just test`
# runs them after assets and signed host binaries exist, while this PR
# lane import-collects them below to catch syntax/fixture drift.
- name: Python integration tests (non-VM suites)
run: |
uv run python -m pytest tests/capsem-rootfs-artifacts/ -v --tb=short
# Verify all integration test suites import cleanly (catches broken imports/syntax)
- name: Verify all integration test imports
run: |
uv run python -m pytest tests/capsem-*/ --collect-only -q
# Schema drift check
- name: Schema drift check
run: |
uv run python scripts/generate_schema.py
git diff --exit-code config/settings-schema.json
# Upload coverage with flags
- name: Upload Rust unit test coverage
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
files: codecov-unit.json
flags: unit
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
- name: Upload Rust integration test coverage
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
files: codecov-integration.json
flags: integration
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
- name: Upload frontend coverage
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
files: coverage/frontend/coverage-final.json
flags: unit
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
- name: Upload Python coverage
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
files: codecov-python.xml
flags: unit
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
# Upload test results for test analytics
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
files: target/nextest/ci/junit.xml,frontend-junit.xml,python-junit.xml
token: ${{ secrets.CODECOV_TOKEN }}
report_type: test_results
# T5: preserve every test artifact (service.log / process.log /
# session.db etc.) on failure so PR reviewers can debug without
# rerunning. preserve_tmp_dir_on_failure() in tests/helpers/service.py
# populates `test-artifacts/` only on red runs; if-no-files-found
# is "ignore" so green runs don't bloat the workflow.
- name: Upload test artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-artifacts-${{ runner.os }}-${{ github.run_attempt }}
path: |
test-artifacts/
frontend/test-artifacts/
target/build.log
retention-days: 7
if-no-files-found: ignore
# Check-only (no link) -- actual cross-compile runs on Linux in release workflow
- name: Cross-compile check (guest binaries)
# Keep release-profile checks on PR validation, but skip them on
# post-merge pushes to main.
if: ${{ github.event_name == 'pull_request' }}
run: |
cargo check --release --target aarch64-unknown-linux-musl -p capsem-agent
cargo check --release --target x86_64-unknown-linux-musl -p capsem-agent
- name: Test summary
if: always()
run: |
COV=$(grep 'TOTAL' coverage-summary.txt 2>/dev/null | awk '{print $(NF)}' || echo "?")
cat >> "$GITHUB_STEP_SUMMARY" << EOF
## Test Results
| Metric | Result |
|--------|--------|
| Line coverage | $COV |
| Test results | See Codecov test analytics |
| Cross-compile | aarch64-unknown-linux-musl |
| Audit | cargo audit + pnpm audit |
> Coverage covers library crates + gateway (capsem-core, agent, logger, proto, gateway).
> Full workspace coverage runs in the release pipeline.
EOF
# ---------------------------------------------------------------------------
# Install e2e: Docker-based install layout + systemd tests (Linux)
# ---------------------------------------------------------------------------
test-install:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-musl
components: llvm-tools
- name: Normalize cargo proxy
run: bash scripts/ci/normalize-cargo.sh
- uses: extractions/setup-just@v3
- uses: pnpm/action-setup@v5
with:
version: 10
- uses: actions/setup-node@v5
with:
node-version: 24
- uses: astral-sh/setup-uv@v5
- run: uv sync
- name: Install install-test host tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends b3sum minisign
- name: Build install VM assets
run: bash scripts/build-assets.sh --profile config/profiles/base/coding.profile.toml --assets-dir assets --arch arm64
- name: Build host builder Docker image
run: just build-host-image
- name: Run install e2e tests
run: just test-install