ReFlex Logo
ReFlex (Title)
Documentation
Navigation

ReFlex: GitHub CI

Table of Contents

  1. Workflows
  2. Pull Request (main)
  3. Complete workflows
  4. Test execution and reports
  5. Pages deployment
  6. Cleanup PR caches

Workflows

The workflow files under .github/workflows/ define these entry points. Reusable workflows also run when invoked by a parent, even if they have no direct PR or push trigger.

File Purpose Direct triggers
build-test-complete.yml Run .NET/server checks, emulator build and Python/gRPC/notebook tests Manual
build-test-complete-with-pages.yml Same reusable checks plus report caching and Pages deployment Push to main, manual
net-build-all.yml Build/test .NET solution and call Python/gRPC/notebook tests PR targeting main, manual
npm-build-all.yml Build, lint and test npm projects PR targeting main, push to main
electron-smoke.yml Package and start emulator and TrackingServer on native desktop runners PR (all target branches), push to main, manual
library-test.yml Test ReFlex.sln with coverage and TRX results Reusable call, manual
python-grpc-test.yml Test Python extraction, isolated gRPC service and notebooks in Docker Reusable call, manual
server-build.yml Build TrackingServer Angular frontend Reusable call, manual
server-lint.yml Lint server Reusable call, manual
server-test.yml Test Angular server frontend Reusable call, manual
emulator-build.yml Build emulator Angular frontend Reusable call, manual
shared-build.yml Build shared TypeScript types Push to main, reusable call, manual
shared-components-build.yml Build shared Angular components Push to main, reusable call, manual
server-release.yml Publish server release Release published
emulator-release.yml Publish emulator release Release published
pages-deploy.yml Build and deploy documentation Push to pages, reusable call, manual
library-readme-packages.yml Update library package documentation Matching paths changed on main, manual
cache-cleanup.yml Remove caches belonging to a closed PR PR closed

The .NET and npm PR triggers explicitly cover opened, reopened, edited and synchronize for PRs targeting main. The Electron workflow uses the default pull_request activity types and has no target-branch filter. A feature-branch push without an open PR does not trigger these checks through their push settings.

Pull Request (main)

Three entry-point workflows run for PRs targeting main:

The manual complete workflow is not the PR entry point. PR checks do not deploy Pages. cache-cleanup.yml runs when the PR closes, rather than as part of its build checks.

Complete workflows

build-test-complete.yml is manually dispatched. It calls the .NET library tests, TrackingServer frontend build/lint/tests, emulator frontend build and Python/gRPC/notebook tests. It does not cache the combined documentation reports or deploy Pages.

These complete workflows are separate from the npm command npm run build-complete: they do not invoke all npm workspace tests or the Electron smoke matrix. The npm and Electron entry-point workflows run independently according to their own triggers.

build-test-complete-with-pages.yml runs on pushes to main or manually. It starts the same checks and adds these dependencies:

flowchart TD
    L[Library tests] --> C[Collect and cache library/server reports]
    S[Server frontend tests] --> C
    C --> P[Deploy Pages]
    G[Python extraction, gRPC and notebooks] --> P

update_pages requires both collect-cache_data and test_python_grpc to succeed. Server build, server lint and emulator build are parallel jobs; the current Pages dependency list does not explicitly gate deployment on those three jobs.

Test execution and reports

npm and Angular

npm-build-all.yml uses .github/actions/npm-install, which selects Node.js 22 and caches npm downloads using the root lockfile. Every run installs the locked workspace dependencies at the repository root with npm ci --include=dev; cached node_modules directories do not bypass installation. The workflow then executes:

npm run build-complete

The root script expands to four sequential phases:

npm run build --workspaces --if-present
npm run lint
npm run test:lint
npm run test-ci --workspaces --if-present

The next phase starts only if the preceding command succeeds. --if-present applies to builds and tests and skips workspaces without those scripts; it does not suppress failures of existing scripts. Lint runs once from the repository root and fails on errors or warnings (--max-warnings 0). Builds follow the workspace order in the root package.json, with shared types and Angular components built before their consumers. Angular projects are configured centrally in the root angular.json.

All ten npm workspaces have a build script. Their additional checks are:

Workspace Lint test-ci
packages/reflex-shared-types ESLint No script
packages/reflex-angular-components ESLint Vitest, headless Chromium, coverage
tools/ReFlex.TrackingServer/ClientApp ESLint Vitest, headless Chromium, coverage
tools/emulator ESLint Vitest, headless Chromium, coverage
tools/gestenrecorder ESLint Vitest, headless Chromium, coverage
tools/logging ESLint No script
examples/basic-angular ESLint Vitest, headless Chromium, coverage
examples/basic-react ESLint No script
examples/basic-vue ESLint (JavaScript and Vue templates) Vitest with happy-dom
examples/shared-components-demo ESLint Vitest, headless Chromium, coverage

The Angular CI commands disable watch mode; the Vue command uses vitest run. Gestenrecorder is included through its own test-ci script. Interactive test scripts are not used by build-complete. Before local execution, run npx playwright install chromium. The shared npm-install action installs Chromium (including required OS dependencies) for CI.

ESLint uses the single root eslint.config.js. Every workspace also has a lint script for local checks; Angular CLI lint targets use the same configuration through @angular-eslint/builder:lint. Repository lint covers application and library sources, specs, mocks, test support files, production environments, Angular external and inline templates, React TSX, Vue single-file components, Electron entry points and repository build scripts. Only generated outputs, dependency directories and build caches are ignored. Per-workspace tsconfig.eslint.json files include tests and build configurations (.ts, .tsx, .mts, .cts) for type-aware linting without adding test helpers to production entry points.

The shared TypeScript rule adapter is scripts/eslint/typescript.config.cjs. It retains the GTV policy, migrates renamed/stylistic TypeScript rules and explicitly restores historical ESLint checks that newer presets omit, including no-undef, no-unreachable and no-redeclare. Necessary decorated Angular test mocks are allowed by the corresponding rule option. Angular template checks include accessibility; Vue templates use eslint-plugin-vue. Unused suppression directives are errors. AngularJS’s eslint-plugin-angular is not required.

npm run test:lint checks source-file coverage, workspace scripts, historical rule severities, Angular template checks and actual React-hook/Vue-template violations. npm run lint-fix applies automatic fixes; remaining findings must be fixed before CI succeeds. Standalone lint commands require the shared packages to have been built, as their consumers resolve the generated declarations. build-complete ensures this ordering. Angular tests use the applications’ zoneless scheduling, including the change-detection regression suites. Zoneless regression cases live in the corresponding component specs; shared typed test contexts and data modules live in test-utils folders.

All six Angular projects use @angular/build:unit-test with Vitest and Playwright Chromium. Application builds use @angular/build:application; the component library uses @angular/build:ng-packagr. The library has a separate test-build target to include its global SCSS in browser tests. Coverage (HTML, text summary, LCOV and Cobertura) is written to separate project folders under test/artifacts/coverage/. JUnit files under test/artifacts/tests/ also have distinct names. npm-build-all.yml verifies these outputs with scripts/verify-angular-reports.cjs and uploads them as angular-test-reports, including available reports on failure.

The separate reusable server-test.yml builds shared types and components, then runs npm run test:server. It uploads coverage as Angular Test Report (ReFlex TrackingServer) and publishes test/artifacts/tests/junit-test-results.xml through the JUnit report action. Report verification checks all coverage formats and a nonempty, successful JUnit report. Coverage upload and JUnit publishing run on success or failure. The complete workflow with Pages collects this server coverage artifact alongside the .NET library report; it does not collect all npm workspace reports.

Electron startup smoke tests

electron-smoke.yml checks the packaged applications independently of Angular unit tests and web builds. Its matrix contains both emulator and server for each target, resulting in ten jobs:

Target suffix OS / architecture Runner
win Windows x64 windows-latest
osx macOS x64 macos-15-intel
osx-arm64 macOS ARM64 macos-15
linux Linux x64 ubuntu-24.04
linux-arm64 Linux ARM64 ubuntu-24.04-arm

Each job installs Node.js 22 and npm dependencies, then builds an unpacked application on its native OS/architecture:

npm run build:<application>:electron-<target> -- --dir
npm run smoke:electron -- <application>

Server jobs also install the .NET SDK selected by global.json. Linux jobs install display dependencies and run the smoke command through xvfb-run -a. Builds are unsigned and do not publish installers or require signing secrets.

scripts/smoke-electron.cjs starts the packaged executable and waits up to 120 seconds for its Angular UI: the emulator canvas or the TrackingServer home page. For TrackingServer, it also checks that the bundled backend answers /api/versionInfo successfully with a JSON array. It fails on early process exit, startup timeout or recorded renderer exceptions, and checks that the process remains alive for another two seconds after the initial render. The application and its child processes are terminated after the check.

Startup logs and a screenshot, when available, are uploaded even after a failure as electron-smoke-<application>-<target> from test/artifacts/electron/<application>/. Matrix jobs have a 30-minute timeout and fail-fast: false; one target’s failure does not cancel the remaining targets. A newer workflow run for the same ref cancels an older in-progress smoke run.

These are startup checks, not full interaction or sensor tests. They do not publish a release or deploy Pages. See Electron builds and startup checks for local commands and packaging details.

.NET

The shared .NET setup reads the SDK version from global.json and restores workloads and dependencies for ReFlex.sln. On Windows, the MAUI example selects its Windows target rather than also requesting Mac Catalyst.

Both .NET test workflows explicitly execute ReFlex.sln with configuration CI and platform x64. InteractionTests is part of that solution, so its raster, classification and observer-pipeline regressions are included without a separate test command. This includes the SingleTouch regression that retains multiple historical IDs internally while publishing at most one point after smoothing.

Python, gRPC and notebooks

python-grpc-test.yml uses ubuntu-latest with a 20-minute job timeout. It builds the notebook target of examples/grpc-service/Dockerfile and runs three separate steps:

docker build -f examples/grpc-service/Dockerfile --target notebook -t reflex-grpc-ci .
docker run --rm --workdir /app reflex-grpc-ci python -m unittest discover -s tests -v
docker run --rm --workdir /app reflex-grpc-ci python -m unittest discover -s /app/example/tests -v
docker run --rm reflex-grpc-ci python /app/example/tests/check_notebook.py

The extraction tests include the unchanged 640 × 480 recording at Skip 0, 1 and 3. The gRPC tests use a private listener. The notebook check executes both demo and observe and verifies rendered plots. No sensor hardware, live service or published container ports are required.

After a successful image build, the gRPC and notebook steps also run if an earlier test step fails, unless the workflow has been cancelled. Failures still fail the job. Results are currently written to the Actions logs; this workflow does not generate a separate Python coverage or JUnit artifact. These tests do not constitute a C#-to-Python end-to-end test or a Compose startup test.

See the gRPC recipe and template for the example and test data.

Pages deployment

pages-deploy.yml copies repository documentation using scripts/copy_docs.sh, downloads the pages-test-reports artifact from the current workflow run under docs/test, builds the site with Jekyll and deploys the Pages artifact. Both before and after Jekyll, it checks the library and server HTML entry points. The existing server URL test/server/report/reflex-tracking-server/index.html is preserved.

In the complete workflow on main, report collection uploads a combined artifact and saves a cache with a unique run-specific key before deployment, and the Python test job must succeed. A direct manual invocation of pages-deploy.yml or a push to pages does not run these tests or impose that dependency. Such a deployment restores the latest compatible test-reports-<run-id>-<attempt> cache (with a legacy test-reports fallback); cached reports can be older than the source documentation. GitHub caches are scoped to branches, with access to eligible default-branch caches.

The Pages dependency graph does not wait for the independent npm-build-all.yml or electron-smoke.yml workflows.

Cleanup PR caches

cache-cleanup.yml removes caches for a PR when it closes. PR-scoped caches are generally no longer useful after that PR has been closed.

⬆ back to top