forked from tinyhumansai/openhuman
-
Notifications
You must be signed in to change notification settings - Fork 0
196 lines (188 loc) · 6.7 KB
/
coverage.yml
File metadata and controls
196 lines (188 loc) · 6.7 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
name: Coverage Gate
on:
pull_request:
workflow_dispatch:
permissions:
contents: read
pull-requests: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.head_ref || github.ref }}
cancel-in-progress: true
defaults:
run:
# The CI container's default `sh` is dash, which rejects `set -o pipefail`
# and bashisms like `mapfile`. Force bash for every `run:` step.
shell: bash
jobs:
frontend-coverage:
name: Frontend Coverage (Vitest)
runs-on: ubuntu-22.04
container:
image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 1
- name: Cache pnpm store
uses: actions/cache@v5
with:
path: ~/.local/share/pnpm/store
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run Vitest with coverage
run: pnpm test:coverage
working-directory: app
env:
NODE_ENV: test
- name: Normalize lcov source paths to repo root
# Vitest writes paths relative to app/ (the Vite root). diff-cover
# resolves SF: paths against the repo root, so prefix them with `app/`
# to match how `git diff` names the files.
run: |
set -euo pipefail
test -f app/coverage/lcov.info
sed -i -E 's#^SF:(src/)#SF:app/\1#' app/coverage/lcov.info
sed -i -E 's#^SF:(\./src/)#SF:app/src/#' app/coverage/lcov.info
- name: Upload frontend lcov
uses: actions/upload-artifact@v5
with:
name: lcov-frontend
path: app/coverage/lcov.info
retention-days: 7
if-no-files-found: error
rust-core-coverage:
name: Rust Core Coverage (cargo-llvm-cov)
runs-on: ubuntu-22.04
container:
image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0
env:
CARGO_INCREMENTAL: '0'
# sccache is incompatible with `-C instrument-coverage` profiles, so we
# skip it for coverage runs and rely on Swatinem/rust-cache for warmup.
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 1
submodules: recursive
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: . -> target
cache-on-failure: true
key: core-coverage
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run cargo llvm-cov for openhuman core
# See test.yml `Test core crate` for why `--test-threads=1` is
# required: process-wide singletons in scheduler_gate / local_ai
# do not isolate cleanly across parallel `#[tokio::test]` runtimes.
run: cargo llvm-cov -p openhuman --lcov --output-path lcov-core.info -- --test-threads=1
- name: Upload core lcov
uses: actions/upload-artifact@v5
with:
name: lcov-rust-core
path: lcov-core.info
retention-days: 7
if-no-files-found: error
rust-tauri-coverage:
name: Rust Tauri Coverage (cargo-llvm-cov)
runs-on: ubuntu-22.04
container:
image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0
env:
CARGO_INCREMENTAL: '0'
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 1
submodules: recursive
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
app/src-tauri -> target
cache-on-failure: true
key: tauri-coverage
- name: Cache CEF binary distribution
uses: actions/cache@v5
with:
path: ~/.cache/tauri-cef
key: cef-ubuntu-22.04-${{ hashFiles('app/src-tauri/Cargo.toml') }}
restore-keys: |
cef-ubuntu-22.04-
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run cargo llvm-cov for Tauri shell
run: cargo llvm-cov --manifest-path app/src-tauri/Cargo.toml --lcov --output-path lcov-tauri.info
- name: Upload tauri lcov
uses: actions/upload-artifact@v5
with:
name: lcov-rust-tauri
path: lcov-tauri.info
retention-days: 7
if-no-files-found: error
coverage-gate:
name: Coverage Gate (diff-cover ≥ 80%)
needs: [frontend-coverage, rust-core-coverage, rust-tauri-coverage]
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
# diff-cover needs full history for the merge-base with the PR base.
fetch-depth: 0
- name: Fetch PR base branch
run: git fetch origin "${{ github.base_ref }}" --depth=200
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Install diff-cover
run: pip install 'diff-cover>=9.2.0'
- name: Download all lcov artifacts
uses: actions/download-artifact@v5
with:
path: lcov-artifacts
pattern: lcov-*
merge-multiple: false
- name: List collected lcov files
run: |
set -euo pipefail
find lcov-artifacts -type f -name '*.info' -print
- name: Enforce ≥ 80% coverage on changed lines
# diff-cover accepts multiple lcov inputs and computes coverage on
# *changed lines only*, scoped to files present in the lcov report.
# Test files are excluded from the lcov reports themselves (Vitest
# `coverage.exclude`, cargo-llvm-cov's `#[cfg(test)]` filtering),
# so changed test lines are simply not measured and do not skew the
# ratio.
run: |
set -euo pipefail
mapfile -t LCOV_FILES < <(find lcov-artifacts -type f -name '*.info' | sort)
if [ "${#LCOV_FILES[@]}" -eq 0 ]; then
echo "::error::No lcov files found — coverage gate cannot run"
exit 1
fi
diff-cover "${LCOV_FILES[@]}" \
--compare-branch="origin/${{ github.base_ref }}" \
--fail-under=80 \
--html-report diff-coverage.html \
--markdown-report diff-coverage.md
- name: Upload diff-cover report
if: always()
uses: actions/upload-artifact@v5
with:
name: diff-coverage-report
path: |
diff-coverage.html
diff-coverage.md
retention-days: 14
if-no-files-found: warn