ZenoZENO

CI/CD pipelines

Continuous integration and deployment pipelines

Zeno's CI pipeline runs on every push to main and on every pull request against it.

CI pipeline

The CI pipeline runs these steps in order:

  1. Lint: Ultracite checks formatting and lint rules
  2. Type check: TypeScript checks every package
  3. Build: Turborepo builds every package and app
  4. Unit tests: Vitest runs the unit tests
  5. E2E tests: Playwright runs the end-to-end tests

Run it locally with:

pnpm ci

To rebuild without the cache, run:

pnpm ci:force

To write a dependency graph to turbo-graph.html, run:

pnpm ci:graph

The root package.json defines these scripts:

package.json
{
  "scripts": {
    "ci": "pnpm run lint && turbo run types:check build test e2e",
    "ci:force": "turbo run types:check build test e2e --force",
    "ci:graph": "turbo run types:check build test e2e --graph=turbo-graph.html"
  }
}

Turborepo tasks

turbo.json defines the pipeline order and dependencies.

GitHub Actions

Zeno's GitHub Actions workflow is .github/workflows/turbo.yml.

Caching

Turborepo caches task outputs and replays them when a task's inputs haven't changed:

  • A local cache in .turbo/
  • A remote cache on Vercel

Enable remote caching locally with:

npx turbo login
npx turbo link

To enable remote caching in GitHub Actions, uncomment these lines in .github/workflows/turbo.yml and edit them as needed:

.github/workflows/turbo.yml
  env:
    TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
    TURBO_TEAM: ${{ vars.TURBO_TEAM }}
    TURBO_CACHE: remote:rw

E2E in CI

In CI, Playwright runs with these settings:

  • An HTML report, which the workflow uploads as an artifact
  • 3 retries on failure
  • A 30-second timeout (120 seconds locally)
  • A trace recorded on the first retry, for debugging
packages/e2e/playwright.config.ts
{
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 3 : 0,
  reporter: process.env.CI ? "html" : "list",
  timeout: process.env.CI ? 30_000 : 120_000,
}