OpenHuman Two-Lane CI Model: CI Lite vs CI Full and Safety Gates Explained
OpenHuman uses a dual-track continuous integration system where CI Lite provides rapid feedback on every push to main while CI Full performs exhaustive verification before any code reaches the release branch.
The OpenHuman repository implements a sophisticated continuous integration strategy that balances developer velocity with release safety. By splitting the pipeline into two distinct lanes, the project ensures that contributors receive immediate feedback during development while maintaining rigorous quality standards for production releases. This two-lane CI model employs path-based change detection and multiple safety gates to enforce code quality, test coverage, and architectural integrity.
Understanding the Two-Lane CI Architecture
OpenHuman's CI/CD pipeline operates on two complementary tracks that run different workloads based on the target branch and the nature of the changes.
CI Lite: The Fast Feedback Lane
CI Lite triggers on pushes to main and pull requests targeting main or release. This lane focuses on speed and precision, running only the checks and tests relevant to the files that actually changed.
The lane uses the dorny/paths-filter action in .github/workflows/ci-lite.yml to detect which areas of the repository were modified. It sets output flags such as frontend, rust-core, rust-tauri, i18n, docs, and scripts to drive conditional job execution. When frontend files change, only Vitest runs against the affected files. When Rust code changes, only the impacted crates undergo testing via cargo-llvm-cov.
Key characteristics of CI Lite include:
- Partial test execution scoped to changed files
- ≥ 80% diff-cover enforcement on modified lines using the
diff-covertool - Quality checks including Prettier, ESLint, i18n coverage validation (
pnpm i18n:check), and generated-docs drift detection (pnpm docs:check) - Script self-tests to validate tooling changes
CI Full: The Exhaustive Verification Lane
CI Full activates on pushes to release, pull requests targeting release, and the manual promote-main-to-release workflow. This lane runs the complete test matrix regardless of which files changed, ensuring every release candidate passes comprehensive validation.
The full lane executes:
- Complete unit suites via
.github/workflows/test-reusable.ymlcovering frontend Vitest, Rust core, and Rust-Tauri - Rust E2E tests against the mock backend with checksum-pinned native test modules (TinyMemory, TinyJuice, etc.)
- Playwright web E2E tests using a cached build artifact to avoid rebuilding the heavy web bundle on every run
- Desktop E2E on Linux (macOS and Windows currently disabled following the Wry migration)
Only after all these jobs succeed does the CI Full Gate permit merging into release.
CI Lite Implementation and Path-Based Optimization
The efficiency of CI Lite relies on intelligent change detection defined in .github/workflows/ci-lite.yml starting at line 47.
Changed-Area Detection
The workflow begins with a changes job that produces boolean outputs indicating which domains require testing:
- name: Detect changed paths
id: filter
uses: dorny/paths-filter@v2
with:
filters: |
frontend:
- 'frontend/**'
rust-core:
- 'src/core/**'
rust-tauri:
- 'src-tauri/**'
Downstream jobs check these outputs to determine execution. For example, the frontend test job includes if: needs.changes.outputs.frontend == 'true', ensuring Vitest runs only when relevant files change.
Partial Test Execution and Coverage Gates
When changes occur, the pipeline runs scoped tests rather than the full suite. For Rust components, this means executing cargo test only on crates listed in rust-core-src-files (or the full suite if rust-core-full equals true). The cargo-llvm-cov integration generates coverage reports specifically for the diff, and the diff-cover tool enforces the ≥ 80% coverage threshold on changed lines.
Quality gates in CI Lite also validate:
- Lint and formatting compliance
- i18n coverage consistency
- Documentation generation drift
- Script functionality via self-tests
CI Full Implementation and the Final Gate
When code approaches release, .github/workflows/ci-full.yml (lines 60-84) orchestrates comprehensive validation through the exhaustive lane.
The Full Test Matrix
CI Full reuses the test workflow defined in test-reusable.yml with all flags enabled (run_unit, run_rust_core, run_rust_tauri). It then proceeds to integration testing:
- Rust E2E: Boots the mock backend and runs
pnpm test:rust:e2eagainst the full native module suite - Playwright Web E2E: Executes after the
build-playwright-e2e-artifactjob creates and caches the web build - Desktop E2E: Runs through the reusable workflow
e2e-reusable.ymlon the Linux matrix
The CI Full Gate Job
After all test jobs complete, the ci-full-gate job aggregates results to enforce the final merge requirement:
- name: Require all CI Full jobs to pass
run: |
declare -A results=(
["Full Unit Suites"]="${{ needs['unit-tests'].result }}"
["Rust E2E"]="${{ needs['rust-e2e'].result }}"
["Build Playwright E2E Artifact"]="${{ needs['build-playwright-e2e-artifact'].result }}"
["Desktop E2E"]="${{ needs['e2e-desktop'].result }}"
)
# Fails if any result is not success or skipped
This gate ensures that only fully validated code reaches the release branch, protecting production releases from partial test passes or transient failures.
Shared Safety Gates Across Both Lanes
Both CI lanes enforce additional architectural and security constraints through specialized guard jobs defined in ci-lite.yml:
Feature-Gate Smoke Test (rust-feature-gate-smoke): Builds crates with --no-default-features to ensure facade and stub signatures remain in sync when domain gates are disabled.
Kernel-Floor Guard: Executes scripts/check-kernel-floor.sh to verify that the minimal dependency set required by embedding hosts does not grow unintentionally, keeping the embedded-host profile lightweight.
Dependency Simulation Guard: Validates scripts/dep-sim.py against expected dependency counts to detect mismatches between the simulator and Cargo's actual graph.
Feature-Forwarding Gate: Runs scripts/ci/check-feature-forwarding.mjs to confirm that the Tauri shell forwards all core product features correctly, ensuring the desktop UI receives the same feature set as the core binary.
Toolchain-Image Drift Guard: Executes scripts/ci/check-toolchain-image.mjs to verify that CI Docker images and Rust toolchain pins match repository definitions, preventing supply-chain drift.
Orchestration IP Gate: Runs scripts/ci/orch-ip-gate.sh to block any resurrected local-brain orchestration code from re-entering the repository.
Test-Inventory Guard: Validates that every controller domain referenced in src/core/all.rs has a corresponding test and that no orphaned test files exist.
Extending the Two-Lane Model
When adding new domains to OpenHuman, developers must update the path filters and conditional logic. To add a new Rust domain called "analytics":
# In .github/workflows/ci-lite.yml
# 1. Extend the paths-filter block
filters: |
analytics:
- 'src/analytics/**'
# 2. Add conditional job
- name: Rust Analytics Checks
if: needs.changes.outputs.analytics == 'true'
runs-on: ubuntu-22.04
steps:
- name: Run analytics unit tests
run: cargo test -p analytics
For Playwright tests, ensure spec files reside under src/** or app/** so the hashFiles call in build-playwright-e2e-artifact automatically invalidates the cache when they change.
Summary
- CI Lite provides rapid, change-scoped feedback on every push to
main, running only affected tests and enforcing 80% diff-cover, lint, formatting, and i18n checks. - CI Full executes comprehensive validation including full unit suites, Rust E2E, Playwright web tests, and desktop E2E before any code reaches the
releasebranch. - The CI Full Gate job consolidates all exhaustive test results and blocks merges unless every component passes.
- Shared guard jobs protect architectural boundaries, feature-gate correctness, kernel dependency limits, and supply-chain integrity across both lanes.
- Path-based detection via
dorny/paths-filterinci-lite.ymldrives the conditional execution that makes the fast lane efficient.
Frequently Asked Questions
What triggers CI Lite versus CI Full in OpenHuman?
CI Lite triggers on pushes to main and pull requests targeting main or release. CI Full triggers only on pushes to release, PRs targeting release, and the manual promote-main-to-release workflow. This ensures developers get fast feedback during active development while exhaustive verification occurs only when code is ready for release.
How does OpenHuman enforce the 80% coverage requirement?
The CI Lite lane uses cargo-llvm-cov to generate coverage reports for changed Rust files and Vitest for changed frontend files. The diff-cover tool then analyzes these reports to ensure modified lines meet the ≥ 80% coverage threshold. If the diff coverage falls below this percentage, the check fails and blocks the pull request.
What happens if the CI Full Gate fails?
If any job in the exhaustive lane fails—including full unit suites, Rust E2E, Playwright tests, or desktop E2E—the ci-full-gate job in ci-full.yml detects the failure and terminates with an error. This prevents the pull request from merging into release and blocks the creation of a production release until all issues are resolved and the pipeline passes.
Can I run CI Full locally or on my feature branch?
While CI Full automatically runs when targeting the release branch, developers can manually trigger the full test matrix locally by running the same commands the CI uses: cargo test for all Rust workspace members, pnpm test:rust:e2e for Rust integration tests, and pnpm exec playwright test for web E2E. However, the gated release branch protection ensures only CI-validated code reaches production.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →