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:
pushandpull_requesttargetingmain,master, ordevelop - Permissions:
contents: read,pull-requests: write,checks: write - Runner:
[self-hosted, dokploy]
Environment
NODE_VERSION: 22CI: trueFORCE_COLOR: 1NPM_CONFIG_LOGLEVEL: infoNODE_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:
- Start from the directories returned by change detection (or scan every workspace on main pushes).
- Skip entries listed in
ignored. - Inspect each
package.jsonto confirm that at least one relevant script exists and is not explicitly ignored. - Persist the remaining component paths to
/tmp/components-to-check.txtfor 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:
- Change into the component directory.
- For every check type (
typecheck,build,lint,format,test), verify the script exists and confirm the check is not listed underignore.<check>inci-ignores.json. - Run the script with
pnpm run <script>and capture the outcome. - 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-setupinstalls 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": []
}
}ignoredremoves 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
- Minimal Concurrency – Only one job is ever scheduled on the runner, so capacity spikes disappear.
- Deterministic Ordering – Components always run in a known order, which simplifies troubleshooting.
- Shared Setup – Tooling installs and caches are performed once per workflow run instead of once per matrix leg.
- 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_URLandWHATSAPP_WEB_SERVER_TEST_DATABASE_URLsecrets so coverage-bearing workspaces can reach their test databases. - The change detection workflow remains the gatekeeper for deciding when the CI job should run.