Skip to content

fix(cli): report unexported generated classes before deploy - #345

Merged
prisis merged 5 commits into
alphafrom
fix/export-gap-visibility
Aug 4, 2026
Merged

fix(cli): report unexported generated classes before deploy#345
prisis merged 5 commits into
alphafrom
fix/export-gap-visibility

Conversation

@prisis

@prisis prisis commented Aug 4, 2026

Copy link
Copy Markdown
Member

What

A declared container, workflow or agent whose generated class the worker entry never re-exports is invisible to every check a project runs: tsc is clean, codegen is clean, the tests pass. Wrangler only rejects the unexported class_name when it provisions the binding, so the first signal is deploy day — and a Worker can ship with three workflows and nothing to run them.

Why it wasn't already covered

It partly was. The dev server raises it in the Vite error overlay, and build / deploy / prepare all warn — that machinery is not new.

It never reaches a project that drives its own dev server and deploys through its own IaC, because that project runs none of those commands. The two it does run were the two that stayed silent:

path before after
Vite dev overlay warns unchanged
build / deploy / prepare warns unchanged
doctor containers only all three kinds
lunora codegen silent warns per gap

doctor is the sharper of the two: inference already computed the identical exported status for workflows and agents, and the check simply ignored two of the three kinds. A project could pass doctor with an unexported workflow.

How

collectExportGaps already existed and already covered all three kinds — it was just private to reconcile-bindings. It is now exported from @lunora/config/cloudflare, so both callers get the gaps without the wrangler.jsonc rewrite that is the rest of reconcileWranglerBindings. Deriving the gaps again at each call site is precisely how one kind ended up silently uncovered, so this routes both through the same function.

Two deliberate calls:

  • codegen warns, it does not fail. Codegen runs on every save. Failing between declaring a workflow and wiring the entry would fail the edit that is halfway through fixing it. doctor, prepare and deploy still fail on it — that is where failing is useful.
  • runCodegenCommand stays sync. Inference is async, but that function is a published entry point for exactly the IaC callers this change helps (see concepts/monorepos-and-iac). The await lives in the command wrapper instead of breaking its signature.

Tests

Four new cases, each mutation-checked — I reverted the fix and confirmed the test fails, then restored:

  • doctor fails on an unexported workflow / passes on an exported one. Excluding workflows from the gap set again → × fails when a declared workflow is not exported by the worker entry.
  • lunora codegen warns on a gap / stays quiet when the entry re-exports the module. Removing the call → × warns when a declared workflow is not exported by the worker entry.

Verification

Full-repo lint:types exit 0 · api:check (snapshot updated for the one new export) · lint:package-json clean · eslint --max-warnings=0 on every changed file · tests: cli 1076, config 579, vite 189.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added export validation for declared containers, workflows, and agents.
    • Code generation now warns when bindings are not re-exported by the worker entry.
    • The doctor command reports exported declarations as passes and missing exports as failures.
  • Bug Fixes

    • Export checks now handle inference failures gracefully without interrupting existing command results.
    • JSON output remains clean by directing warnings through the appropriate format-specific logger.

A declared container, workflow or agent whose generated class the worker
entry never re-exports is invisible to every check a project runs: `tsc`
is clean, codegen is clean, the tests pass. Wrangler only rejects the
unexported `class_name` when it provisions the binding, so the first
signal is deploy day — and a Worker can ship with three workflows and
nothing to run them.

The dev server already raises it in the error overlay and `build` /
`deploy` / `prepare` warn. But a project that drives its own dev server
and deploys through its own IaC runs none of those, and `lunora codegen`
— the one command it does run — stayed silent.

Two gaps closed:

- `doctor` checked containers ONLY, while inference computes the same
  status for workflows and agents. A project could pass `doctor` with an
  unexported workflow. It now reports all three from `collectExportGaps`,
  so a fourth kind cannot be added to inference and silently skipped.
- `lunora codegen` now warns for each gap. A warning, not a non-zero
  exit: codegen runs on every save, and failing between declaring a
  workflow and wiring the entry would fail the edit that is halfway
  through fixing it. `doctor`/`prepare`/`deploy` still fail on it.

`collectExportGaps` is exported from `@lunora/config/cloudflare` so both
callers get the gaps without the `wrangler.jsonc` rewrite that is the
rest of `reconcileWranglerBindings`. The warning lives in the command
wrapper rather than `runCodegenCommand`, which stays sync — it is a
published entry point for exactly the IaC callers this helps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@netlify

netlify Bot commented Aug 4, 2026

Copy link
Copy Markdown

Deploy Preview for lunorash ready!

Name Link
🔨 Latest commit 2d416ed
🔍 Latest deploy log https://app.netlify.com/projects/lunorash/deploys/6a71e261e93c0b000828008e
😎 Deploy Preview https://deploy-preview-345--lunorash.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Thank you for confirming the Contributor License Agreement! 🙏

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@prisis, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ce2fd718-c407-4a43-b0a2-eddd09daee3b

📥 Commits

Reviewing files that changed from the base of the PR and between 55fb009 and 2d416ed.

📒 Files selected for processing (1)
  • packages/cli/src/commands/doctor/handler.ts

Walkthrough

The Cloudflare configuration now exposes export-gap collection. The codegen command warns about missing worker exports after generation. The doctor command validates containers, workflows, and agents.

Changes

Export Gap Detection

Layer / File(s) Summary
Export-gap collection API
packages/config/src/cloudflare/reconcile-bindings.ts, packages/config/src/cloudflare/index.ts
collectExportGaps and ExportGap are publicly exported for callers that do not rewrite wrangler.jsonc.
Codegen export warnings
packages/cli/src/commands/codegen/handler.ts
Codegen infers bindings after generation and logs format-specific warnings for declarations missing from worker exports. Inference failures are ignored.
Doctor declared-export validation
packages/cli/src/commands/doctor/handler.ts
Doctor checks declared containers, workflows, and agents, and reports exported declarations as passes and missing exports as failures.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Codegen
  participant BindingInference
  participant ExportGapCollector
  participant Logger
  User->>Codegen: Run codegen
  Codegen->>BindingInference: Infer bindings
  BindingInference-->>Codegen: Return inferred bindings
  Codegen->>ExportGapCollector: Collect export gaps
  ExportGapCollector-->>Codegen: Return missing exports
  Codegen->>Logger: Report remediation warnings
Loading

Possibly related PRs

  • anolilab/lunora#146: Modifies codegen and config worker-entry export detection, including generated container, workflow, and agent export analysis.
  • anolilab/lunora#335: Modifies the codegen declaration and inference pipeline used to derive worker bindings.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: reporting generated classes that the worker entry does not re-export.
Description check ✅ Passed The description clearly explains the problem, solution, scope, tests, and verification, although it does not use every template heading.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/export-gap-visibility

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.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@packages/cli/src/commands/codegen/handler.ts`:
- Around line 207-210: Gate the warnAboutExportGaps call in runCodegenCommand on
an explicit signal that code generation completed, so validation failures for
invalid --format or unresolved --target return without scanning or warning. Set
and check that signal around the generation path while preserving the existing
loggerForFormat behavior, and add tests covering both early-failure cases.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4728a989-bca1-460b-864b-c991b0742b47

📥 Commits

Reviewing files that changed from the base of the PR and between 0a662ec and 072b054.

⛔ Files ignored due to path filters (3)
  • api-snapshots/config.api.md is excluded by none and included by none
  • packages/cli/__tests__/commands/codegen.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/__tests__/commands/doctor.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
📒 Files selected for processing (4)
  • packages/cli/src/commands/codegen/handler.ts
  • packages/cli/src/commands/doctor/handler.ts
  • packages/config/src/cloudflare/index.ts
  • packages/config/src/cloudflare/reconcile-bindings.ts

Comment thread packages/cli/src/commands/codegen/handler.ts Outdated
@codspeed-hq

codspeed-hq Bot commented Aug 4, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 0.84%

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 251 untouched benchmarks
⏩ 10 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
1 shard × 1000 rows (single round-trip) 2.7 ms 3.1 ms -11.62%
baseline (Object.keys + toInternal + path spread per field) 72.2 µs 64.9 µs +11.25%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/export-gap-visibility (2d416ed) with alpha (6ac4f54)2

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on alpha (875a1d6) during the generation of this report, so 6ac4f54 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Review catch. `runCodegenCommand` returns before generation for an invalid
`--format` and for an unresolved `--target`, but `execute` scanned for export
gaps unconditionally afterwards. The result was export-gap warnings stacked on
top of the real validation error, describing a codegen that never happened —
and naming whatever classes a previous run had left on disk.

Gated on `outputDirectory`, which both early returns leave empty and a real emit
always fills. Deliberately not `result.error`: that is also set for a platform
diagnostic raised AFTER a successful emit, where the warning still applies.

Both cases covered, and demonstrated to fail without the gate — the warning
currently prints right beside `codegen: unknown --format "nope"`.

cli 1078/1078.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019WfuWNN3cWJE6beZjng347
`eslint --fix` rewrote three concise arrow bodies into block bodies on a
single line after Prettier had already run, which Prettier then wants
expanded — so the file landed formatted by neither.

Prettier owns formatting here, so it runs last. The repo convention is
Prettier then ESLint; the missing half is re-running Prettier when an
ESLint autofix touches layout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@prisis
prisis merged commit 6ac4f54 into alpha Aug 4, 2026
8 of 10 checks passed
@prisis
prisis deleted the fix/export-gap-visibility branch August 4, 2026 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant