Skip to content

Handle deleted rebuild dependencies in CLI watch#20114

Open
fallintoplace wants to merge 2 commits into
tailwindlabs:mainfrom
fallintoplace:fix/cli-watch-delete-full-rebuild
Open

Handle deleted rebuild dependencies in CLI watch#20114
fallintoplace wants to merge 2 commits into
tailwindlabs:mainfrom
fallintoplace:fix/cli-watch-delete-full-rebuild

Conversation

@fallintoplace
Copy link
Copy Markdown

Fixes #20113.

What changed

  • forward delete events from the CLI watcher to the rebuild decision logic instead of dropping them up front
  • keep ignoring deleted content files for incremental rebuilds, but still force a full rebuild when the deleted path is a tracked dependency
  • add a CLI integration regression test that deletes a config dependency during watch mode and verifies the watcher surfaces the error and recovers on the next rebuild

Why

The watcher already tracks config/plugin/import dependencies as fullRebuildPaths, but delete events were being filtered out before that check happened. That meant deleting a tracked dependency could leave the watcher serving stale output until some other full-rebuild file changed.

Impact

Deleting a tracked dependency in --watch mode now behaves like other full-rebuild dependency changes: the watcher rebuilds immediately instead of silently keeping stale state.

Validation

  • pnpm exec vitest --root=./integrations run cli/config.test.ts
  • pnpm exec prettier --check packages/@tailwindcss-cli/src/commands/build/index.ts integrations/cli/config.test.ts
  • pnpm --dir packages/@tailwindcss-cli lint currently reports unrelated repo-wide TypeScript errors outside this change

@fallintoplace fallintoplace marked this pull request as ready for review May 25, 2026 22:55
@fallintoplace fallintoplace requested a review from a team as a code owner May 25, 2026 22:55
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Review Change Stack

Walkthrough

This PR adds delete event handling to the Tailwind CLI watch mode. A new WatchEvent type represents file system events with path and type metadata. The watcher infrastructure now tracks events per-path in a Map instead of a simple file set. The callback pipeline is updated to pass typed events rather than plain paths. The watch handler applies full rebuild logic when affected dependencies are in the rebuild path list and skips incremental rebuilds for deletes. A new test validates that deleting and recreating a config dependency properly triggers errors and rebuilds.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Handle deleted rebuild dependencies in CLI watch' accurately and clearly describes the main change—ensuring the CLI watch mode properly handles deleted dependency files.
Description check ✅ Passed The description is clearly related to the changeset, detailing what changed, why, and the impact on the CLI watch behavior when dependencies are deleted.
Linked Issues check ✅ Passed The PR fully addresses issue #20113 by forwarding delete events to rebuild logic, forcing full rebuilds for deleted tracked dependencies, and adding a regression test.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the CLI watch delete handling issue: the watcher pipeline modification and the integration test are both within scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 25, 2026

Confidence Score: 5/5

The change is narrowly scoped and all existing guard logic correctly handles the new event shape — safe to merge.

The core logic change is small and well-contained: one new type, one map replacing a set, and one early-continue for non-tracked deletes. The callback handler already had the right structure to handle delete events correctly, and the test exercises the full error-and-recovery path.

No files require special attention.

Reviews (2): Last reviewed commit: "Tighten delete event coalescing in CLI w..." | Re-trigger Greptile

Comment thread packages/@tailwindcss-cli/src/commands/build/index.ts
Comment thread integrations/cli/config.test.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/@tailwindcss-cli/src/commands/build/index.ts (1)

319-323: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve fullRebuildPaths until the reload succeeds.

Line 320 clears the tracked full-rebuild dependencies before createCompiler(...) has succeeded. If that rebuild fails because a config/import/plugin dependency was deleted, recreating the same file no longer triggers a full rebuild, so watch mode stays broken until some other tracked file changes. That’s why the new regression test has to touch src/index.css.

♻️ Possible fix
             clearRequireCache(resolvedFullRebuildPaths)
-            fullRebuildPaths = inputFilePath ? [inputFilePath] : []
-
-            // Create a new compiler, given the new `input`
-            ;[compiler, scanner] = await createCompiler(input, I)
+            let previousFullRebuildPaths = fullRebuildPaths
+            fullRebuildPaths = inputFilePath ? [inputFilePath] : []
+
+            // Create a new compiler, given the new `input`
+            try {
+              ;[compiler, scanner] = await createCompiler(input, I)
+            } catch (error) {
+              fullRebuildPaths = previousFullRebuildPaths
+              throw error
+            }
🤖 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 `@packages/`@tailwindcss-cli/src/commands/build/index.ts around lines 319 -
323, The code clears tracked full-rebuild dependencies
(clearRequireCache(resolvedFullRebuildPaths) and resetting fullRebuildPaths)
before attempting to create a new compiler, which can leave watch mode broken if
createCompiler(input, I) fails; change the flow so that you do NOT
clearRequireCache or mutate fullRebuildPaths until createCompiler(input, I) has
succeeded — either move clearRequireCache(resolvedFullRebuildPaths) and the
assignment fullRebuildPaths = inputFilePath ? [inputFilePath] : [] to after the
await createCompiler(...) line, or wrap createCompiler(...) in a try/catch and
only clear the require cache/assign fullRebuildPaths on success (and restore the
old state or leave it untouched on error), keeping references to the existing
variables compiler, scanner, inputFilePath, input and resolvedFullRebuildPaths
to locate the change.
🤖 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.

Outside diff comments:
In `@packages/`@tailwindcss-cli/src/commands/build/index.ts:
- Around line 319-323: The code clears tracked full-rebuild dependencies
(clearRequireCache(resolvedFullRebuildPaths) and resetting fullRebuildPaths)
before attempting to create a new compiler, which can leave watch mode broken if
createCompiler(input, I) fails; change the flow so that you do NOT
clearRequireCache or mutate fullRebuildPaths until createCompiler(input, I) has
succeeded — either move clearRequireCache(resolvedFullRebuildPaths) and the
assignment fullRebuildPaths = inputFilePath ? [inputFilePath] : [] to after the
await createCompiler(...) line, or wrap createCompiler(...) in a try/catch and
only clear the require cache/assign fullRebuildPaths on success (and restore the
old state or leave it untouched on error), keeping references to the existing
variables compiler, scanner, inputFilePath, input and resolvedFullRebuildPaths
to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 07f53fb2-8a9d-47b7-9f94-2fb50304e18e

📥 Commits

Reviewing files that changed from the base of the PR and between a8dceea and 05579f3.

📒 Files selected for processing (2)
  • integrations/cli/config.test.ts
  • packages/@tailwindcss-cli/src/commands/build/index.ts

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.

CLI watch does not rebuild when a tracked dependency is deleted

1 participant