NexisChat Docs
ActionsWorkflows

Main CI Workflow

Runs all CI quality checks sequentially inside a single job to minimize runner concurrency.

The main CI workflow now performs every quality check inside one long-running job. Instead of creating a matrix and fanning out across multiple runners, the workflow gathers the components that need verification and loops through them sequentially.

Triggers & Permissions

  • Events: push and pull_request targeting main, master, or develop
  • Permissions: contents: read, pull-requests: write, checks: write
  • Runner: [self-hosted, dokploy]

Environment

  • NODE_VERSION: 22
  • CI: true
  • FORCE_COLOR: 1
  • NPM_CONFIG_LOGLEVEL: info
  • NODE_OPTIONS: --max-old-space-size=4096

Node and pnpm versions stay aligned by relying on the internal pnpm-setup action, which installs the toolchain declared in the lockfile.

Job Overview

  • detect-changes – Reusable workflow that reports the set of modified workspaces. On main branch pushes it returns the full workspace list so every component gets checked.
  • ci-check – Single job that installs tooling, discovers the components to validate, and runs every applicable script (typecheck, build, lint, format, test) one component at a time. Coverage uploads are attempted at the end if a component produced coverage/lcov.info.

There is no matrix generation job anymore and no follow-up performance summary. All logic lives inside ci-check so GitHub Actions only schedules one job for the CI run.

Component Discovery

The discover step inside ci-check combines the data from change detection with the repository’s ci-ignores.json file:

  1. Start from the directories returned by change detection (or scan every workspace on main pushes).
  2. Skip entries listed in ignored.
  3. Inspect each package.json to confirm that at least one relevant script exists and is not explicitly ignored.
  4. Persist the remaining component paths to /tmp/components-to-check.txt for the execution loop.

If no components qualify, the job exits early without running any checks.

Sequential Checks Per Component

For each component path that survives discovery:

  1. Change into the component directory.
  2. For every check type (typecheck, build, lint, format, test), verify the script exists and confirm the check is not listed under ignore.<check> in ci-ignores.json.
  3. Run the script with pnpm run <script> and capture the outcome.
  4. Emit a per-component mini summary and track failures so the job can fail after all components finish.

The format check prefers format:check, then format, then prettier. The test check only runs when test:coverage is defined so the Codecov upload has predictable output.

Caching and Tooling Setup

  • ./.github/actions/pnpm-setup installs pnpm, configures the global store, and restores the workspace cache.
  • Bun is installed up front because several workspaces rely on it in their scripts.
  • A lightweight cache step restores shared caches (.turbo, .eslintcache, .prettiercache). Per-component caches live inside each project directory and are populated by their own tooling during the checks.

Unified Ignore File

ci-ignores.json still drives the allowlist/denylist logic:

{
  "ignored": ["apps/evolution-api-lite", "apps/subscription"],
  "ignore": {
    "typecheck": [],
    "build": ["packages/eslint-config"],
    "lint": [],
    "format": [],
    "test": []
  }
}
  • ignored removes a workspace entirely from the CI run.
  • ignore.<check> skips just that check for the listed workspace.
  • If every check for a workspace is skipped, discovery drops the component so unnecessary work never starts.

Coverage Uploads

After all components finish, the workflow scans /tmp/components-to-check.txt and uploads any coverage/lcov.info files it finds. If CODECOV_TOKEN is missing the step exits gracefully, so forks can run the workflow without secrets while the main repository still benefits from coverage reporting.

Benefits of the Single-Job Model

  1. Minimal Concurrency – Only one job is ever scheduled on the runner, so capacity spikes disappear.
  2. Deterministic Ordering – Components always run in a known order, which simplifies troubleshooting.
  3. Shared Setup – Tooling installs and caches are performed once per workflow run instead of once per matrix leg.
  4. Centralized Logging – Every check summary is printed in a single job log, making it easier to spot patterns or compare components.

Operational Notes

  • Failures do not short-circuit the loop. All components run, and the job fails at the end if any component reported an error.
  • Add SERVER_TEST_DATABASE_URL and WHATSAPP_WEB_SERVER_TEST_DATABASE_URL secrets so coverage-bearing workspaces can reach their test databases.
  • The change detection workflow remains the gatekeeper for deciding when the CI job should run.