Skip to content

fix(upgrade): use v3 config content patterns when no @source is set#19779

Closed
SychO9 wants to merge 1 commit intotailwindlabs:mainfrom
SychO9:fix/upgrade-scan-scope-and-skip-unchanged-writes
Closed

fix(upgrade): use v3 config content patterns when no @source is set#19779
SychO9 wants to merge 1 commit intotailwindlabs:mainfrom
SychO9:fix/upgrade-scan-scope-and-skip-unchanged-writes

Conversation

@SychO9
Copy link
Copy Markdown
Contributor

@SychO9 SychO9 commented Mar 10, 2026

Summary

Fixes two main problems I've come across on every project i try tp upgrade from v3 to v4:

  1. It ignores my tailwind.config.js's content and tries to go through every single file in the project.
  2. It wipes out files, and since it goes through every single file, it just wipes out all files.

When migrating from v3 to v4, the CSS entrypoint has no @source directive yet, leaving compiler.root as null. The fallback to '**/*' caused the tool to scan every file in the project (PHP migrations, config files, etc.) and unconditionally write them all back to disk.

Proposed solution:

  • Use the v3 JS config's content patterns (config.sources) as the scan scope when compiler.root is null, falling back to '**/*' only when no config sources are available
  • Skip fs.writeFile when the migrated content is identical to the original

This is likely a bug introduced from allowing the upgrade tool to also run on tailwind v4 projects.

8e826b1

…skip writes when content is unchanged

When migrating from v3 to v4, the CSS entrypoint has no @source directive
yet, leaving compiler.root as null. The fallback to '**/*' caused the tool
to scan every file in the project (PHP migrations, config files, etc.) and
unconditionally write them all back to disk.

- Use the v3 JS config's content patterns (config.sources) as the scan
  scope when compiler.root is null, falling back to '**/*' only when no
  config sources are available
- Move config lookup before the sources IIFE to avoid a TDZ error
- Skip fs.writeFile when the migrated content is identical to the original
@SychO9 SychO9 requested a review from a team as a code owner March 10, 2026 14:57
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

Walkthrough

This pull request modifies two files in the Tailwind CSS upgrade codemod package. The first change optimizes the template migration process by computing migrated content once and writing to the file only when the content differs from the original. The second change refactors configuration retrieval logic to fetch per-sheet configuration early and uses it to influence source file discovery during v3→v4 migrations. When compiler.root is null, the source discovery now respects per-sheet configuration sources instead of using a broad pattern scan, and removes a redundant configuration retrieval call.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: using v3 config content patterns when @source is not set, which directly addresses the core fix in the PR.
Description check ✅ Passed The description is clearly related to the changeset, explaining the problems encountered, the proposed solutions, and how the changes address the issues of file scanning and unnecessary writes.

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

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

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.

🧹 Nitpick comments (1)
packages/@tailwindcss-upgrade/src/index.ts (1)

305-314: Logic looks correct; minor type inconsistency in sources array.

The fallback logic correctly addresses the PR objective: when compiler.root is null during v3→v4 migration, the tool now uses the v3 config's content patterns instead of blindly scanning **/*.

However, there's a minor type inconsistency: config.sources (line 311) returns { base: string; pattern: string }[] without a negated property, while the fallback at line 313 and the regular case at line 317 add negated: false. This creates a mixed-type array when concatenated at line 318.

Since the downstream Scanner only reads base and pattern fields (per the Rust struct definition), this won't cause runtime issues, but you may want to normalize the shape for consistency.

♻️ Optional: Normalize source entries to consistent shape
          if (compiler.root === null) {
            if (config?.sources && config.sources.length > 0) {
-              return config.sources
+              return config.sources.map((s) => ({ ...s, negated: false }))
            }
            return [{ base, pattern: '**/*', negated: false }]
          }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/`@tailwindcss-upgrade/src/index.ts around lines 305 - 314, When
compiler.root is null the code returns config.sources which lacks the negated
field and later merges with entries that include negated: false; normalize the
shape by mapping each item in config.sources to include negated: false before
returning or concatenating so the array elements all share { base, pattern,
negated } shape; update the logic around compiler.root / config.sources in
packages/@tailwindcss-upgrade/src/index.ts (referencing compiler.root and
config.sources) to transform config.sources entries (e.g., via a .map) to add
negated: false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/`@tailwindcss-upgrade/src/index.ts:
- Around line 305-314: When compiler.root is null the code returns
config.sources which lacks the negated field and later merges with entries that
include negated: false; normalize the shape by mapping each item in
config.sources to include negated: false before returning or concatenating so
the array elements all share { base, pattern, negated } shape; update the logic
around compiler.root / config.sources in
packages/@tailwindcss-upgrade/src/index.ts (referencing compiler.root and
config.sources) to transform config.sources entries (e.g., via a .map) to add
negated: false.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: efc768ee-1ff5-4e4a-b003-d447618b5678

📥 Commits

Reviewing files that changed from the base of the PR and between c586bd6 and df535b2.

📒 Files selected for processing (2)
  • packages/@tailwindcss-upgrade/src/codemods/template/migrate.ts
  • packages/@tailwindcss-upgrade/src/index.ts

Fergarram pushed a commit to Fergarram/tailwindcss that referenced this pull request Mar 14, 2026
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.

### What changed?




#### ✳️ eslint (9.27.0 → 9.29.0) ·
[Repo](https://github.com/eslint/eslint) ·
[Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)



<details>
<summary>Release Notes</summary>
<h4><a
href="https://github.com/eslint/eslint/releases/tag/v9.29.0">9.29.0</a></h4>

<blockquote><h2 dir="auto">Features</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/f686fcb51e47cf53b891ae595684afe8a0ef584d"><code
class="notranslate">f686fcb</code></a> feat: add <code
class="notranslate">ecmaVersion: 2026</code>, parsing <code
class="notranslate">using</code> and <code class="notranslate">await
using</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19832">#19832</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/19cdd226bb5957f8f7e8cb4e92d38aafe47f8ff4"><code
class="notranslate">19cdd22</code></a> feat: prune suppressions for
non-existent files (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19825">#19825</a>)
(TKDev7)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b3d720f82f08022a33b10f0437111e7d270b8e3c"><code
class="notranslate">b3d720f</code></a> feat: add ES2025 globals (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19835">#19835</a>)
(fisker Cheung)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/677a2837a17320f54a8869682af128a2a7d77579"><code
class="notranslate">677a283</code></a> feat: add auto-accessor fields
support to class-methods-use-this (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19789">#19789</a>)
(sethamus)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/dbba0589f5509223658b73de6eb721f659bcec47"><code
class="notranslate">dbba058</code></a> feat: allow global type
declaration in <code class="notranslate">no-var</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19714">#19714</a>)
(Remco Haszing)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/342bd29e1a10a4b521ed0dbb6d889dcfc137e863"><code
class="notranslate">342bd29</code></a> feat: ignore type annotations in
no-restricted-globals (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19781">#19781</a>)
(sethamus)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/786bcd13652b90c5bd0c7201610b856ad1b87542"><code
class="notranslate">786bcd1</code></a> feat: add allowProperties option
to no-restricted-properties (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19772">#19772</a>)
(sethamus)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/05b66d05bd68214f2fa1ab53fb2734c9d9e5348a"><code
class="notranslate">05b66d0</code></a> feat: add <code
class="notranslate">sourceCode.isGlobalReference(node)</code> method (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19695">#19695</a>)
(Nitin Kumar)</li>
</ul>
<h2 dir="auto">Bug Fixes</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/85c082c54bd42ad818f5938b8fb1fb2aa0a1912f"><code
class="notranslate">85c082c</code></a> fix: explicit matching behavior
with negated patterns and arrays (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19845">#19845</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/9bda4a9bf18c9fef91cdd93921a0935ffcf9a9fc"><code
class="notranslate">9bda4a9</code></a> fix: fix <code
class="notranslate">LintOptions.filterCodeBlock</code> types (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19837">#19837</a>)
(ntnyq)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/7ab77a2c7605126daaa7e7f7ab75b5c252677d12"><code
class="notranslate">7ab77a2</code></a> fix: correct breaking deprecation
of FlatConfig type (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19826">#19826</a>)
(Logicer)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/1ba33181ab300588a803434884c054ed003f0bbd"><code
class="notranslate">1ba3318</code></a> fix: add <code
class="notranslate">language</code> and <code
class="notranslate">dialects</code> to <code
class="notranslate">no-use-before-define</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19808">#19808</a>)
(Francesco Trotta)</li>
</ul>
<h2 dir="auto">Documentation</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/00e3e6ad1357df7d46be51d3f305efecb90244a7"><code
class="notranslate">00e3e6a</code></a> docs: add support for custom name
parameter to <code class="notranslate">includeIgnoreFile</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19795">#19795</a>)
(루밀LuMir)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/3aed0756ed3669ac27fc243c81fd82e3d0e6973b"><code
class="notranslate">3aed075</code></a> docs: Update README (GitHub
Actions Bot)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a2f888d679e2a44964da596a4158911819e1d31d"><code
class="notranslate">a2f888d</code></a> docs: enhance documentation with
links and fix typos (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19761">#19761</a>)
(루밀LuMir)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/53c3235ba1c90a85a44f0abd18998ccc4e0445bf"><code
class="notranslate">53c3235</code></a> docs: update to clarify prompt
usage (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19748">#19748</a>)
(Jennifer Davis)</li>
</ul>
<h2 dir="auto">Chores</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/5c114c962f29d0b33e6439e9ab0985014af06b9f"><code
class="notranslate">5c114c9</code></a> chore: upgrade @eslint/[email protected]
(<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19851">#19851</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/acf2201a067d062e007b1b7b164b8e96fa1af50f"><code
class="notranslate">acf2201</code></a> chore: package.json update for
@eslint/js release (Jenkins)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a806994263e54e4bc1481736b1c0626c8b770808"><code
class="notranslate">a806994</code></a> refactor: Remove eslintrc from
flat config functionality (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19833">#19833</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/152ed51329d82c6e7375f41a105e01b31750e17f"><code
class="notranslate">152ed51</code></a> test: switch to flat config mode
in code path analysis tests (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19824">#19824</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b647239272931e0a947500b2f554fc8ccdf8adfd"><code
class="notranslate">b647239</code></a> chore: Update first-party
dependencies faster with Renovate (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19822">#19822</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/7abe42e2de931289e19e34e390d16936cf6faf64"><code
class="notranslate">7abe42e</code></a> refactor: SafeEmitter -&gt;
SourceCodeVisitor (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19708">#19708</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e39289596757702b6c8d747d5ab9c1a7820c108f"><code
class="notranslate">e392895</code></a> perf: improve time complexity of
<code class="notranslate">getLocFromIndex</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19782">#19782</a>)
(루밀LuMir)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0ed289c5ceed1c10b599b22c8b9374a5a3a144dd"><code
class="notranslate">0ed289c</code></a> chore: remove accidentally
committed file (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19807">#19807</a>)
(Francesco Trotta)</li>
</ul></blockquote>
<h4><a
href="https://github.com/eslint/eslint/releases/tag/v9.28.0">9.28.0</a></h4>

<blockquote><h2 dir="auto">Features</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b0674be94e4394401b4f668453a473572c321023"><code
class="notranslate">b0674be</code></a> feat: Customization of
serialization for languageOptions (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19760">#19760</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a95721f1064fdbfe0e392b955ce3053a24551f80"><code
class="notranslate">a95721f</code></a> feat: Add <code
class="notranslate">--pass-on-unpruned-suppressions</code> CLI option
(<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19773">#19773</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/bfd0e7a39535b3c1ddc742dfffa6bdcdc93079e2"><code
class="notranslate">bfd0e7a</code></a> feat: support TypeScript syntax
in <code class="notranslate">no-use-before-define</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19566">#19566</a>)
(Tanuj Kanti)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/68c61c093a885623e48f38026e3f3a05bfa403de"><code
class="notranslate">68c61c0</code></a> feat: support TS syntax in <code
class="notranslate">no-shadow</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19565">#19565</a>)
(Nitin Kumar)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0f773ef248af0301a410fee11e1b22174100cf6a"><code
class="notranslate">0f773ef</code></a> feat: support TS syntax in <code
class="notranslate">no-magic-numbers</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19561">#19561</a>)
(Nitin Kumar)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c4a6b6051889b1cb668d4d2ae29e9c27c74993d6"><code
class="notranslate">c4a6b60</code></a> feat: add allowTypeAnnotation to
func-style (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19754">#19754</a>)
(sethamus)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b03ad176f158afdd921f0af5126c398012b10559"><code
class="notranslate">b03ad17</code></a> feat: add TypeScript support to
<code class="notranslate">prefer-arrow-callback</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19678">#19678</a>)
(Tanuj Kanti)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/bc3c3313ce2719062805b6849d29f9a375cf23f2"><code
class="notranslate">bc3c331</code></a> feat: ignore overloaded function
declarations in func-style rule (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19755">#19755</a>)
(sethamus)</li>
</ul>
<h2 dir="auto">Bug Fixes</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/eea3e7eb1ca84f9e8870e1190d65d5235d9d8429"><code
class="notranslate">eea3e7e</code></a> fix: Remove configured global
variables from <code class="notranslate">GlobalScope#implicit</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19779">#19779</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a467de39f6e509af95a7963904326635c1bf7116"><code
class="notranslate">a467de3</code></a> fix: update context.report types
(<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19751">#19751</a>)
(Nitin Kumar)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/fd467bb892d735a4a8863beabd181a3f3152689a"><code
class="notranslate">fd467bb</code></a> fix: remove interopDefault to use
jiti's default (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19697">#19697</a>)
(sethamus)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/72d16e3066aac2f1c74f4150ba43dfa8cf532584"><code
class="notranslate">72d16e3</code></a> fix: avoid false positive in
<code class="notranslate">no-unassigned-vars</code> for declare module
(<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19746">#19746</a>)
(Azat S.)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/81c3c936266474c2081f310098084bd0eb1768d2"><code
class="notranslate">81c3c93</code></a> fix: curly types (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19750">#19750</a>)
(Eli)</li>
</ul>
<h2 dir="auto">Documentation</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/3ec208233f29c161aae8f99f9f091e371fe83a62"><code
class="notranslate">3ec2082</code></a> docs: Nested arrays in files
config entry (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19799">#19799</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/89a65b07f6171a860284b62d97c8b3edf312b98c"><code
class="notranslate">89a65b0</code></a> docs: clarify how config arrays
can apply to subsets of files (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19788">#19788</a>)
(Shais Ch)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2ba8a0d75c7a8e6aa4798275126698be40391d37"><code
class="notranslate">2ba8a0d</code></a> docs: Add description of
meta.namespace to plugin docs (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19798">#19798</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/59dd7e6b28507053bde985ea2311dca8ec0db681"><code
class="notranslate">59dd7e6</code></a> docs: update <code
class="notranslate">func-style</code> with examples (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19793">#19793</a>)
(Tanuj Kanti)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e9129e0799d068c377d63d59a0a800e7d1fea8dd"><code
class="notranslate">e9129e0</code></a> docs: add global scope's <code
class="notranslate">implicit</code> field to Scope Manager docs (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19770">#19770</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/52f5b7a0af48a2f143f0bccfd4e036025b08280d"><code
class="notranslate">52f5b7a</code></a> docs: fix minor typos and add
links (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19743">#19743</a>)
(루밀LuMir)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/00716a339ede24ed5a76aceed833f38a6c4e8d3a"><code
class="notranslate">00716a3</code></a> docs: upfront recommend against
using the no-return-await rule (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19727">#19727</a>)
(Mike DiDomizio)</li>
</ul>
<h2 dir="auto">Chores</h2>
<ul dir="auto">
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/175b7b83fcdc8f3f84821510dd7e04d120402317"><code
class="notranslate">175b7b8</code></a> chore: upgrade to <code
class="notranslate">@eslint/[email protected]</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19802">#19802</a>)
(Francesco Trotta)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/844f5a69dc78ca38f856c137e061e8facc9d00ba"><code
class="notranslate">844f5a6</code></a> chore: package.json update for
@eslint/js release (Jenkins)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/62b1c1bc7981798c3aec2dd430c200c797a25629"><code
class="notranslate">62b1c1b</code></a> chore: update globals to v16 (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19791">#19791</a>)
(Nitin Kumar)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e8a1cb8f7fbc18efa589bfedea5326de636b4868"><code
class="notranslate">e8a1cb8</code></a> chore: ignore jiti-v2.0 &amp;
jiti-v2.1 for renovate (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19786">#19786</a>)
(Nitin Kumar)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/43d39754b6d315954f46a70dbd53d1fa0eea1619"><code
class="notranslate">43d3975</code></a> chore: Add Copilot Instructions
file (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19753">#19753</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2dfb5ebef4c14d552d10a6c7c2c2ce376e63654a"><code
class="notranslate">2dfb5eb</code></a> test: update <code
class="notranslate">SourceCodeTraverser</code> tests (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19763">#19763</a>)
(Milos Djermanovic)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/5bc21f9e8e00f9e49442d1b6520b307ce94f3518"><code
class="notranslate">5bc21f9</code></a> chore: add <code
class="notranslate">*.code-workspace</code> to <code
class="notranslate">.gitignore</code> (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19771">#19771</a>)
(루밀LuMir)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/f4fa40eb4bd6f4dba3b2e7fff259d0780ef6becf"><code
class="notranslate">f4fa40e</code></a> refactor: NodeEventGenerator
-&gt; SourceCodeTraverser (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19679">#19679</a>)
(Nicholas C. Zakas)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0f49329b4a7f91714f2cd1e9ce532d32202c47f4"><code
class="notranslate">0f49329</code></a> refactor: use a service to emit
warnings (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19725">#19725</a>)
(Francesco Trotta)</li>
<li>
<a
href="https://bounce.depfu.com/github.com/eslint/eslint/commit/20a9e59438fde3642ab058cc55ee1b9fa02b6391"><code
class="notranslate">20a9e59</code></a> chore: update dependency shelljs
to ^0.10.0 (<a
href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19740">#19740</a>)
(renovate[bot])</li>
</ul></blockquote>
<p><em>Does any of this look wrong? <a
href="https://depfu.com/packages/npm/eslint/feedback">Please let us
know.</a></em></p>
</details>

<details>
<summary>Commits</summary>
<p><a
href="https://github.com/eslint/eslint/compare/b9080cf28d88f934941a545a033eb960eceeadbd...edf232b680390013c68f081a5e41843bcf2dd18f">See
the full diff on Github</a>. The new version differs by 58 commits:</p>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/edf232b680390013c68f081a5e41843bcf2dd18f"><code>9.29.0</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/c2414b647baaa75303ef647e134b2520c10bf6e0"><code>Build:
changelog update for 9.29.0</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/5c114c962f29d0b33e6439e9ab0985014af06b9f"><code>chore:
upgrade @eslint/[email protected] (tailwindlabs#19851)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/acf2201a067d062e007b1b7b164b8e96fa1af50f"><code>chore:
package.json update for @eslint/js release</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/f686fcb51e47cf53b891ae595684afe8a0ef584d"><code>feat:
add `ecmaVersion: 2026`, parsing `using` and `await using`
(tailwindlabs#19832)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/85c082c54bd42ad818f5938b8fb1fb2aa0a1912f"><code>fix:
explicit matching behavior with negated patterns and arrays
(tailwindlabs#19845)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/00e3e6ad1357df7d46be51d3f305efecb90244a7"><code>docs:
add support for custom name parameter to `includeIgnoreFile`
(tailwindlabs#19795)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/9bda4a9bf18c9fef91cdd93921a0935ffcf9a9fc"><code>fix:
fix `LintOptions.filterCodeBlock` types (tailwindlabs#19837)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/a806994263e54e4bc1481736b1c0626c8b770808"><code>refactor:
Remove eslintrc from flat config functionality (tailwindlabs#19833)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/19cdd226bb5957f8f7e8cb4e92d38aafe47f8ff4"><code>feat:
prune suppressions for non-existent files (tailwindlabs#19825)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/b3d720f82f08022a33b10f0437111e7d270b8e3c"><code>feat:
add ES2025 globals (tailwindlabs#19835)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/677a2837a17320f54a8869682af128a2a7d77579"><code>feat:
add auto-accessor fields support to class-methods-use-this
(tailwindlabs#19789)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/3aed0756ed3669ac27fc243c81fd82e3d0e6973b"><code>docs:
Update README</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/7ab77a2c7605126daaa7e7f7ab75b5c252677d12"><code>fix:
correct breaking deprecation of FlatConfig type (tailwindlabs#19826)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/a2f888d679e2a44964da596a4158911819e1d31d"><code>docs:
enhance documentation with links and fix typos (tailwindlabs#19761)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/dbba0589f5509223658b73de6eb721f659bcec47"><code>feat:
allow global type declaration in `no-var` (tailwindlabs#19714)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/152ed51329d82c6e7375f41a105e01b31750e17f"><code>test:
switch to flat config mode in code path analysis tests
(tailwindlabs#19824)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/b647239272931e0a947500b2f554fc8ccdf8adfd"><code>chore:
Update first-party dependencies faster with Renovate
(tailwindlabs#19822)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/7abe42e2de931289e19e34e390d16936cf6faf64"><code>refactor:
SafeEmitter -&gt; SourceCodeVisitor (tailwindlabs#19708)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/342bd29e1a10a4b521ed0dbb6d889dcfc137e863"><code>feat:
ignore type annotations in no-restricted-globals
(tailwindlabs#19781)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/e39289596757702b6c8d747d5ab9c1a7820c108f"><code>perf:
improve time complexity of `getLocFromIndex` (tailwindlabs#19782)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/1ba33181ab300588a803434884c054ed003f0bbd"><code>fix:
add `language` and `dialects` to `no-use-before-define`
(tailwindlabs#19808)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/786bcd13652b90c5bd0c7201610b856ad1b87542"><code>feat:
add allowProperties option to no-restricted-properties
(tailwindlabs#19772)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/05b66d05bd68214f2fa1ab53fb2734c9d9e5348a"><code>feat:
add `sourceCode.isGlobalReference(node)` method (tailwindlabs#19695)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/53c3235ba1c90a85a44f0abd18998ccc4e0445bf"><code>docs:
update to clarify prompt usage (tailwindlabs#19748)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/0ed289c5ceed1c10b599b22c8b9374a5a3a144dd"><code>chore:
remove accidentally committed file (tailwindlabs#19807)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/f341f21e024388e602cfccee06e11b9113a2d298"><code>9.28.0</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/779dda93a25a0e9da934a96311e5f97985e4401c"><code>Build:
changelog update for 9.28.0</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/175b7b83fcdc8f3f84821510dd7e04d120402317"><code>chore:
upgrade to `@eslint/[email protected]` (tailwindlabs#19802)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/844f5a69dc78ca38f856c137e061e8facc9d00ba"><code>chore:
package.json update for @eslint/js release</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/b0674be94e4394401b4f668453a473572c321023"><code>feat:
Customization of serialization for languageOptions
(tailwindlabs#19760)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/3ec208233f29c161aae8f99f9f091e371fe83a62"><code>docs:
Nested arrays in files config entry (tailwindlabs#19799)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/89a65b07f6171a860284b62d97c8b3edf312b98c"><code>docs:
clarify how config arrays can apply to subsets of files
(tailwindlabs#19788)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/2ba8a0d75c7a8e6aa4798275126698be40391d37"><code>docs:
Add description of meta.namespace to plugin docs
(tailwindlabs#19798)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/eea3e7eb1ca84f9e8870e1190d65d5235d9d8429"><code>fix:
Remove configured global variables from `GlobalScope#implicit`
(tailwindlabs#19779)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/a95721f1064fdbfe0e392b955ce3053a24551f80"><code>feat:
Add `--pass-on-unpruned-suppressions` CLI option
(tailwindlabs#19773)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/a467de39f6e509af95a7963904326635c1bf7116"><code>fix:
update context.report types (tailwindlabs#19751)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/59dd7e6b28507053bde985ea2311dca8ec0db681"><code>docs:
update `func-style` with examples (tailwindlabs#19793)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/62b1c1bc7981798c3aec2dd430c200c797a25629"><code>chore:
update globals to v16 (tailwindlabs#19791)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/bfd0e7a39535b3c1ddc742dfffa6bdcdc93079e2"><code>feat:
support TypeScript syntax in `no-use-before-define`
(tailwindlabs#19566)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/68c61c093a885623e48f38026e3f3a05bfa403de"><code>feat:
support TS syntax in `no-shadow` (tailwindlabs#19565)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/e8a1cb8f7fbc18efa589bfedea5326de636b4868"><code>chore:
ignore jiti-v2.0 &amp; jiti-v2.1 for renovate (tailwindlabs#19786)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/0f773ef248af0301a410fee11e1b22174100cf6a"><code>feat:
support TS syntax in `no-magic-numbers` (tailwindlabs#19561)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/43d39754b6d315954f46a70dbd53d1fa0eea1619"><code>chore:
Add Copilot Instructions file (tailwindlabs#19753)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/c4a6b6051889b1cb668d4d2ae29e9c27c74993d6"><code>feat:
add allowTypeAnnotation to func-style (tailwindlabs#19754)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/fd467bb892d735a4a8863beabd181a3f3152689a"><code>fix:
remove interopDefault to use jiti&tailwindlabs#39;s default (tailwindlabs#19697)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/2dfb5ebef4c14d552d10a6c7c2c2ce376e63654a"><code>test:
update `SourceCodeTraverser` tests (tailwindlabs#19763)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/b03ad176f158afdd921f0af5126c398012b10559"><code>feat:
add TypeScript support to `prefer-arrow-callback`
(tailwindlabs#19678)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/e9129e0799d068c377d63d59a0a800e7d1fea8dd"><code>docs:
add global scope&tailwindlabs#39;s `implicit` field to Scope Manager docs
(tailwindlabs#19770)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/bc3c3313ce2719062805b6849d29f9a375cf23f2"><code>feat:
ignore overloaded function declarations in func-style rule
(tailwindlabs#19755)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/5bc21f9e8e00f9e49442d1b6520b307ce94f3518"><code>chore:
add `*.code-workspace` to `.gitignore` (tailwindlabs#19771)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/72d16e3066aac2f1c74f4150ba43dfa8cf532584"><code>fix:
avoid false positive in `no-unassigned-vars` for declare module
(tailwindlabs#19746)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/f4fa40eb4bd6f4dba3b2e7fff259d0780ef6becf"><code>refactor:
NodeEventGenerator -&gt; SourceCodeTraverser (tailwindlabs#19679)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/81c3c936266474c2081f310098084bd0eb1768d2"><code>fix:
curly types (tailwindlabs#19750)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/52f5b7a0af48a2f143f0bccfd4e036025b08280d"><code>docs:
fix minor typos and add links (tailwindlabs#19743)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/0f49329b4a7f91714f2cd1e9ce532d32202c47f4"><code>refactor:
use a service to emit warnings (tailwindlabs#19725)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/20a9e59438fde3642ab058cc55ee1b9fa02b6391"><code>chore:
update dependency shelljs to ^0.10.0 (tailwindlabs#19740)</code></a></li>
<li><a
href="https://github.com/eslint/eslint/commit/00716a339ede24ed5a76aceed833f38a6c4e8d3a"><code>docs:
upfront recommend against using the no-return-await rule
(tailwindlabs#19727)</code></a></li>
</ul>
</details>












---
![Depfu
Status](https://depfu.com/badges/edd6acd35d74c8d41cbb540c30442adf/stats.svg)

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.

<details><summary>All Depfu comment commands</summary>
<blockquote><dl>
<dt>@​depfu rebase</dt><dd>Rebases against your default branch and
redoes this update</dd>
<dt>@​depfu recreate</dt><dd>Recreates this PR, overwriting any edits
that you've made to it</dd>
<dt>@​depfu merge</dt><dd>Merges this PR once your tests are passing and
conflicts are resolved</dd>
<dt>@​depfu cancel merge</dt><dd>Cancels automatic merging of this
PR</dd>
<dt>@​depfu close</dt><dd>Closes this PR and deletes the branch</dd>
<dt>@​depfu reopen</dt><dd>Restores the branch and reopens this PR (if
it's closed)</dd>
<dt>@​depfu pause</dt><dd>Ignores all future updates for this dependency
and closes this PR</dd>
<dt>@​depfu pause [minor|major]</dt><dd>Ignores all future minor/major
updates for this dependency and closes this PR</dd>
<dt>@​depfu resume</dt><dd>Future versions of this dependency will
create PRs again (leaves this PR as is)</dd>
</dl></blockquote>
</details>

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
pull bot pushed a commit to steinsi/Tailwind that referenced this pull request Mar 24, 2026
This PR is an attempt to make the upgrade tooling more stable.


### TL;DR

1. When migrating from Tailwind CSS v3 → Tailwind CSS v4, only migrate
files listed in the `config.content` instead of relying on v4's auto
content detection feature
2. Skip writing files that have not been changed
3. Write changed files in a safe way: first write to a temporary file,
then rename the file atomically
4. Never migrate files that are git ignored, even if they are listed in
the `config.content` file
5. Always ignore `.env` and `.env.*` files when scanning for files. Most
people will have this in their `.gitignore` file, but if not, then this
is a fallback mechanism.

---

Looking at the tailwindlabs#18972 issue, it looks like some people are running into
weird situations where some of the contents is just gone.

I have never been able to reproduce this on my own devices and in my own
projects unfortunately. But there is definitely _something_ happening
that's not right that people are running into.

Therefore, this PR is an attempt to fix what I think _might_ be wrong,
but I'm not 100% sure if these fixes are enough, or if something else is
still happening here.

This builds on top of the tailwindlabs#19779 PR which has some small fixes, but is
incomplete to make this work.

### What's happening

Looking at some of the comments, it looks like a few things are
happening such as:

1. The upgrade tool is emptying out my files — it looks like these are
only happening if you ctrl+c while the process is taking a while. It
could be that a lot of files are being checked and therefore the tooling
looks like its stuck.
6. The upgrade tool is looking at files it shouldn't look at — in
Tailwind CSS v4 we have this concept of the auto-content detection. This
means that we will look at any plain text file that is not git ignored.

### Fixes


#### Emptying out files

The files being emptied looks like it's because how `fs.writeFile`
behaves by default. It opens the file handle with the `w` flag, which
will first truncate the file before writing the new contents. This is
not a single atomic operation, so a killed process in the middle will
cause invalid state.

When we migrate your template files, everything is happening in promises
to migrate things at the same time. When a lot of files are being
scanned, truncating might have happened already before we write the new
content. Since we migrate a bunch of files in parallel, a ctrl+c could
cause data loss in multiple files.

To mitigate this, I switched to an alternative way of writing files. 

1. First, we do some quick checks where if the contents didn't change we
just bail out immediately. Files that don't include Tailwind CSS classes
won't change, and therefore we don't need to override these files with
the same contents.
2. When the migrated contents is empty, we bail out as well. I'm 100%
sure that this is not the spot where the "emptying out" happens, I still
believe it happens in the `writeFile` itself, but added it just in case.
7. Next, I introduced a safe write, where we first write to a temporary
file in the same folder. We could write it to `/tmp`, but then we can't
guarantee that we are on the same file system.
   
If we ctrl+c at this stage, then the worst case scenario is that you
have additional temporary files in your project, but your original files
are still there.
   
Once that file was written, we will use the atomic `fs.rename`. This
should be atomic as long as we are on the same file system, so either
the rename didn't happen yet, or it completed.

I added an integration test for this, but I had to change the
`writeFile` implementation slightly. In the test, we will truncate the
file first, after that we will write the new contents. This is so that
we have enough time to kill the current process and allows us to verify
that we didn't clear out the file. Again, this is a hacky way of testing
this, just because I can't reproduce this issue myself, let alone
reproduce it reliable in a CI environment.

Note: we are also using `realpath` to make sure that we are updating the
real file. Otherwise, if we were dealing with a symlinked file, we would
override the symlink with a "hard" copy instead.

#### Touching files that should not be touched

During the migration, we rely on the Tailwind CSS v4 auto detection
logic which means that it will scan any plain text file that is not git
ignored. Therefore changes to php files could happen because in theory
they could contain Tailwind CSS classes.

To solve this, when migrating from Tailwind CSS v3 to Tailwind CSS v4,
we will _only_ take the sources into account that were listed in the
`config.content` array. Since this was a requirement in Tailwind CSS v3,
it should be safe to rely on this array.

Additionally, this will make sure that we are dealing with way fewer
files to migrate as well.

On top of that, files that match the patterns in the content array that
are git ignored will also be skipped. This is to prevent that we mutate
files in `node_modules` for example.

In one of the comments I read that `.env` files were emptied out. In
most cases people will have these files gitignored but I explicitly
added `.env` and `.env.*` as files to never ever touch by default when
scanning.

Last but not least, this also updates the output a little bit of the
upgrade tool in case we skip content files (because of git ignore) and
if we changed a file.

<img width="1122" height="1376" alt="image"
src="https://github.com/user-attachments/assets/318fdbbf-e319-4c7e-9648-ee9283842624"
/>

- "Git ignored folder, skipping: `./node_modules`": this is because the
content array looks like this while the `node_modules` are being
ignored:
<img width="1090" height="398" alt="image"
src="https://github.com/user-attachments/assets/7d694720-5671-47ec-bb2e-f24c5f2c4248"
/>

- "Migrated
`./resources/views/vendor/filament-panels/components/logo.blade.php`":
this is because **I** made a change to showcase this feature.

Fixes: tailwindlabs#18972
Closes: tailwindlabs#19779

### Test plan

1. Existing tests still pass
1. Added a dedicated integration test to ensure that we only take
`config.content` into account when migrating from Tailwind CSS v3 to
Tailwind CSS v4 projects.
1. Added a dedicated integration test to make sure that files listed in
`config.content` that are also git ignored, will still be skipped.
1. Added a dedicated integration test to ensure that when `writeFile` is
cancelled mid-write that our old files are still present.
1. Added a dedicated integration test to ensure that we ignore `.env`
and `.env.*` files even if you didn't git ignore them.

[ci-all] To verify on Windows

---------

Co-authored-by: Sami <[email protected]>
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