Skip to content

fix(ci): orchestrate builds & type-checks from the repo root via Turborepo#4

Merged
Irere123 merged 4 commits into
stagingfrom
fix/ci-root-turbo-orchestration
Jun 17, 2026
Merged

fix(ci): orchestrate builds & type-checks from the repo root via Turborepo#4
Irere123 merged 4 commits into
stagingfrom
fix/ci-root-turbo-orchestration

Conversation

@Irere123

Copy link
Copy Markdown
Owner

Problem

CI ran per-app commands (bun run --cwd apps/<app> ...), bypassing Turbo's
dependency graph. A bare vite build for web does not build
@lemma/headless first — and @lemma/headless/dist is gitignored — so a fresh
CI checkout could build (and deploy) web against a missing/stale workspace
dependency. The previous turbo config was also inconsistent: the task was
named check-types while every workspace's script is typecheck, so
turbo check-types only ever checked web.

Fix — orchestrate from the root with Turborepo

  • turbo.json: check-typestypecheck (matches the script name used by
    every workspace) with dependsOn: ["^build"], so packages type-check against
    their dependencies' emitted declarations.
  • root package.json: add build (turbo build) and typecheck
    (turbo typecheck).
  • @lemma/email: build (react-email preview build) → preview:build, to
    keep it out of the Turbo build graph. Nothing consumes its output (the API
    imports @lemma/email as source) and it's flaky to build (ENOTEMPTY on its
    .react-email scratch dir, now gitignored).
  • ci.yaml: four per-app jobs → two root jobs:
    • verify (blocking): bun run build + bunx turbo typecheck --filter='!web'
    • quality (advisory, continue-on-error): biome:check + turbo typecheck --filter=web
  • deploy-web.yaml: bunx turbo build --filter=web (builds @lemma/headless
    web in order) then wrangler deploy the already-built worker.
  • deploy-api.yaml: type-check via bunx turbo typecheck --filter=@lemma/api.
  • docs/DEPLOYMENT.md: document the root/Turbo orchestration model.

Verified locally

  • turbo build@lemma/headless#build then web#build, green (no email build).
  • turbo typecheck --filter='!web' (api + packages) → green.
  • Simulated a clean checkout (rm -rf packages/headless/dist): turbo build --filter=web
    rebuilds @lemma/headless/dist first, then builds web — the exact breakage
    the old per-app path missed.
  • turbo typecheck --filter=web builds headless first, then surfaces only the
    known pre-existing web errors (stray react-router import + TS6307
    project-reference) — handled by the advisory job.

🤖 Generated with Claude Code

Irere123 and others added 4 commits June 17, 2026 14:39
…rborepo

CI previously ran per-app commands (`bun run --cwd apps/<app> ...`), bypassing
Turbo's dependency graph. A bare `vite build` for web does not build
@lemma/headless first — whose dist/ is gitignored — so a fresh checkout could
build (and deploy) web against a missing/stale workspace dependency.

- turbo.json: rename the `check-types` task to `typecheck` (the script name every
  workspace already uses) and have it `dependsOn ^build`, so each package is
  type-checked against its dependencies' emitted declarations.
- root package.json: add `build` (turbo build) and `typecheck` (turbo typecheck).
- @lemma/email: rename `build` (the react-email preview build) to `preview:build`
  so it stays out of the Turbo build graph — nothing consumes its output (the API
  imports it as source) and it is flaky (ENOTEMPTY on .react-email). Ignore the
  .react-email scratch dir.
- ci.yaml: replace the four per-app jobs with two root jobs — `verify`
  (turbo build + `turbo typecheck --filter='!web'`, blocking) and `quality`
  (biome + `turbo typecheck --filter=web`, advisory/continue-on-error).
- deploy-web.yaml: build with `turbo build --filter=web` (deps in order), then
  `wrangler deploy` the already-built worker (no rebuild).
- deploy-api.yaml: type-check via `turbo typecheck --filter=@lemma/api`.
- docs/DEPLOYMENT.md: document the root/Turbo orchestration model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… installs

bun 1.2.2 has a `catalog:` resolution bug: it tries to `git clone @types/react`
and fails (`@types/react@catalog: failed to resolve`), which broke every CI job
at `bun install`. Local dev runs 1.3.14, which resolves catalogs correctly —
hence green locally but red in CI. Reproduced both ways with a minimal catalog
workspace (1.2.2 fails, 1.3.14 succeeds with an empty cache).

- package.json: packageManager bun@1.2.2 -> bun@1.3.14.
- ci.yaml / deploy-api.yaml / deploy-web.yaml: setup-bun bun-version -> 1.3.14.
- Regenerate bun.lock with 1.3.14 (postgres demoted to a devDep to match
  package.json; @types/bun + bun-types bumped to 1.3.14) and switch every
  install back to `bun install --frozen-lockfile` for reproducible CI.
- docs/DEPLOYMENT.md: record the bun version requirement and the 1.2.2 bug.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
apps/web declares `motion` but three files imported `framer-motion` directly — a
transitive dependency of `motion`. That only resolved via local node_modules
hoisting; a clean frozen install (as in CI) fails with "Rollup failed to resolve
import framer-motion", breaking web#build. Switch the imports to `motion/react`
(the React entry the declared `motion` package provides), matching the existing
usage in document-library-list.tsx. Verified with a clean `--frozen-lockfile`
install + `turbo build --filter=web`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
It is regenerated by `wrangler types` on every install (web's
`postinstall: cf-typegen`), so tracking it produced perpetual diff churn. CI
regenerates it during `bun install` before any type-check. The API copy stays
tracked because the API has no postinstall hook to regenerate it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Irere123 Irere123 merged commit a9ec208 into staging Jun 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant