Skip to content

Commit b3d1cbb

Browse files
Upgrade: Error when project is already using Tailwind CSS v4 (#15015)
In some local testing we ran the `@tailwindcss/upgrade` command twice in a row. It would be great to get some feedback that this is not working, so this PR now checks if it can resolve the installed version of `tailwindcss` and if it can, it requires it to be < 4 (you can bypass this check with `--force`). --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
1 parent 38c9a88 commit b3d1cbb

File tree

5 files changed

+81
-0
lines changed

5 files changed

+81
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- Allow `addUtilities()` and `addComponents()` to work with child combinators and other complex selectors ([#15029](https://github.com/tailwindlabs/tailwindcss/pull/15029))
1616
- _Upgrade (experimental)_: Migrate `[&>*]` to the `*` variant ([#15022](https://github.com/tailwindlabs/tailwindcss/pull/15022))
1717
- _Upgrade (experimental)_: Migrate `[&_*]` to the `**` variant ([#15022](https://github.com/tailwindlabs/tailwindcss/pull/15022))
18+
- _Upgrade (experimental)_: Warn when trying to migrating a project that is not on Tailwind CSS v3 ([#15015](https://github.com/tailwindlabs/tailwindcss/pull/15015))
1819

1920
### Fixed
2021

integrations/upgrade/index.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ test(
954954
'package.json': json`
955955
{
956956
"dependencies": {
957+
"tailwindcss": "^3",
957958
"@tailwindcss/upgrade": "workspace:^"
958959
}
959960
}
@@ -2463,3 +2464,37 @@ test(
24632464
`)
24642465
},
24652466
)
2467+
2468+
test(
2469+
'requires Tailwind v3 before attempting an upgrade',
2470+
{
2471+
fs: {
2472+
'package.json': json`
2473+
{
2474+
"dependencies": {
2475+
"tailwindcss": "workspace:^",
2476+
"@tailwindcss/upgrade": "workspace:^"
2477+
}
2478+
}
2479+
`,
2480+
'tailwind.config.ts': js` export default {} `,
2481+
'src/index.html': html`
2482+
<div class="underline"></div>
2483+
`,
2484+
'src/index.css': css`
2485+
@tailwind base;
2486+
@tailwind components;
2487+
@tailwind utilities;
2488+
`,
2489+
},
2490+
},
2491+
async ({ exec }) => {
2492+
let output = await exec('npx @tailwindcss/upgrade', {}, { ignoreStdErr: true }).catch((e) =>
2493+
e.toString(),
2494+
)
2495+
2496+
expect(output).toMatch(
2497+
/Tailwind CSS v.* found. The migration tool can only be run on v3 projects./,
2498+
)
2499+
},
2500+
)

integrations/upgrade/js-config.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ test(
99
'package.json': json`
1010
{
1111
"dependencies": {
12+
"tailwindcss": "^3",
1213
"@tailwindcss/upgrade": "workspace:^"
1314
}
1415
}
@@ -297,6 +298,7 @@ test(
297298
'package.json': json`
298299
{
299300
"dependencies": {
301+
"tailwindcss": "^3",
300302
"@tailwindcss/typography": "^0.5.15",
301303
"@tailwindcss/upgrade": "workspace:^"
302304
}
@@ -404,6 +406,7 @@ test(
404406
'package.json': json`
405407
{
406408
"dependencies": {
409+
"tailwindcss": "^3",
407410
"@tailwindcss/upgrade": "workspace:^"
408411
}
409412
}
@@ -485,6 +488,7 @@ test(
485488
'package.json': json`
486489
{
487490
"dependencies": {
491+
"tailwindcss": "^3",
488492
"@tailwindcss/upgrade": "workspace:^"
489493
}
490494
}
@@ -572,6 +576,7 @@ test(
572576
'package.json': json`
573577
{
574578
"dependencies": {
579+
"tailwindcss": "^3",
575580
"@tailwindcss/upgrade": "workspace:^"
576581
}
577582
}
@@ -640,6 +645,7 @@ test(
640645
'package.json': json`
641646
{
642647
"dependencies": {
648+
"tailwindcss": "^3",
643649
"@tailwindcss/upgrade": "workspace:^"
644650
}
645651
}
@@ -718,6 +724,7 @@ test(
718724
'package.json': json`
719725
{
720726
"dependencies": {
727+
"tailwindcss": "^3",
721728
"@tailwindcss/upgrade": "workspace:^"
722729
}
723730
}
@@ -838,6 +845,7 @@ test(
838845
'package.json': json`
839846
{
840847
"dependencies": {
848+
"tailwindcss": "^3",
841849
"@tailwindcss/upgrade": "workspace:^"
842850
}
843851
}
@@ -915,6 +923,7 @@ describe('border compatibility', () => {
915923
'package.json': json`
916924
{
917925
"dependencies": {
926+
"tailwindcss": "^3",
918927
"@tailwindcss/upgrade": "workspace:^"
919928
}
920929
}
@@ -973,6 +982,7 @@ describe('border compatibility', () => {
973982
'package.json': json`
974983
{
975984
"dependencies": {
985+
"tailwindcss": "^3",
976986
"@tailwindcss/upgrade": "workspace:^"
977987
}
978988
}
@@ -1034,6 +1044,7 @@ describe('border compatibility', () => {
10341044
'package.json': json`
10351045
{
10361046
"dependencies": {
1047+
"tailwindcss": "^3",
10371048
"@tailwindcss/upgrade": "workspace:^"
10381049
}
10391050
}
@@ -1077,6 +1088,7 @@ describe('border compatibility', () => {
10771088
'package.json': json`
10781089
{
10791090
"dependencies": {
1091+
"tailwindcss": "^3",
10801092
"@tailwindcss/upgrade": "workspace:^"
10811093
}
10821094
}
@@ -1136,6 +1148,7 @@ describe('border compatibility', () => {
11361148
'package.json': json`
11371149
{
11381150
"dependencies": {
1151+
"tailwindcss": "^3",
11391152
"@tailwindcss/upgrade": "workspace:^"
11401153
}
11411154
}
@@ -1219,6 +1232,7 @@ describe('border compatibility', () => {
12191232
'package.json': json`
12201233
{
12211234
"dependencies": {
1235+
"tailwindcss": "^3",
12221236
"@tailwindcss/upgrade": "workspace:^"
12231237
}
12241238
}
@@ -1330,6 +1344,7 @@ describe('border compatibility', () => {
13301344
'package.json': json`
13311345
{
13321346
"dependencies": {
1347+
"tailwindcss": "^3",
13331348
"@tailwindcss/upgrade": "workspace:^"
13341349
}
13351350
}
@@ -1443,6 +1458,7 @@ describe('border compatibility', () => {
14431458
'package.json': json`
14441459
{
14451460
"dependencies": {
1461+
"tailwindcss": "^3",
14461462
"@tailwindcss/upgrade": "workspace:^"
14471463
}
14481464
}

packages/@tailwindcss-upgrade/src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { prepareConfig } from './template/prepare-config'
2222
import { args, type Arg } from './utils/args'
2323
import { isRepoDirty } from './utils/git'
2424
import { hoistStaticGlobParts } from './utils/hoist-static-glob-parts'
25+
import { getPackageVersion } from './utils/package-version'
2526
import { pkg } from './utils/packages'
2627
import { eprintln, error, header, highlight, info, relative, success } from './utils/renderer'
2728

@@ -50,6 +51,7 @@ async function run() {
5051
let cleanup: (() => void)[] = []
5152

5253
if (!flags['--force']) {
54+
// Require a clean git directory
5355
if (isRepoDirty()) {
5456
error('Git directory is not clean. Please stash or commit your changes before migrating.')
5557
info(
@@ -59,6 +61,15 @@ async function run() {
5961
}
6062
}
6163

64+
// Require an installed `tailwindcss` version < 4
65+
let tailwindVersion = await getPackageVersion('tailwindcss', base)
66+
if (tailwindVersion && Number(tailwindVersion.split('.')[0]) !== 3) {
67+
error(
68+
`Tailwind CSS v${tailwindVersion} found. The migration tool can only be run on v3 projects.`,
69+
)
70+
process.exit(1)
71+
}
72+
6273
{
6374
// Stylesheet migrations
6475

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import fs from 'node:fs/promises'
2+
import { createRequire } from 'node:module'
3+
4+
const localResolve = createRequire(import.meta.url).resolve
5+
6+
/**
7+
* Resolves the version string of an npm dependency installed in the based
8+
* directory.
9+
*/
10+
export async function getPackageVersion(pkg: string, base: string): Promise<string | null> {
11+
try {
12+
let packageJson = localResolve(`${pkg}/package.json`, { paths: [base] })
13+
let { version } = JSON.parse(await fs.readFile(packageJson, 'utf8'))
14+
return version
15+
} catch {
16+
return null
17+
}
18+
}

0 commit comments

Comments
 (0)