Skip to content

Commit 77f6b3e

Browse files
ci(codecov): add advisory portable-core coverage workflow (#263)
* ci(codecov): add advisory portable-core coverage workflow Adds .github/workflows/coverage.yml to run cargo-llvm-cov coverage on: - push to main - workflow_dispatch - PRs labeled coverage, full-ci, or ci:full Coverage scope is limited to portable core/control-plane crates: flight-core, flight-axis, flight-bus, flight-scheduler, flight-rules, flight-profile, flight-units, flight-session, flight-metrics, flight-device-common, flight-hid-types, flight-adapter-common, flight-test-helpers, flight-workspace-meta Generates coverage.json, coverage.txt, and lcov.info artifacts. Codecov uploads require CODECOV_TOKEN secret. CI economics: - Default PR impact: none (labeled only) - Runs on: ubuntu-latest, 45min timeout - Generates artifacts for 14 days retention - No branch protection impact (advisory only) Claim boundary: Codecov is execution-surface evidence only. Does not prove: - real-time deadline correctness - hardware/device correctness - simulator adapter correctness - force-feedback safety - HIL readiness - BDD completeness - fuzz robustness - release readiness https://claude.ai/code/session_01U8AKLUWvrAE2w6Ey63qDGQ * ci(codecov): add quiet Codecov config Adds codecov.yml with: - Precision 2, round down, range 50-85% - Project status: auto target, 5% threshold, informational - Patch status: 70% target, 20% threshold, informational - All flags: rust-core (portable core/control-plane crates) - Comments disabled (quiet mode) - GitHub check annotations disabled - Ignores: target/, fuzz/, benches/, examples/, installer/ CI economics: - No direct CI impact (config file only) - Requires Codecov GitHub app integration - Codecov dashboard hosted externally - No branch protection impact (advisory mode) Claim boundary: Same as coverage workflow - execution-surface evidence only, does not prove real-time timing, hardware correctness, simulator adapter correctness, force-feedback safety, HIL readiness, BDD completeness, fuzz robustness, or release readiness. https://claude.ai/code/session_01U8AKLUWvrAE2w6Ey63qDGQ * docs(readme): add CI and Codecov badges Adds badge block for: - CI workflow status - Codecov coverage reporting - MSRV 1.92.0 - MIT OR Apache-2.0 license Also adds note linking to Coverage documentation explaining Codecov claim boundaries and execution-surface evidence scope. CI economics: - No direct CI impact (docs only) - Badge links are external (GitHub Actions, Codecov dashboards) - No branch protection impact https://claude.ai/code/session_01U8AKLUWvrAE2w6Ey63qDGQ * docs(ci): document coverage lane Adds docs/ci/coverage.md explaining: - What Codecov coverage measures (execution-surface evidence) - What it does not measure (real-time timing, hardware correctness, simulator adapter correctness, force-feedback safety, HIL readiness, BDD completeness, fuzz robustness, release readiness) - When the coverage workflow runs (push main, workflow_dispatch, coverage/full-ci/ci:full labels) - Coverage scope (rust-core flag for portable core/control-plane) - Durable receipts (coverage.json, coverage.txt, lcov.info, GitHub artifact, Codecov dashboard) - Claim boundary (what this lane is and is not responsible for) CI economics: - No direct CI impact (docs only) - No branch protection impact https://claude.ai/code/session_01U8AKLUWvrAE2w6Ey63qDGQ * ci(codecov): add coverage receipt artifact Adds receipt generation and summary to coverage workflow: 1. Write coverage receipt (coverage-receipt.json) - Schema version 1 - Repo, lane, flag, workflow, scope metadata - Artifact presence flags (coverage.json, coverage.txt, lcov.info) - Explicit claim boundary array 2. Includes coverage-receipt.json in artifact upload - 14-day retention - Machine-readable JSON format 3. Adds step summary with artifact status table - Shows which artifacts are present - Documents flag and scope - Visible in GitHub Actions UI This provides durable receipt that coverage was generated and aligns with OpenFlight's evidence-heavy CI model. CI economics: - ~50ms added to workflow (Python JSON generation) - No failure path (always() condition) - No branch protection impact https://claude.ai/code/session_01U8AKLUWvrAE2w6Ey63qDGQ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 607f501 commit 77f6b3e

4 files changed

Lines changed: 331 additions & 0 deletions

File tree

.github/workflows/coverage.yml

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
name: Coverage
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "Cargo.toml"
8+
- "Cargo.lock"
9+
- "crates/**"
10+
- "specs/**"
11+
- ".github/workflows/coverage.yml"
12+
- "codecov.yml"
13+
pull_request:
14+
types: [opened, synchronize, reopened, labeled]
15+
branches: [main]
16+
paths:
17+
- "Cargo.toml"
18+
- "Cargo.lock"
19+
- "crates/**"
20+
- "specs/**"
21+
- ".github/workflows/coverage.yml"
22+
- "codecov.yml"
23+
workflow_dispatch:
24+
25+
permissions:
26+
contents: read
27+
28+
concurrency:
29+
group: coverage-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
30+
cancel-in-progress: true
31+
32+
env:
33+
CARGO_TERM_COLOR: always
34+
CARGO_INCREMENTAL: "0"
35+
RUSTFLAGS: "-C debuginfo=0"
36+
37+
jobs:
38+
coverage:
39+
name: Codecov Coverage
40+
runs-on: ubuntu-latest
41+
timeout-minutes: 45
42+
43+
if: >-
44+
github.event_name == 'push' ||
45+
github.event_name == 'workflow_dispatch' ||
46+
contains(github.event.pull_request.labels.*.name, 'coverage') ||
47+
contains(github.event.pull_request.labels.*.name, 'full-ci') ||
48+
contains(github.event.pull_request.labels.*.name, 'ci:full')
49+
50+
steps:
51+
- uses: actions/checkout@v4
52+
53+
- name: Install Rust
54+
uses: dtolnay/rust-toolchain@master
55+
with:
56+
toolchain: "1.92.0"
57+
components: llvm-tools-preview
58+
59+
- name: Install Linux HID build deps
60+
run: |
61+
sudo apt-get update
62+
sudo apt-get install -y libudev-dev
63+
64+
- name: Use larger target dir
65+
run: echo "CARGO_TARGET_DIR=${RUNNER_TEMP}/target" >> "$GITHUB_ENV"
66+
67+
- uses: Swatinem/rust-cache@v2
68+
with:
69+
cache-on-failure: true
70+
cache-directories: ${{ runner.temp }}/target
71+
shared-key: coverage-1.92
72+
save-if: ${{ github.ref == 'refs/heads/main' }}
73+
74+
- name: Install coverage tools
75+
uses: taiki-e/install-action@v2
76+
with:
77+
tool: cargo-llvm-cov,cargo-nextest
78+
79+
- name: Generate coverage
80+
env:
81+
CI: true
82+
PROPTEST_CASES: "64"
83+
INSTA_UPDATE: "no"
84+
run: |
85+
set -euo pipefail
86+
cargo llvm-cov clean --workspace
87+
88+
cargo llvm-cov nextest \
89+
--locked \
90+
--no-report \
91+
-p flight-core \
92+
-p flight-axis \
93+
-p flight-bus \
94+
-p flight-scheduler \
95+
-p flight-rules \
96+
-p flight-profile \
97+
-p flight-units \
98+
-p flight-session \
99+
-p flight-metrics \
100+
-p flight-device-common \
101+
-p flight-hid-types \
102+
-p flight-adapter-common \
103+
-p flight-test-helpers \
104+
-p flight-workspace-meta
105+
106+
cargo llvm-cov report --json --output-path coverage.json
107+
cargo llvm-cov report --lcov --output-path lcov.info
108+
cargo llvm-cov report --text | tee coverage.txt
109+
110+
- name: Validate coverage output
111+
run: |
112+
set -euo pipefail
113+
test -s coverage.json
114+
test -s coverage.txt
115+
test -s lcov.info
116+
117+
- name: Detect Codecov token
118+
id: codecov-token
119+
env:
120+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
121+
run: |
122+
if [ -n "${CODECOV_TOKEN:-}" ]; then
123+
echo "present=true" >> "$GITHUB_OUTPUT"
124+
else
125+
echo "present=false" >> "$GITHUB_OUTPUT"
126+
fi
127+
128+
- name: Upload coverage to Codecov (main)
129+
if: ${{ always() && github.event_name == 'push' && hashFiles('lcov.info') != '' && steps.codecov-token.outputs.present == 'true' }}
130+
uses: codecov/codecov-action@v5
131+
with:
132+
token: ${{ secrets.CODECOV_TOKEN }}
133+
files: lcov.info
134+
flags: rust-core
135+
name: openflight-rust-core
136+
fail_ci_if_error: true
137+
138+
- name: Upload coverage to Codecov (advisory)
139+
if: ${{ always() && github.event_name != 'push' && hashFiles('lcov.info') != '' && steps.codecov-token.outputs.present == 'true' }}
140+
uses: codecov/codecov-action@v5
141+
with:
142+
token: ${{ secrets.CODECOV_TOKEN }}
143+
files: lcov.info
144+
flags: rust-core
145+
name: openflight-rust-core
146+
fail_ci_if_error: false
147+
148+
- name: Write coverage receipt
149+
if: always()
150+
run: |
151+
mkdir -p target/coverage
152+
python3 - <<'PY'
153+
import json
154+
import pathlib
155+
156+
receipt = {
157+
"schema_version": 1,
158+
"repo": "OpenFlight",
159+
"lane": "coverage",
160+
"flag": "rust-core",
161+
"workflow": "Coverage",
162+
"scope": "portable-core-control-plane",
163+
"artifacts": {
164+
"coverage_json": pathlib.Path("coverage.json").exists(),
165+
"coverage_text": pathlib.Path("coverage.txt").exists(),
166+
"lcov": pathlib.Path("lcov.info").exists(),
167+
},
168+
"claim_boundary": [
169+
"execution_surface_only",
170+
"not_realtime_deadline_proof",
171+
"not_hardware_correctness",
172+
"not_simulator_adapter_correctness",
173+
"not_force_feedback_safety",
174+
"not_hil_readiness",
175+
"not_bdd_completeness",
176+
"not_fuzz_robustness",
177+
"not_release_readiness"
178+
],
179+
}
180+
181+
pathlib.Path("target/coverage/coverage-receipt.json").write_text(
182+
json.dumps(receipt, indent=2) + "\n",
183+
encoding="utf-8",
184+
)
185+
PY
186+
187+
- name: Upload coverage artifacts
188+
if: always()
189+
uses: actions/upload-artifact@v4
190+
with:
191+
name: coverage-report
192+
path: |
193+
coverage.json
194+
coverage.txt
195+
lcov.info
196+
target/coverage/coverage-receipt.json
197+
retention-days: 14
198+
199+
- name: Summarize coverage artifacts
200+
if: always()
201+
run: |
202+
{
203+
echo "## Coverage"
204+
echo ""
205+
echo "| Artifact | Present |"
206+
echo "| --- | ---: |"
207+
echo "| coverage.json | $([ -s coverage.json ] && echo yes || echo no) |"
208+
echo "| coverage.txt | $([ -s coverage.txt ] && echo yes || echo no) |"
209+
echo "| lcov.info | $([ -s lcov.info ] && echo yes || echo no) |"
210+
echo "| coverage-receipt.json | $([ -s target/coverage/coverage-receipt.json ] && echo yes || echo no) |"
211+
echo ""
212+
echo "Codecov flag: \`rust-core\`"
213+
echo "Scope: portable core/control-plane crates"
214+
} >> "$GITHUB_STEP_SUMMARY"

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Flight Hub
22

33
[![Repo](https://img.shields.io/badge/repo-EffortlessMetrics%2FOpenFlight-blue?logo=github&style=flat-square)](https://github.com/EffortlessMetrics/OpenFlight)
4+
[![CI](https://github.com/EffortlessMetrics/OpenFlight/actions/workflows/ci.yml/badge.svg)](https://github.com/EffortlessMetrics/OpenFlight/actions/workflows/ci.yml)
5+
[![Codecov](https://codecov.io/gh/EffortlessMetrics/OpenFlight/branch/main/graph/badge.svg)](https://codecov.io/gh/EffortlessMetrics/OpenFlight)
6+
[![MSRV](https://img.shields.io/badge/MSRV-1.92.0-blue.svg)](Cargo.toml)
7+
[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)
48

59
Flight Hub is a PC flight simulation input management system written in Rust. It provides a unified control plane for flight controls, panels, force feedback devices, and simulator adapters.
610

@@ -22,6 +26,8 @@ Flight Hub is an accessory/input manager that requires a simulator such as MSFS,
2226

2327
For simulator integration boundaries and compliance notes, see `docs/product-posture.md`.
2428

29+
Codecov is execution-surface telemetry only; see [Coverage](docs/ci/coverage.md) for what the badge does and does not claim.
30+
2531
## Workspace Crates
2632

2733
- **Real-time spine:** `flight-axis`, `flight-scheduler`, `flight-bus`

codecov.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
coverage:
2+
precision: 2
3+
round: down
4+
range: "50...85"
5+
6+
status:
7+
project:
8+
default:
9+
target: auto
10+
threshold: 5%
11+
informational: true
12+
flags:
13+
- rust-core
14+
15+
patch:
16+
default:
17+
target: 70%
18+
threshold: 20%
19+
informational: true
20+
flags:
21+
- rust-core
22+
23+
comment: false
24+
25+
github_checks:
26+
annotations: false
27+
28+
ignore:
29+
- "target/**"
30+
- "fuzz/**"
31+
- "benches/**"
32+
- "crates/*/benches/**"
33+
- "crates/*/examples/**"
34+
- "crates/flight-hub-examples/**"
35+
- "installer/**"

docs/ci/coverage.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Coverage
2+
3+
Codecov coverage is Rust execution-surface evidence.
4+
5+
It answers:
6+
7+
> Did tests execute this Rust surface?
8+
9+
It does not answer:
10+
11+
- whether real-time deadlines are met,
12+
- whether physical HID devices behave correctly,
13+
- whether simulator adapters are correct,
14+
- whether force-feedback output is safe,
15+
- whether hardware-in-the-loop testing passed,
16+
- whether BDD feature coverage is complete,
17+
- whether fuzzing is sufficient,
18+
- whether release readiness is proven.
19+
20+
Those are separate proof lanes.
21+
22+
## Coverage Workflow
23+
24+
The Coverage workflow runs on:
25+
26+
- push to `main`,
27+
- `workflow_dispatch`,
28+
- PRs labeled `coverage`, `full-ci`, or `ci:full`.
29+
30+
### Scope
31+
32+
The initial Codecov flag is `rust-core`, scoped to portable core/control-plane crates:
33+
34+
- flight-core
35+
- flight-axis
36+
- flight-bus
37+
- flight-scheduler
38+
- flight-rules
39+
- flight-profile
40+
- flight-units
41+
- flight-session
42+
- flight-metrics
43+
- flight-device-common
44+
- flight-hid-types
45+
- flight-adapter-common
46+
- flight-test-helpers
47+
- flight-workspace-meta
48+
49+
Hardware, simulator adapter, and force-feedback correctness are measured by separate testing lanes.
50+
51+
### Artifacts
52+
53+
Durable receipts from the Coverage workflow are:
54+
55+
- `coverage.json` — machine-readable coverage summary
56+
- `coverage.txt` — human-readable coverage report
57+
- `lcov.info` — LCOV format for Codecov upload
58+
- GitHub Actions `coverage-report` artifact (14-day retention)
59+
- Codecov dashboard (permanent link)
60+
61+
Codecov comments are disabled (quiet mode).
62+
63+
## Claim Boundary
64+
65+
Codecov coverage is **not**:
66+
67+
- proof of real-time deadline correctness,
68+
- proof of hardware/device correctness,
69+
- proof of simulator adapter correctness,
70+
- proof of force-feedback safety,
71+
- proof of HIL readiness,
72+
- proof of BDD scenario completeness,
73+
- proof of fuzz target robustness,
74+
- proof of release readiness.
75+
76+
Each of those is a separate testing lane with dedicated receipts.

0 commit comments

Comments
 (0)