# How OpenHuman's Two-Lane CI Model Ensures Test Coverage Before Merges

> Discover how OpenHuman's two-lane CI model guarantees test coverage before merges. CI Lite checks code on pull requests, CI Full validates release branches for robust quality assurance.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: how-to-guide
- Published: 2026-08-27

---

**OpenHuman enforces mandatory test coverage through a dual-pipeline system where CI Lite validates changed code with an 80% coverage threshold on every pull request, while CI Full runs the complete test suite against the release branch to catch integration regressions before production deployment.**

OpenHuman (tinyhumansai/openhuman) implements a sophisticated continuous integration strategy that balances developer velocity with quality assurance. The repository employs two distinct pipelines—**CI Lite** and **CI Full**—that work sequentially to guarantee no code reaches production without adequate test coverage. This architecture ensures rapid feedback during development while maintaining rigorous standards for releases.

## The Two-Lane CI Architecture Explained

The CI system operates on a progressive validation principle. **CI Lite** provides immediate feedback on incremental changes, while **CI Full** serves as a comprehensive safety net before release. This separation allows developers to iterate quickly on feature branches while ensuring that integrated code meets enterprise-grade quality standards.

According to the source configuration in `tinyhumansai/openhuman`, the pipelines are defined in [`.github/workflows/ci-lite.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-lite.yml) and [`.github/workflows/ci-full.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-full.yml), with orchestration scripts located in `scripts/ci/`.

## CI Lite Pipeline: Selective Testing for Rapid Feedback

CI Lite executes on every push to `main` and every pull request targeting `main` or `release` branches. It focuses exclusively on files modified in the current changeset to minimize execution time while maintaining coverage standards.

### Trigger Conditions and Scope

The workflow triggers are configured to run when:

- Code is pushed to the `main` branch
- Pull requests are opened against `main` or `release` branches

This ensures that developers receive immediate validation without waiting for the full matrix to complete.

### Selective Test Execution

In [`.github/workflows/ci-lite.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-lite.yml), the pipeline identifies changed files and executes targeted test suites. For TypeScript components in `app/src/**`, the workflow runs Vitest with change detection:

```yaml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run changed Vitest tests
        run: pnpm test:coverage --changed

```

For Rust components, the pipeline invokes [`./scripts/ci/rust-coverage-changed.sh`](https://github.com/tinyhumansai/openhuman/blob/main/./scripts/ci/rust-coverage-changed.sh), which filters test execution using `cargo llvm-cov` to examine only the modified domains:

```bash
#!/bin/bash

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

cargo llvm-cov --lib --filter changed

```

### Enforcing the 80% Coverage Threshold

CI Lite mandates a **minimum 80% line coverage on all changed lines**. The workflow integrates coverage analysis tools—`diff-cover` for Vitest outputs and `cargo-llvm-cov` for Rust artifacts—to calculate differential coverage. If the threshold is not satisfied, the job fails and blocks the merge.

The enforcement logic appears in the workflow configuration:

```yaml
- name: Verify coverage on changed lines
  run: |
    pnpm coverage:diff-check --threshold=80
    ./scripts/ci/verify-rust-diff-cov.sh 80

```

## CI Full Pipeline: Comprehensive Pre-Release Validation

While CI Lite validates incremental changes, CI Full ensures that the entire codebase remains stable before release promotion. This pipeline executes the exhaustive test matrix that would be impractical to run on every commit.

### Release Branch Protection

CI Full triggers exclusively on pushes to the long-lived `release` branch. This includes merges from `main` and direct commits, ensuring that only fully validated code reaches production environments.

### Complete Test Matrix Execution

Defined in [`.github/workflows/ci-full.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-full.yml), the pipeline executes:

- **Complete Vitest suite**: All unit tests across the TypeScript codebase
- **Rust integration tests**: Full `cargo test` execution with the mock backend
- **End-to-end validation**: Playwright UI specifications and desktop application E2E tests across Windows, macOS, and Linux runners

```yaml
jobs:
  full-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: pnpm test
      - run: pnpm test:e2e
      - run: ./scripts/test-rust-with-mock.sh --all

```

### The CI Full Gate

The pipeline aggregates results through the **CI Full Gate** check, implemented as an artifact upload step that signals completion:

```yaml
- name: CI Full Gate
  uses: actions/upload-artifact@v3
  with:
    name: ci-full-gate
    path: ./ci-full-results/

```

Branch protection rules require this gate to pass before any code merges into `release`, preventing regressions that selective testing might miss.

## Implementation Details and Source Configuration

The orchestration relies on helper scripts in `scripts/ci/` that calculate file differentials and invoke appropriate test filters. The [`ci-lite.sh`](https://github.com/tinyhumansai/openhuman/blob/main/ci-lite.sh) script determines which Vitest and Rust tests correspond to the current PR's modifications, while [`ci-full.sh`](https://github.com/tinyhumansai/openhuman/blob/main/ci-full.sh) coordinates the cross-platform E2E execution.

Key implementation files include:

- [`.github/workflows/ci-lite.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-lite.yml): Defines the fast feedback pipeline and 80% coverage enforcement
- [`.github/workflows/ci-full.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-full.yml): Configures the exhaustive pre-release validation matrix
- [`scripts/ci/ci-lite.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/ci-lite.sh): Computes changed file sets for selective testing
- [`scripts/ci/ci-full.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/ci-full.sh): Orchestrates full suite execution including Playwright and desktop E2E

## Summary

- **OpenHuman's two-lane CI model** separates rapid validation from comprehensive verification to balance speed and quality.
- **CI Lite** runs on every PR to `main`, executing only tests for changed files and requiring **≥80% line coverage** on modifications before merge.
- **CI Full** activates on the `release` branch, running the complete test suite—including Vitest, Rust units, Playwright E2E, and desktop cross-platform tests—to prevent integration regressions.
- **Branch protection rules** enforce both pipelines, ensuring no code reaches production without passing selective coverage checks and full matrix validation.
- The implementation resides in [`.github/workflows/ci-lite.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-lite.yml) and [`.github/workflows/ci-full.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/ci-full.yml), supported by differential coverage scripts in `scripts/ci/`.

## Frequently Asked Questions

### What happens if CI Lite coverage falls below 80%?

The workflow job fails and GitHub blocks the pull request merge. Developers must add tests for the uncovered lines or modify the implementation to reduce untested branches before the PR can proceed.

### Why does CI Full only run on the release branch rather than every PR?

Running the complete matrix—including Rust mock-backend E2E and Playwright desktop tests across three operating systems—requires significant runner resources and time. By restricting CI Full to the `release` branch, OpenHuman preserves developer velocity on feature branches while guaranteeing integration stability before deployment.

### How does OpenHuman detect which tests to run in CI Lite?

The [`scripts/ci/ci-lite.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/ci-lite.sh) script compares the current branch against the merge base to identify modified files. It then maps these files to corresponding Vitest specifications (`app/src/**` patterns) and Rust crates, invoking `pnpm test:coverage --changed` and `cargo llvm-cov` with appropriate filters.

### Can CI Lite pass while CI Full fails?

Yes. CI Lite validates only the changed code, so it might miss integration issues between components. If CI Full subsequently fails on the `release` branch, the merge that promoted the code is identified as faulty, triggering a revert or hotfix process before the code reaches production.