Skip to content

feat: modernize toolchain, runx CLI, and worker templates - #22

Merged
jahands merged 28 commits into
mainfrom
feat/modernize-2026
Jul 27, 2026
Merged

feat: modernize toolchain, runx CLI, and worker templates#22
jahands merged 28 commits into
mainfrom
feat/modernize-2026

Conversation

@jahands

@jahands jahands commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Broad modernization pass over the template: newer toolchain, a real runx CLI instead of wrapper bin scripts, TypeScript-authored Turbo config, a new @repo/test-helpers package, a workflows-worker generator, and a big docs/config cleanup.

Toolchain

  • pnpm 10.14.0 → 11.2.2, bun 1.3.10 → 1.3.12, turbo 2.8.20 → 2.10.1, syncpack 13 → 15.1.2, vitest 4.1.0 → 4.1.5, wrangler 4.76.0 → 4.111.0, prettier 3.8.1 → 3.8.3. Added fd and watchexec to .mise.toml.
  • pnpm 11 migration: .npmrc deleted, its settings moved into pnpm-workspace.yaml (autoInstallPeers, publicHoistPattern). onlyBuiltDependencies replaced with the pnpm 11 allowBuilds map. Added verifyDepsBeforeRun: error so Turbo running many package scripts can't kick off concurrent implicit installs.
  • CI pins bun-version: 1.3.12 (1.3.14 segfaults on linux x64). Action tags and node-version: lts/* are unchanged.

runx CLI replaces wrapper bins

Wrangler orchestration moved out of shell scripts and into @repo/tools:

  • runx build wranglerwrangler deploy --dry-run with --minify --outdir ./dist, forces color outside CI, prints build duration.
  • runx deploy wrangler — derives RELEASE as <version>-<short-sha>, cleans ./dist, deploys with --var RELEASE:… --var ENVIRONMENT:production, uploads sourcemaps, retries 3×.
  • runx dev wrangler — builds workspace deps first, copies .dev.vars.example.dev.vars if missing, then wrangler dev.
  • runx check--workers-types is now a first-class check run from cwd rather than buried in the --format branch, and is part of the default set. Prettier runs now share a cache location so Turbo can cache them.

Deleted 9 dead or one-line pass-through bins (get-branch, get-version, run-vite-*, run-vitest-ci, run-wrangler-{build,dev,deploy}). Added run-vitest-watch. run-tsc gained a DISABLE_TSGO escape hatch, run-oxlint a FIX_OXLINT flag, and run-vitest now runs explicitly in run mode.

New library modules with tests: workspace/workspace.ts (getWorkspacePackages, getWorkersProjects, globProjectFiles), zod-validated getPackageJson(), timeFn(), isCI(). getRepoRoot() is now anchored to import.meta.dirname so it's deterministic regardless of cwd.

Turbo config in TypeScript

turbo.jsonc → generated turbo.json, authored in turbo.config.ts via turbo-config. The win: the config introspects the workspace at generation time — buildPackages is derived by scanning every package for a build script and injected into dependsOn for the root-only tasks, replacing a hand-maintained list. A //#check:turbo-config task verifies turbo.json is in sync, and postinstall regenerates it outside CI. Prettier cache is now declared as a task output.

New @repo/test-helpers

Source-only package (no build step) with five entrypoints:

  • /test — msw-based HTTP mocking. The server is created lazily so importing from a setup file doesn't start intercepting, and it runs with onUnhandledRequest: 'error' so un-mocked outbound requests fail the test instead of hitting the network.
  • /matcherstoBeUUID(), toBeAfterDate(), and a toBeGreaterThan() that fails rather than throws on non-numbers. Failures carry actual/expected so vitest renders a diff.
  • /serializer — snapshot serializers scoped per test (keyed on test path + name), so enabling one doesn't leak into later tests.
  • /suitetestSuite(), vitest test pre-extended with a harness fixture.
  • rootisWorkers() / isNode() runtime detection.

Wired up in example-worker-echoback as a working example.

New workflows-worker generator

Scaffolds a Hono worker backed by Cloudflare Workflows: a WorkflowEntrypoint subclass with tagged logging and zod-parsed params, an admin route for querying instance status (validated with @hono/standard-validator + ts-pattern exhaustive matching over known workflow slugs), a create-instance route, and integration tests that validate responses with zod.

Worker template updates

All worker templates (and the example app) converge on one shape:

  • compatibility_date2026-06-04, plus workers_dev: false, preview_urls: false, placement: { mode: "smart" }, and version_metadata bound to CF_VERSION_METADATA.
  • SENTRY_RELEASERELEASE everywhere (SharedHonoEnv, wrangler vars, deploy command, app source). Sentry was never actually wired up; the TODO comments marking where you'd add it remain.
  • New .dev.vars.example in every worker template, listed explicitly in templateFiles because plop's **.hbs glob skips dotfiles.
  • remoteBindings: false in vitest configs; scripts use runx instead of wrapper bins; stale dep pins refreshed.
  • fix-all now generates worker-configuration.d.ts before running lint/type passes, so a freshly generated worker passes checks.

@repo/wrangler-config (TypeScript-authored wrangler config) was tried mid-branch and reverted — wrangler.jsonc is authored directly.

Generators run in the current directory

just gen and just new-package no longer cd to the workspace root — generators derive the destination from where they were invoked (apps/my-team/apps/my-team/<name>), falling back to apps//packages/ at the root. This also fixes new-package aborting with ERR_PNPM_VERIFY_DEPS_BEFORE_RUN: the post-generation step now runs fix --depspnpm installfix --format, and the install is no longer filtered to the new package.

Docs and editor config

  • AGENTS.md rewritten from a 78-line XML-tagged blob into 27 lines of plain markdown, and CLAUDE.md is now a symlink to it — one source of truth.
  • Deleted ~3,100 lines of .cursor/rules/, .windsurf/rules/, and a stale .claude/agents/ file, all superseded by AGENTS.md.
  • .vscode/settings.json scrubbed of personal leftovers (file-nesting patterns and cSpell words from unrelated repos).
  • New just lint runs check:lint + check:types repo-wide with grouped logs and --continue.
  • Removed a stale dagger-specific lint override from @repo/oxlint-config.

Testing

bun turbo check:ci passes: 30 tests across 6 files, plus lint, types, deps, format, and workers-types checks.

jahands added 26 commits July 25, 2026 07:18
- wrangler 4.111.0, @cloudflare/vitest-pool-workers 0.16.18,
  @cloudflare/workers-types 5.20260703.1
- vitest 4.1.5 (+ @vitest/ui), turbo/@turbo/gen 2.10.1, prettier 3.8.3,
  syncpack 15.1.2, oxlint 1.60.0, oxlint-tsgolint 0.21.1
- declare explicit vite 7.3.5 where vitest-pool-workers is used
- set remoteBindings: false in cloudflareTest() configs
- syncpack 15: drop lintFormatting, add url specifier guard
- pnpm 11.2.2: move .npmrc settings into pnpm-workspace.yaml,
  allowBuilds map, verifyDepsBeforeRun, mise pnpm 11.2.2 / bun 1.3.12
…ild/dev orchestration, and DX hardening

- fix broken @repo/tools exports (src/lib/ never existed) with explicit
  subpath exports: ./path, ./environment, ./workspace, ./package
- port workspace introspection: getWorkspacePackages(), getWorkersProjects(),
  globProjectFiles() with git check-ignore filtering; getRepoRoot() is now
  anchored to the tools package location instead of cwd
- add 'runx build wrangler' (wrangler deploy --dry-run --outdir ./dist with
  --config/--no-minify/--no-output, FORCE_COLOR outside CI, timed) and point
  build:wrangler scripts at it, removing bin/run-wrangler-build
- dev: 'runx dev wrangler' builds workspace deps first and copies
  .dev.vars.example to .dev.vars when missing; run-wrangler-dev delegates to it
- check: run workers-types check regardless of --format (new -w flag)
- prettier: stable cache location node_modules/.cache/.prettier/.prettier-cache
- bins: explicit 'vitest run' + maxConcurrency, run-vitest-watch (watchexec),
  DISABLE_TSGO and FIX_OXLINT escape hatches, syncpack fix
- root DX: Justfile dotenv-load + agent-friendly 'just lint' recipe,
  .mise.toml fd/watchexec, .prettierignore generic build-output entries
turbo.json is now generated from turbo.config.ts using the turbo-config
package. Workspace packages with build scripts are computed dynamically
as dependsOn for the root lint/test tasks, replacing the hand-maintained
comment-driven list. Adds check:turbo-config to the check:ci flow, a
postinstall that regenerates turbo.json (skipped in CI), prettier cache
outputs for format tasks, and a just generate-turbo-config recipe.
Adds a shared testing package ported from the internal workers monorepo:

- http-mock: useHttpMock()/resetHttpMocks() msw wrapper with a lazily
  created server and onUnhandledRequest: 'error'
- matchers: toBeUUID(), toBeAfterDate() and a corrected toBeGreaterThan()
- serializer: opt-in snapshot serializers for Date
- suite: testSuite() test.extend harness
- env: isWorkers()/isNode() runtime detection

Wires it into apps/example-worker-echoback via a vitest setup file and
adds a small useHttpMock() demonstration to the integration tests.
…er config in TypeScript

- new packages/wrangler-config with defineConfig(), a zod schema generated
  from wrangler's config-schema.json, and a wrangler-config CLI with
  generate + check (CI drift guard)
- example-worker-echoback now authors wrangler.jsonc via wrangler.config.ts
- turbo build:wrangler-config task wired into build (runs check in CI)
- worker generators emit wrangler.config.ts and generate wrangler.jsonc
Replace mutable action tags with full commit SHAs, annotated with
`# gagen:pin <action>@<tag> = <sha>` comments so future updates stay
traceable. Also pin bun-version to 1.3.12 (1.3.14 segfaults on linux
x64) and node-version to 22.x instead of lts/*.
- rewrite AGENTS.md as one lean file with the repo's working rules
- replace CLAUDE.md with a symlink to AGENTS.md
- fix stale README references (turbo.config.ts, prerequisites, generator list, just lint)
SHA pinning in the workers repo comes from the TypeScript workflow
generator (gagen); this template defines workflows by hand, so stick
to mutable tags. Keeps the bun/node toolchain version pins.
TypeScript-authored Wrangler config is a poor fit for most template
users - plain wrangler.jsonc is simpler and matches Cloudflare docs.
Generator templates now ship a wrangler.jsonc.hbs with the same
modernized defaults the generated config carried (compat date,
nodejs_compat, observability, smart placement, NAME/RELEASE vars,
version_metadata).
Matches ~/src/workers: apps call 'runx dev wrangler' and
'runx deploy wrangler' directly. NAME comes from wrangler.jsonc vars
instead of a --var flag; deploy now also sets ENVIRONMENT:production
and retries up to 3 times.
- delete unreferenced get-version/get-branch bins
- delete run-vite-* and run-vitest-ci wrappers; scripts call vite/vitest directly
- ship .dev.vars.example in the example app and worker generator templates
  so the runx dev bootstrap actually fires (dotfile templates listed
  explicitly - '**.hbs' globs skip them)
- delete .cursor/.windsurf rule packs superseded by AGENTS.md
Completes the rename - apps and templates already used RELEASE, so check:types was failing.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 107 files, which is 7 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 28ce40d9-c45d-46fc-88ca-5ee948b58399

📥 Commits

Reviewing files that changed from the base of the PR and between 3f03d99 and 0671e8d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (134)
  • .changeset/gen-cwd-destination.md
  • .changeset/oxlint-drop-dagger-override.md
  • .changeset/remove-wrapper-bins.md
  • .changeset/rename-release-var.md
  • .changeset/runx-modernize.md
  • .changeset/runx-wrangler-commands.md
  • .changeset/test-helpers.md
  • .changeset/toolchain-upgrade.md
  • .changeset/workflows-worker-generator.md
  • .changeset/wrangler-config-modernize.md
  • .changeset/zod-test-responses.md
  • .claude/agents/codebase-explainer.md
  • .cursor/rules/auto-commit.mdc
  • .cursor/rules/ci-cd-deployment.mdc
  • .cursor/rules/cursor-rules.mdc
  • .cursor/rules/development-workflow.mdc
  • .cursor/rules/package-management.mdc
  • .cursor/rules/project-structure.mdc
  • .cursor/rules/testing-patterns.mdc
  • .cursor/rules/worker-development.mdc
  • .cursor/rules/zod-v4.mdc
  • .github/workflows/branches.yml
  • .github/workflows/release.yml
  • .mise.toml
  • .npmrc
  • .prettierignore
  • .syncpackrc.cjs
  • .vscode/settings.json
  • .windsurf/rules/ci-cd-deployment.md
  • .windsurf/rules/development-workflow.md
  • .windsurf/rules/package-management.md
  • .windsurf/rules/project-structure.md
  • .windsurf/rules/testing-patterns.md
  • .windsurf/rules/worker-development.md
  • AGENTS.md
  • CLAUDE.md
  • CLAUDE.md
  • Justfile
  • README.md
  • apps/example-worker-echoback/.dev.vars.example
  • apps/example-worker-echoback/package.json
  • apps/example-worker-echoback/src/example-worker-echoback.app.ts
  • apps/example-worker-echoback/src/test/integration/api.test.ts
  • apps/example-worker-echoback/src/test/setup.ts
  • apps/example-worker-echoback/vitest.config.ts
  • apps/example-worker-echoback/worker-configuration.d.ts
  • apps/example-worker-echoback/wrangler.jsonc
  • package.json
  • packages/hono-helpers/package.json
  • packages/hono-helpers/src/middleware/withOnError.ts
  • packages/hono-helpers/src/types.ts
  • packages/oxlint-config/package.json
  • packages/oxlint-config/src/default.config.ts
  • packages/test-helpers/README.md
  • packages/test-helpers/package.json
  • packages/test-helpers/src/env.ts
  • packages/test-helpers/src/http-mock.ts
  • packages/test-helpers/src/index.ts
  • packages/test-helpers/src/matchers.ts
  • packages/test-helpers/src/serializer.spec.ts
  • packages/test-helpers/src/serializer.ts
  • packages/test-helpers/src/suite.spec.ts
  • packages/test-helpers/src/suite.ts
  • packages/test-helpers/src/test.ts
  • packages/test-helpers/tsconfig.json
  • packages/test-helpers/vitest.config.ts
  • packages/tools/bin/get-branch
  • packages/tools/bin/get-version
  • packages/tools/bin/run-fix-deps
  • packages/tools/bin/run-oxlint
  • packages/tools/bin/run-tsc
  • packages/tools/bin/run-vite-build
  • packages/tools/bin/run-vite-dev
  • packages/tools/bin/run-vite-preview
  • packages/tools/bin/run-vitest
  • packages/tools/bin/run-vitest-ci
  • packages/tools/bin/run-vitest-watch
  • packages/tools/bin/run-wrangler-build
  • packages/tools/bin/run-wrangler-deploy
  • packages/tools/bin/run-wrangler-dev
  • packages/tools/package.json
  • packages/tools/src/bin/runx.cmd.ts
  • packages/tools/src/cmd/build.cmd.ts
  • packages/tools/src/cmd/check.cmd.ts
  • packages/tools/src/cmd/deploy.cmd.ts
  • packages/tools/src/cmd/dev.cmd.ts
  • packages/tools/src/cmd/fix.cmd.ts
  • packages/tools/src/dev-vars.ts
  • packages/tools/src/environment.ts
  • packages/tools/src/path.ts
  • packages/tools/src/proc.ts
  • packages/tools/src/time.ts
  • packages/tools/src/workspace/package-json.ts
  • packages/tools/src/workspace/workspace.spec.ts
  • packages/tools/src/workspace/workspace.ts
  • packages/workspace-dependencies/package.json
  • pnpm-workspace.yaml
  • turbo.config.ts
  • turbo.json
  • turbo/generators/answers.ts
  • turbo/generators/config.ts
  • turbo/generators/helpers/package-destination.test.ts
  • turbo/generators/helpers/package-destination.ts
  • turbo/generators/package.json
  • turbo/generators/plugins/fix-all.ts
  • turbo/generators/plugins/fix-deps-and-format.ts
  • turbo/generators/plugins/pnpm-install.ts
  • turbo/generators/templates/fetch-worker-minimal/.dev.vars.example.hbs
  • turbo/generators/templates/fetch-worker-minimal/package.json.hbs
  • turbo/generators/templates/fetch-worker-minimal/vitest.config.ts.hbs
  • turbo/generators/templates/fetch-worker-minimal/wrangler.jsonc.hbs
  • turbo/generators/templates/fetch-worker-vite/.dev.vars.example.hbs
  • turbo/generators/templates/fetch-worker-vite/package.json.hbs
  • turbo/generators/templates/fetch-worker-vite/src/{{ slug name }}.app.ts.hbs
  • turbo/generators/templates/fetch-worker-vite/vitest.config.ts.hbs
  • turbo/generators/templates/fetch-worker-vite/wrangler.jsonc.hbs
  • turbo/generators/templates/fetch-worker/.dev.vars.example.hbs
  • turbo/generators/templates/fetch-worker/package.json.hbs
  • turbo/generators/templates/fetch-worker/src/{{ slug name }}.app.ts.hbs
  • turbo/generators/templates/fetch-worker/vitest.config.ts.hbs
  • turbo/generators/templates/fetch-worker/wrangler.jsonc.hbs
  • turbo/generators/templates/package/package.json.hbs
  • turbo/generators/templates/workflows-worker/.dev.vars.example.hbs
  • turbo/generators/templates/workflows-worker/README.md.hbs
  • turbo/generators/templates/workflows-worker/env.d.ts.hbs
  • turbo/generators/templates/workflows-worker/package.json.hbs
  • turbo/generators/templates/workflows-worker/src/context.ts.hbs
  • turbo/generators/templates/workflows-worker/src/test/integration/api.test.ts.hbs
  • turbo/generators/templates/workflows-worker/src/workflows/{{ slug workflowName }}/{{ slug workflowName }}.ts.hbs
  • turbo/generators/templates/workflows-worker/src/{{ slug name }}.app.ts.hbs
  • turbo/generators/templates/workflows-worker/tsconfig.json.hbs
  • turbo/generators/templates/workflows-worker/vitest.config.ts.hbs
  • turbo/generators/templates/workflows-worker/wrangler.jsonc.hbs
  • turbo/generators/vitest.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/modernize-2026

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Jul 27, 2026

Copy link
Copy Markdown

@socket-security

socket-security Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @emnapi/runtime is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?npm/vitest@4.1.5npm/@cloudflare/vitest-pool-workers@0.16.18npm/wrangler@4.111.0npm/@emnapi/runtime@1.11.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@emnapi/runtime@1.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @mswjs/interceptors is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?npm/msw@2.13.4npm/@mswjs/interceptors@0.41.9

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mswjs/interceptors@0.41.9. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm yargs is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?npm/msw@2.13.4npm/yargs@17.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/yargs@17.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

…ators run below the workspace root

The `gen` and `new-package` justfile recipes no longer cd to the
workspace root, and generators now derive the destination from the
directory they were run from, falling back to `apps/`/`packages/` at the
root. Also fixes `new-package` post-generation steps aborting with
`ERR_PNPM_VERIFY_DEPS_BEFORE_RUN`: `fixDepsAndFormat` now runs `bun runx
fix --deps`, then `pnpm install`, then `bun runx fix --format` (matching
the Worker generators), and `pnpmInstall` no longer filters the install
to the new package.
The old set described intermediate states - a wrangler-config package that was added and reverted within the branch, and a turbo-generators bump for a zod change that only touched the example app. Also adds coverage for the wrangler.jsonc modernization, which no changeset described.
@jahands
jahands merged commit 11c2532 into main Jul 27, 2026
4 checks passed
@jahands
jahands deleted the feat/modernize-2026 branch July 27, 2026 12:05
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