OpenHuman Two-Lane CI Model: Understanding CI Lite vs CI Full and the 80% Coverage Gate

OpenHuman uses a dual-track continuous integration system where CI Lite enforces an 80% diff-coverage gate on every pull request to main using targeted test runs, while CI Full executes the complete test suite—including Playwright and cross-platform desktop E2E tests—on the release branch before production deployment.

The tinyhumansai/openhuman repository implements a sophisticated CI strategy that balances rapid developer feedback with rigorous release quality. By splitting validation into two distinct lanes, the project ensures that daily development moves quickly while guaranteeing that every release candidate undergoes comprehensive testing. This architecture centers on a strict diff-coverage gate that requires all new code to be sufficiently exercised by tests before merging.

The Two-Lane CI Architecture

OpenHuman’s pipeline is explicitly divided into CI Lite and CI Full, each defined in separate workflow files and triggered by different branch events.

CI Lite: Fast Feedback for Development

CI Lite is defined in .github/workflows/ci-lite.yml and runs on every push to main and every pull request targeting main or release. This lane prioritizes speed by testing only what changed:

  • Frontend testing – Vitest executes only tests importing files modified under app/src/ using the --changed flag.
  • Rust testing – cargo llvm-cov runs with a libtest filter derived from changed source directories (src/<a>/<b>/…).
  • Quality checks – Lint, format, and static analysis run in parallel.
  • Coverage enforcement – The 80% diff-coverage gate blocks merges if changed lines lack sufficient test coverage.

CI Full: Comprehensive Release Validation

CI Full is defined in .github/workflows/ci-full.yml and triggers only on pushes to the long-lived release branch and PRs targeting release. This lane executes the exhaustive test matrix:

  • Complete Vitest and Rust unit test suites.
  • Rust mock-backend E2E tests.
  • Playwright UI tests (run as a non-blocking signal; flaky tests do not block merge).
  • Full desktop-E2E matrix across Linux, macOS, and Windows.

Results aggregate behind the CI Full Gate check, which must pass before a release is cut.

How the 80% Diff-Coverage Gate Works

The coverage gate is enforced exclusively in the CI Lite lane to ensure all new code entering main meets quality standards. The implementation relies on a four-step process coordinated by shell scripts in the repository.

Step 1: Identify Changed Lines

GitHub Actions provides the list of files modified in a pull request. The system uses this list to scope all subsequent operations, ensuring the pipeline ignores unchanged legacy code when calculating coverage percentages.

Step 2: Execute Targeted Tests

The scripts scripts/ci/vitest-changed-coverage.sh (frontend) and scripts/ci/rust-coverage-changed.sh (backend) invoke the appropriate test runners with change-aware filters:

  • Frontend: Vitest runs with --changed to select only relevant tests.
  • Rust: cargo llvm-cov receives flags limiting execution to test targets matching the changed source directories.

Step 3: Calculate and Enforce Coverage

Both scripts generate LCOV reports. The diff-cover utility then calculates the percentage of changed lines covered by tests. If this percentage falls below 80%, the script exits with a non-zero status, failing the CI Lite job and preventing the pull request from merging.

Fallback for Configuration Changes

When changes touch configuration files (e.g., Cargo.toml, lockfiles, or Vitest config), the changed-file strategy becomes insufficient. In these cases, the scripts automatically fallback to running the full test suite to guarantee coverage on the broader impact of these modifications.

Promotion Flow from Main to Release

Code moves from development to production through a structured promotion process:

  1. Developers merge feature branches into main after passing the CI Lite diff-coverage gate.
  2. Maintainers trigger the promotion workflow (promote-main-to-release.yml), creating a merge commit from main into release.
  3. The CI Full lane runs on this commit, providing the final safety net with complete UI and desktop E2E validation.
  4. Only after CI Full passes is a production release cut from the release branch.

Running Coverage Checks Locally

Developers can verify diff-coverage locally before submitting a pull request using the same scripts invoked in CI:


# Install required tooling

cargo install cargo-llvm-cov diff-cover
npm install -g vitest

# Execute the coverage scripts

./scripts/ci/vitest-changed-coverage.sh
./scripts/ci/rust-coverage-changed.sh

Both commands print the percentage coverage of changed lines and abort with exit code 1 if the result falls below the 80% threshold, mirroring the behavior of the CI Lite gate.

Key Implementation Files

The two-lane CI model and coverage gate rely on these specific files in the tinyhumansai/openhuman repository:

Summary

  • CI Lite provides rapid feedback on every PR to main by running scoped tests and enforcing an 80% diff-coverage gate via .github/workflows/ci-lite.yml.
  • CI Full runs the exhaustive test suite—including Playwright and desktop E2E tests—only on the release branch via .github/workflows/ci-full.yml.
  • The coverage gate uses diff-cover on LCOV reports generated by scripts/ci/vitest-changed-coverage.sh and scripts/ci/rust-coverage-changed.sh.
  • Configuration changes trigger a fallback to full-suite testing to ensure accurate coverage metrics.
  • Code promotes from main to release through a manual workflow that triggers the CI Full gate as the final quality checkpoint.

Frequently Asked Questions

What is the 80% diff-coverage gate in OpenHuman?

The 80% diff-coverage gate is a quality checkpoint enforced in the CI Lite lane that requires at least 80% of lines modified in a pull request to be covered by tests. It is implemented using the diff-cover utility on LCOV reports generated by targeted Vitest and cargo llvm-cov runs.

When does CI Full run instead of CI Lite?

CI Full runs on every push to the release branch and on pull requests targeting release, whereas CI Lite runs on pushes to main and PRs targeting main or release. CI Full executes the complete test matrix including cross-platform desktop E2E tests, while CI Lite runs only tests relevant to changed files.

How can I check if my changes meet the coverage requirement before opening a PR?

Run the scripts/ci/vitest-changed-coverage.sh and scripts/ci/rust-coverage-changed.sh scripts locally after installing cargo-llvm-cov, diff-cover, and Vitest. These scripts calculate coverage only on your changed lines and exit with an error if the result is below 80%, identical to the CI Lite behavior.

What happens if I modify configuration files like Cargo.toml?

If your changes touch configuration files (lockfiles, Cargo.toml, Vitest config), the CI Lite scripts detect this and fallback to running the full test suite rather than the scoped changed-file tests. This ensures that broad configuration changes are validated against the entire codebase to prevent coverage gaps.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →