chore(repo): overhaul the CI and turbo configuration - #477
Conversation
Every workflow repeated the same checkout/pnpm/setup-node/install block and hardcoded node 22 in nine places. .github/actions/setup owns that now, with .node-version as the single source of truth and one automatic install retry for registry flakes. Also pins every action to a commit SHA, sets persist-credentials: false wherever the job has no further git operations, adds concurrency groups and timeouts, and moves the two API-only jobs to the ubuntu-slim runner. Adds a dependency-review job on the PR diff.
Two things were silently broken. TURBO_TOKEN and TURBO_TEAM were never set, so the remote cache had never once been hit; and every run logged 'unable to detect git range, assuming all files have changed', so --affected was a no-op and all 34 packages were always in scope. The token is now minted per run from the GitHub OIDC token, which removes the secret entirely and degrades to the local cache on fork PRs. TURBO_SCM_BASE and a full-depth checkout make --affected actually filter. The job graph followed from measuring a run: each of the four test shards spent ~90s to run 7s of tests, and the coverage job replayed the whole suite a fifth time. Ten jobs become four, plus a gate job so branch protection has one stable required check. Preview publishing no longer waits on the test jobs. Adds a build of the affected examples, which nothing covered before, and a cleanup of per-branch caches on PR close.
globalEnv fed thirteen app secrets into the global hash, so rotating POSTHOG_HOST or DATABASE_URL invalidated every cached task in the repo, including lint on the core package. They only ever matter to build and dev, so they move there. lint now hashes the root eslint config through $TURBO_ROOT$: editing it used to leave every lint result cached and green. test declares its coverage output.
Twenty-four near-identical root scripts existed only to spell out a turbo filter, and adding an example meant adding another. scripts/run-app.mjs discovers them instead: pnpm example pick from a list pnpm example hono run examples/hono pnpm playground next run apps/next-playground This also reaches examples/bun-script, which no root script could start because it has a start script rather than dev. Docs updated to match. Drops the workspaces field: pnpm reads pnpm-workspace.yaml, so it was a second declaration of the workspace layout that nothing consumed.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: a44c904 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Thank you for following the naming conventions! 🙏 |
|
Warning Review limit reached
Next review available in: 4 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
📝 WalkthroughWalkthroughThe change adds a shared repository setup action, consolidates CI jobs, adds a local example runner, updates Turbo configuration, pins workflow actions, adds workflow permission and cache controls, and adds structured client ChangesRepository tooling and automation
Client Error logging
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant Log
participant ErrorSerializer
participant Output
Caller->>Log: call error with Error instance
Log->>ErrorSerializer: serialize Error fields
ErrorSerializer-->>Log: return structured error data
Log->>Output: emit error under error
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
The new job surfaced pre-existing breakage: seven examples do not build from a clean checkout. examples/vite is a server example whose `vite build` script was never meaningful, and sveltekit, react-router, solidstart and tanstack-start need framework codegen that no dev:prepare script runs. None of that is caused by this branch and fixing it is its own piece of work, so the job reports without blocking the gate.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/actions/setup/action.yml:
- Around line 27-35: Update the pinned references for pnpm/action-setup and
changesets/action to the commit SHAs that resolve to their intended tags,
preserving the corresponding version comments and all other workflow
configuration.
In @.github/workflows/ci.yml:
- Around line 45-53: Remove the unsupported “parallel” wrapper from the setup
steps in the quality, test, examples, and publish jobs. In each job’s steps
list, place “Set up Turborepo remote cache” and “Set up pnpm and Node” as
top-level sequential steps, preserving their existing conditions, actions, and
configuration.
- Around line 64-66: Update the permissions blocks for the test, examples, and
publish jobs in the CI workflow to document each sensitive grant with comments
matching the existing quality job style: explain id-token: write as remote cache
OIDC and document publish’s pull-requests: write purpose as well. Keep the
permission values unchanged.
In @.github/workflows/pr-clean-caches.yml:
- Around line 12-13: Set workflow-level permissions to an empty mapping in
.github/workflows/pr-clean-caches.yml, then move actions: write into
jobs.cleanup.permissions. In .github/workflows/semantic-pull-request.yml, also
set workflow-level permissions to an empty mapping and move contents: read and
pull-requests: write into jobs.validate-pr.permissions.
- Around line 8-10: Add a required pr_number workflow_dispatch input in the
workflow definition, then update the BRANCH construction to use
github.event.pull_request.number for pull_request events and the manual input
when that value is absent. Preserve the existing pull-request behavior while
ensuring manual runs target refs/pull/{pr_number}/merge.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e8811a23-ea71-41ec-aa4f-099c25f7e4ca
📒 Files selected for processing (23)
.github/actions/setup/action.yml.github/workflows/autofix.yml.github/workflows/ci.yml.github/workflows/dependency-review.yml.github/workflows/e2e.yml.github/workflows/label-pr.yml.github/workflows/mutation.yml.github/workflows/pr-clean-caches.yml.github/workflows/release.yml.github/workflows/semantic-pull-request.yml.node-versionapps/docs/content/4.integrate/frameworks/03.sveltekit.mdapps/docs/content/4.integrate/frameworks/06.nestjs.mdapps/docs/content/4.integrate/frameworks/07.express.mdapps/docs/content/4.integrate/frameworks/08.hono.mdapps/docs/content/4.integrate/frameworks/09.fastify.mdapps/docs/content/4.integrate/frameworks/10.elysia.mdapps/docs/content/4.integrate/frameworks/11.react-router.mdapps/docs/content/4.integrate/frameworks/15.orpc.mdapps/docs/content/5.use-cases/5.eve.mdpackage.jsonscripts/run-app.mjsturbo.json
name, message and stack are non-enumerable, so spreading an Error into a wide
event contributed nothing: log.error(new Error('boom')) emitted an event with
no error in it at all. The type only accepted a tag pair or a plain object, so
the call did not type check either — while the Next.js docs teach exactly that
pattern for client components, and examples/nextjs uses it.
Errors now land under `error` with the same shape the server logger stores,
carrying code, status, cause and friends.
Dependency ReviewThe following issues were found:
Vulnerabilitiespnpm-lock.yaml
Only included vulnerabilities with severity high or higher. OpenSSF ScorecardScorecard details
Scanned Files
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e8a07f0 to
d923cb1
Compare
examples/vite is a Hono server, so `vite build` looked for an index.html that does not exist. It now builds src/server.ts as an ssr entry, which is also what its `start` script already expected to run — that script had never worked. examples/nextjs is fixed by the client log.error() change in the previous commit. turbo declared no outputs covering build/ or .svelte-kit/, so react-router and sveltekit warned on every run and their builds were never cached. The job runs with --continue, so one broken example no longer cancels the rest and hides whether they are healthy, and it is back in the required gate. Two examples stay excluded. Both are dependency-resolution problems needing a lockfile change that a workflow PR should not carry: tanstack-start aliases nitro to nitro-nightly@latest while shamefullyHoist puts a different nitro at the workspace root, and eve fails to type check because three copies of @types/react resolve at once.
d923cb1 to
b27a5ac
Compare
pr-clean-caches only ever read the PR number from the pull_request payload, so a workflow_dispatch run expanded the ref to refs/pull//merge and matched nothing. Manual runs now take the number as an input. Workflow-level write permissions applied to every job in pr-clean-caches and semantic-pull-request; they move onto the job that needs them, with the workflow scope emptied. Every id-token and pull-requests grant now says what it is for.
CI builds ten of the eleven examples. eve is the one that fails, and it is a real failure I had wrongly dismissed: three copies of @types/react resolve at once, so React.Key from one is not assignable to Key from another and every JSX element fails to type check. It only passed on my machine because repeated installs had left node_modules in a state CI never reproduces. Pinning @types/react through a workspace override fixes it, but any change to the resolution graph forces a full re-resolve, and that re-resolve breaks apps/playground with 'Could not resolve @nuxt/icon (specified as a dependency of @nuxt/ui)' and drags nitro-nightly@latest from a July 2026 build back to an October 2025 one that pins a vulnerable h3. None of that belongs in a workflow PR, so the lockfile stays untouched and eve is excluded until it is sorted.
Two overrides, both needed because a single duplicated version breaks a consumer: @types/react resolved to three versions at once, so React.Key from one copy was not assignable to Key from another and every JSX element in examples/eve failed to type check. Pinning it forces a re-resolve that pulls a second rolldown, which splits @nuxt/icon into two peer variants. shamefullyHoist then hoists neither, and apps/playground dies on 'Could not resolve @nuxt/icon'. Scoping rolldown to tsdown@0.22.8 keeps @nuxthub/core's older tsdown on its own copy. examples/tanstack-start pinned off nitro-nightly@latest, which had drifted from a July 2026 build to an October 2025 one carrying h3 2.0.1-rc.2 and its two high-severity advisories. All 11 examples build, 35 lint and typecheck tasks pass, 1647 tests green.
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
turbo.json (1)
97-98: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winMake
testwait for the package-localbuild.
testdepends only ondev:prepare, anddev:prepareis scoped to dependencybuildoutputs via^build. Run the current packagebuildas well so tests that consumedistartifacts do not use stale output.Proposed fix
"test": { - "dependsOn": ["dev:prepare"], + "dependsOn": ["dev:prepare", "build"], "outputs": ["coverage/**"] },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@turbo.json` around lines 97 - 98, Update the test task configuration to depend on both dev:prepare and the current package’s build task, preserving the existing coverage outputs and dependency build behavior.Source: Learnings
.github/workflows/ci.yml (2)
73-81: 🎯 Functional Correctness | 🔴 CriticalRemove the unsupported
parallelwrappers.GitHub Actions does not support
parallel:insidesteps. Each setup action must be a top-level sequential step withuses:. Thetest,examples, andpublishjobs remain invalid.This is the same finding as the previous review comment, and it is still present in the current file.
#!/usr/bin/env bash set -euo pipefail actionlint .github/workflows/ci.ymlAlso applies to: 104-112, 146-154
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/ci.yml around lines 73 - 81, Remove the unsupported parallel wrappers from the setup steps in the test, examples, and publish jobs. Promote each nested setup action directly to the job’s steps list, preserving its name, if condition, uses reference, and with configuration so every step remains sequential and valid GitHub Actions syntax.
88-89: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winUse Turbo for the evlog coverage step.
.turbo/turbo.jsondefinestestwithdependsOn: ["dev:prepare"], but.github/workflows/ci.ymlrunspnpm --filter evlog run test:coverage, which uses the directvitest run --coveragescript. Runpnpm exec turbo run test --filter=evlogor updatetest:coverageto preserve the required preparation dependency.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/ci.yml around lines 88 - 89, Update the “Test evlog with coverage” workflow step to invoke the Turbo `test` task for the `evlog` package, using the existing `dev:prepare` dependency defined in `.turbo/turbo.json`, instead of running `pnpm --filter evlog run test:coverage` directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 124-127: Update the “Build affected examples” workflow step so
evlog-eve-example is included in the required example build gate by removing its
exclusion filter. If its dependency issue prevents inclusion, resolve that
dependency or add a separate required build step for evlog-eve-example.
In @.github/workflows/pr-clean-caches.yml:
- Around line 34-35: Update the cache ID retrieval command in the PR cache
cleanup workflow to use gh api pagination, ensuring all pages of caches for the
pull request ref are fetched before deletion. Preserve the existing ref filter,
page size, and jq extraction.
In @.github/workflows/semantic-pull-request.yml:
- Around line 25-27: Split the workflow’s validate-pr flow so
amannn/action-semantic-pull-request runs in a separate job with only
pull-requests: read (and contents: read only if required by the pinned action),
then pass its lint failure result to the existing sticky-comment reporting job
configured with pull-requests: write. Preserve the current validation and
reporting behavior while ensuring write permissions are limited to
comment-posting steps.
In `@examples/eve/next-env.d.ts`:
- Line 3: Remove the manually added generated declaration import from
examples/eve/next-env.d.ts at lines 3-3 and examples/nextjs/next-env.d.ts at
lines 1-6, restoring both files to their original warning-only content so
Next.js regenerates them from .next/types/routes.d.ts.
In `@packages/evlog/src/runtime/client/log.ts`:
- Around line 123-126: Update serializeError() to preserve the full documented
payload by including internal and the EvlogError metadata fields why, fix, and
link alongside the existing fields. When serializing cause, recursively
serialize nested Error values while tracking visited objects to prevent cycles,
so their message and stack are retained rather than becoming {}. Add regression
coverage for internal, EvlogError metadata, and an Error-valued cause.
---
Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 73-81: Remove the unsupported parallel wrappers from the setup
steps in the test, examples, and publish jobs. Promote each nested setup action
directly to the job’s steps list, preserving its name, if condition, uses
reference, and with configuration so every step remains sequential and valid
GitHub Actions syntax.
- Around line 88-89: Update the “Test evlog with coverage” workflow step to
invoke the Turbo `test` task for the `evlog` package, using the existing
`dev:prepare` dependency defined in `.turbo/turbo.json`, instead of running
`pnpm --filter evlog run test:coverage` directly.
In `@turbo.json`:
- Around line 97-98: Update the test task configuration to depend on both
dev:prepare and the current package’s build task, preserving the existing
coverage outputs and dependency build behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: fcc149ee-f51d-4459-8b3f-d144d5a9a075
📒 Files selected for processing (11)
.changeset/client-log-error-instance.md.github/workflows/ci.yml.github/workflows/pr-clean-caches.yml.github/workflows/semantic-pull-request.ymlexamples/eve/next-env.d.tsexamples/nextjs/next-env.d.tsexamples/vite/vite.config.tspackages/evlog/src/runtime/client/log.tspackages/evlog/src/types.tspackages/evlog/test/core/client-console.test.tsturbo.json
| /// <reference types="next" /> | ||
| /// <reference types="next/image-types/global" /> | ||
| import "./.next/dev/types/routes.d.ts"; | ||
| import "./.next/types/routes.d.ts"; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
for file in examples/eve/next-env.d.ts examples/nextjs/next-env.d.ts; do
rg -n 'NOTE: This file should not be edited|types/routes\.d\.ts' "$file"
done
git diff --check -- examples/eve/next-env.d.ts examples/nextjs/next-env.d.tsRepository: HugoRCD/evlog
Length of output: 311
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '--- tracked next-env.d.ts files ---\n'
git ls-files '*next-env.d.ts' || true
printf '\n--- file contents ---\n'
while IFS= read -r f; do
echo "#### $f"
cat -n "$f"
done < <(git ls-files '*next-env.d.ts')
printf '\n--- checked out diff/stat for target files ---\n'
git diff --ignore-submodules -- examples/eve/next-env.d.ts examples/nextjs/next-env.d.ts | sed -n '1,120p' || true
printf '\n--- lint/typecheck/test status without repo execution ---\n'
printf 'package scripts (if available)...\n'
python3 - <<'PY'
import json, pathlib
for path in ['package.json','pnpm-lock.yaml','yarn.lock','package-lock.json']:
p=pathlib.Path(path)
if p.exists():
print(path)
if p.name=='package.json':
data=json.loads(p.read_text())
print('scripts=',\njson.dumps(data.get('scripts',{}), indent=2, sort_keys=True))
PYRepository: HugoRCD/evlog
Length of output: 242
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- tracked next-env.d.ts files ---'
git ls-files '*next-env.d.ts' || true
printf '%s\n' ''
printf '%s\n' '--- file contents ---'
while IFS= read -r f; do
echo "#### $f"
cat -n "$f"
done < <(git ls-files '*next-env.d.ts')
printf '%s\n' ''
printf '%s\n' '--- checked out diff/stat for target files ---'
git diff --ignore-submodules -- examples/eve/next-env.d.ts examples/nextjs/next-env.d.ts | sed -n '1,120p' || true
printf '%s\n' ''
printf '%s\n' '--- package.json scripts if available ---'
python3 - <<'PY'
import json, pathlib
p=pathlib.Path('package.json')
if p.exists():
data=json.loads(p.read_text())
print(json.dumps(data.get('scripts', {}), indent=2, sort_keys=True))
else:
print('no package.json')
PYRepository: HugoRCD/evlog
Length of output: 355
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- file contents ---'
git ls-files '*next-env.d.ts' | while IFS= read -r f; do
echo "#### $f"
cat -n "$f"
done
printf '%s\n' ''
printf '%s\n' '--- checked out diff/stat for target files ---'
git diff --ignore-submodules -- examples/eve/next-env.d.ts examples/nextjs/next-env.d.ts | sed -n '1,120p' || true
printf '%s\n' ''
printf '%s\n' '--- package.json scripts if available ---'
python3 - <<'PY'
import json, pathlib
p=pathlib.Path('package.json')
if p.exists():
data=json.loads(p.read_text())
print(json.dumps(data.get('scripts', {}), indent=2, sort_keys=True))
else:
print('no package.json')
PYRepository: HugoRCD/evlog
Length of output: 2777
Do not commit generated Next.js declaration changes.
next-env.d.ts is a generated declaration file, and both changed examples still include the unedited warning. Let Next.js regenerate next-env.d.ts from .next/types/routes.d.ts rather than committing these manual changes.
🧰 Tools
🪛 ESLint
[error] 3-3: Extra semicolon.
(semi)
📍 Affects 2 files
examples/eve/next-env.d.ts#L3-L3(this comment)examples/nextjs/next-env.d.ts#L1-L6
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/eve/next-env.d.ts` at line 3, Remove the manually added generated
declaration import from examples/eve/next-env.d.ts at lines 3-3 and
examples/nextjs/next-env.d.ts at lines 1-6, restoring both files to their
original warning-only content so Next.js regenerates them from
.next/types/routes.d.ts.
Sources: Coding guidelines, Linters/SAST tools
…Error
serializeError dropped internal and the EvlogError why/fix/link metadata that
the server logger stores, and it passed cause straight through: a nested Error
JSON.stringify's to {}, so the console output lost its message and stack.
Causes are now serialized recursively, with a seen set for cycles.
Also splits PR-title validation from comment posting so pull-requests: write is
scoped to the job that comments, paginates the cache listing in
pr-clean-caches, and drops two generated next-env.d.ts files that git add -A
had swept in.
Its drizzle query results resolve to any on a cold CI checkout, so vue-tsc reports implicit-any on thirteen callbacks that type fine locally. The old telemetry job only ran test and build, so this never ran in CI either and no coverage is lost by leaving it out until the NuxtHub type generation is sorted.
❓ Type of change
📚 Description
Two things were silently broken
The remote cache had never been hit. Every run logged empty values:
Neither secret ever existed. The token is now minted per run by exchanging the
GitHub OIDC token through
vercel/setup-turborepo-remote-cache-action, so thereis no long-lived secret to rotate and only a
TURBO_TEAMrepository variableto configure. Fork PRs get no OIDC token, so
TURBO_CACHEfalls back tolocal:rwinstead of failing.--affectedwas a no-op. Withfetch-depth: 1turbo could not resolve abase to diff against:
Fixed with a full-depth checkout plus
TURBO_SCM_BASE.The job graph came from measuring a run
Per-step timings over the last runs:
pnpm installis 18s (the pnpm cachealready works), but each of the four test shards spent ~90s of runner time to
run 7s of tests, and
coveragereplayed the entire suite a fifth time.Ten jobs become five:
quality,test,examples,publish, and acigatejob so branch protection has one stable required check instead of a list of
matrix names. Preview publishing no longer waits on the test jobs — a preview
build is most useful while the PR is still red.
examplesis new: nothing built the examples before.Composite action
The checkout/pnpm/setup-node/install block was copied across eight jobs and
node-version: 22was hardcoded in nine places..github/actions/setupowns itnow, with
.node-versionas the single source of truth and one automaticinstall retry for registry flakes.
Hardening
Every action pinned to a commit SHA,
persist-credentials: falsewherever thejob has no further git operations (
release.ymlkeeps them:changesets/actionpushes the release branch), least-privilege
permissions,timeout-minutes,concurrency groups, and
--frozen-lockfileinrelease.yml, which installedunpinned before. Adds
dependency-reviewon the PR diff and a cleanup ofper-branch caches on PR close.
ubuntu-slimandparallelThe three API-only jobs move to
ubuntu-slim.parallelgroups the remotecache and Node setup steps, matching
turborepo'slint.yml. Lint andtypecheck stay a single
turbo run lint typecheck— turbo already parallelisesthem and knows their dependency graph.
turbo.json
globalEnvcarried thirteen app secrets, so rotatingPOSTHOG_HOSTorDATABASE_URLinvalidated every cached task in the repo, includinglintonthe core package. They only matter to
buildanddev.lintnow hashes theroot eslint config through
$TURBO_ROOT$— editing it used to leave every lintresult cached and green.
Root scripts
Twenty-four near-identical scripts existed only to spell out a turbo filter:
This also reaches
examples/bun-script, which no root script could start. Thedead
workspacesfield is dropped: pnpm readspnpm-workspace.yaml.📝 Notes
actionlintis not added: v1.7.12 predates theparallelkeyword andrejects it (rhysd/actionlint#693).
Worth adding once that lands.
examples/evewants>=24and warns on every install.examplesjobwill build all of them. Can be moved behind a label like
e2eif that is tooheavy.
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Documentation
Improvements
Update: examples are fixed and gated
examplesstarted out informational because it reported failures. One was realand is fixed here; the earlier reading that several examples were broken was
wrong twice over.
First, turbo stops at the first failure by default, so most of what looked like
failures were cancelled tasks. The job now runs with
--continue.Second, the remaining failures came from a bad install state in my working
tree, not from the examples. On a clean checkout, all eleven example builds
pass with no exclusions.
What is genuinely fixed:
vite buildlooked for anindex.htmlthat does not exist. It now buildssrc/server.tsas an ssrentry, which is also what its
startscript always expected to run — thatscript had never worked either. Verified: reverting this config reproduces
Could not resolve entry module "index.html".build/or.svelte-kit/, soreact-router and sveltekit warned on every run and were never cached.
The client
log.error()fixIndependent of the examples.
createLogMethodroutes any object toemitLog,which spreads it — but
name,messageandstackare non-enumerable on anError. Solog.error(new Error('boom'))emitted an event containing noerror at all, silently. The type did not accept an
Erroreither, while theNext.js docs teach exactly that pattern for client components.
Errors now land under
errorwith the same shape the server logger stores.Separate commit,
patchchangeset, three tests.