Skip to content

Commit 793c537

Browse files
fix(cli): avoid npx during upgrade command (#10479)
**Problem** Fixes #10466. During `yarn rw upgrade` we check the version of `npx` installed. It's entirely possible that `npx` is not available or installed. We only do this check because we have to handle dedupe differently between yarn v1 and yarn >v1. We specify that redwood projects should be using yarn v4 using `"packageManager": "[email protected]"` in the `package.json`. Therefore when following the recommended setup users should not be using yarn v1 in their redwood projects. **Changes** 1. Avoid `npx` version check. 2. Skip dedupe step if for some reason have yarn v1. When this happens we log a warning message to tell the user to run a command manually to dedupe.
1 parent 942f296 commit 793c537

File tree

2 files changed

+39
-39
lines changed

2 files changed

+39
-39
lines changed

.changesets/10479.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- fix(cli): avoid `npx` during upgrade command (#10479) by @Josh-Walker-GM
2+
3+
This change fixes a problem with the `yarn rw upgrade` command when you don't have `npx` installed. If you don't have `npx` installed you will now have to manually run a command to dedupe dependencies rather than this being done for you automatically during the upgrade command. If this is the case, the `npx` command will be logged to the console when you run `yarn rw upgrade`.

packages/cli/src/commands/upgrade.js

+36-39
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const builder = (yargs) => {
2020
yargs
2121
.example(
2222
'rw upgrade -t 0.20.1-canary.5',
23-
'Specify a version. URL for Version History:\nhttps://www.npmjs.com/package/@redwoodjs/core'
23+
'Specify a version. URL for Version History:\nhttps://www.npmjs.com/package/@redwoodjs/core',
2424
)
2525
.option('dry-run', {
2626
alias: 'd',
@@ -49,11 +49,11 @@ export const builder = (yargs) => {
4949
.epilogue(
5050
`Also see the ${terminalLink(
5151
'Redwood CLI Reference for the upgrade command',
52-
'https://redwoodjs.com/docs/cli-commands#upgrade'
52+
'https://redwoodjs.com/docs/cli-commands#upgrade',
5353
)}.\nAnd the ${terminalLink(
5454
'GitHub releases page',
55-
'https://github.com/redwoodjs/redwood/releases'
56-
)} for more information on the current release.`
55+
'https://github.com/redwoodjs/redwood/releases',
56+
)} for more information on the current release.`,
5757
)
5858
}
5959

@@ -76,8 +76,8 @@ export const validateTag = (tag) => {
7676
// Stop execution
7777
throw new Error(
7878
c.error(
79-
"Invalid tag supplied. Supported values: 'rc', 'canary', 'latest', 'next', 'experimental', or a valid semver version\n"
80-
)
79+
"Invalid tag supplied. Supported values: 'rc', 'canary', 'latest', 'next', 'experimental', or a valid semver version\n",
80+
),
8181
)
8282
}
8383

@@ -132,19 +132,19 @@ export const handler = async ({ dryRun, tag, verbose, dedupe }) => {
132132
const version = ctx.versionToUpgradeTo
133133
const messageSections = [
134134
`One more thing...\n\n ${c.warning(
135-
`🎉 Your project has been upgraded to RedwoodJS ${version}!`
135+
`🎉 Your project has been upgraded to RedwoodJS ${version}!`,
136136
)} \n\n`,
137137
]
138138
// Show links when switching to 'latest' or 'rc', undefined is essentially an alias of 'latest'
139139
if ([undefined, 'latest', 'rc'].includes(tag)) {
140140
messageSections.push(
141141
` Please review the release notes for any manual steps: \n ❖ ${terminalLink(
142142
`Redwood community discussion`,
143-
`https://community.redwoodjs.com/search?q=${version}%23announcements`
143+
`https://community.redwoodjs.com/search?q=${version}%23announcements`,
144144
)}\n ❖ ${terminalLink(
145145
`GitHub Release notes`,
146-
`https://github.com/redwoodjs/redwood/releases` // intentionally not linking to specific version
147-
)} \n\n`
146+
`https://github.com/redwoodjs/redwood/releases`, // intentionally not linking to specific version
147+
)} \n\n`,
148148
)
149149
}
150150
// @MARK
@@ -157,14 +157,14 @@ export const handler = async ({ dryRun, tag, verbose, dedupe }) => {
157157
isValidRedwoodJSTag(tag)
158158
) {
159159
additionalMessages.push(
160-
` ❖ You may want to update your redwood.toml config so that \`notifications.versionUpdates\` includes "${tag}"\n`
160+
` ❖ You may want to update your redwood.toml config so that \`notifications.versionUpdates\` includes "${tag}"\n`,
161161
)
162162
}
163163
// Append additional messages with a header
164164
if (additionalMessages.length > 0) {
165165
messageSections.push(
166166
` 📢 ${c.warning(`We'd also like to remind you that:`)} \n`,
167-
...additionalMessages
167+
...additionalMessages,
168168
)
169169
}
170170
}
@@ -175,7 +175,7 @@ export const handler = async ({ dryRun, tag, verbose, dedupe }) => {
175175
{
176176
renderer: verbose && 'verbose',
177177
rendererOptions: { collapseSubtasks: false },
178-
}
178+
},
179179
)
180180

181181
await tasks.run()
@@ -192,11 +192,11 @@ async function yarnInstall({ verbose }) {
192192
stdio: verbose ? 'inherit' : 'pipe',
193193

194194
cwd: getPaths().base,
195-
}
195+
},
196196
)
197197
} catch (e) {
198198
throw new Error(
199-
'Could not finish installation. Please run `yarn install` and then `yarn dedupe`, before continuing'
199+
'Could not finish installation. Please run `yarn install` and then `yarn dedupe`, before continuing',
200200
)
201201
}
202202
}
@@ -205,7 +205,7 @@ async function setLatestVersionToContext(ctx, tag) {
205205
try {
206206
const foundVersion = await latestVersion(
207207
'@redwoodjs/core',
208-
tag ? { version: tag } : {}
208+
tag ? { version: tag } : {},
209209
)
210210

211211
ctx.versionToUpgradeTo = foundVersion
@@ -220,12 +220,12 @@ async function setLatestVersionToContext(ctx, tag) {
220220
*/
221221
function updatePackageJsonVersion(pkgPath, version, { dryRun, verbose }) {
222222
const pkg = JSON.parse(
223-
fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf-8')
223+
fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf-8'),
224224
)
225225

226226
if (pkg.dependencies) {
227227
for (const depName of Object.keys(pkg.dependencies).filter(
228-
(x) => x.startsWith('@redwoodjs/') && x !== '@redwoodjs/studio'
228+
(x) => x.startsWith('@redwoodjs/') && x !== '@redwoodjs/studio',
229229
)) {
230230
if (verbose || dryRun) {
231231
console.log(` - ${depName}: ${pkg.dependencies[depName]} => ${version}`)
@@ -235,11 +235,11 @@ function updatePackageJsonVersion(pkgPath, version, { dryRun, verbose }) {
235235
}
236236
if (pkg.devDependencies) {
237237
for (const depName of Object.keys(pkg.devDependencies).filter(
238-
(x) => x.startsWith('@redwoodjs/') && x !== '@redwoodjs/studio'
238+
(x) => x.startsWith('@redwoodjs/') && x !== '@redwoodjs/studio',
239239
)) {
240240
if (verbose || dryRun) {
241241
console.log(
242-
` - ${depName}: ${pkg.devDependencies[depName]} => ${version}`
242+
` - ${depName}: ${pkg.devDependencies[depName]} => ${version}`,
243243
)
244244
}
245245
pkg.devDependencies[depName] = `${version}`
@@ -249,7 +249,7 @@ function updatePackageJsonVersion(pkgPath, version, { dryRun, verbose }) {
249249
if (!dryRun) {
250250
fs.writeFileSync(
251251
path.join(pkgPath, 'package.json'),
252-
JSON.stringify(pkg, undefined, 2)
252+
JSON.stringify(pkg, undefined, 2),
253253
)
254254
}
255255
}
@@ -274,7 +274,7 @@ function updateRedwoodDepsForAllSides(ctx, options) {
274274
updatePackageJsonVersion(basePath, ctx.versionToUpgradeTo, options),
275275
skip: () => !fs.existsSync(pkgJsonPath),
276276
}
277-
})
277+
}),
278278
)
279279
}
280280

@@ -318,13 +318,13 @@ async function updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }) {
318318
if (!depName.startsWith('@redwoodjs/')) {
319319
if (verbose || dryRun) {
320320
console.log(
321-
` - ${depName}: ${localPackageJson.dependencies[depName]} => ${depVersion}`
321+
` - ${depName}: ${localPackageJson.dependencies[depName]} => ${depVersion}`,
322322
)
323323
}
324324

325325
localPackageJson.dependencies[depName] = depVersion
326326
}
327-
}
327+
},
328328
)
329329

330330
Object.entries(templatePackageJson.devDependencies || {}).forEach(
@@ -333,25 +333,25 @@ async function updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }) {
333333
if (!depName.startsWith('@redwoodjs/')) {
334334
if (verbose || dryRun) {
335335
console.log(
336-
` - ${depName}: ${localPackageJson.devDependencies[depName]} => ${depVersion}`
336+
` - ${depName}: ${localPackageJson.devDependencies[depName]} => ${depVersion}`,
337337
)
338338
}
339339

340340
localPackageJson.devDependencies[depName] = depVersion
341341
}
342-
}
342+
},
343343
)
344344

345345
if (!dryRun) {
346346
fs.writeFileSync(
347347
pkgJsonPath,
348-
JSON.stringify(localPackageJson, null, 2)
348+
JSON.stringify(localPackageJson, null, 2),
349349
)
350350
}
351351
},
352352
skip: () => !fs.existsSync(pkgJsonPath),
353353
}
354-
})
354+
}),
355355
)
356356
}
357357

@@ -366,7 +366,7 @@ async function refreshPrismaClient(task, { verbose }) {
366366
} catch (e) {
367367
task.skip('Refreshing the Prisma client caused an Error.')
368368
console.log(
369-
'You may need to update your prisma client manually: $ yarn rw prisma generate'
369+
'You may need to update your prisma client manually: $ yarn rw prisma generate',
370370
)
371371
console.log(c.error(e.message))
372372
}
@@ -390,11 +390,6 @@ export const getCmdMajorVersion = async (command) => {
390390
const dedupeDeps = async (task, { verbose }) => {
391391
try {
392392
const yarnVersion = await getCmdMajorVersion('yarn')
393-
const npxVersion = await getCmdMajorVersion('npx')
394-
let npxArgs = []
395-
if (npxVersion > 6) {
396-
npxArgs = ['--yes']
397-
}
398393

399394
const baseExecaArgsForDedupe = {
400395
shell: true,
@@ -404,16 +399,18 @@ const dedupeDeps = async (task, { verbose }) => {
404399
if (yarnVersion > 1) {
405400
await execa('yarn', ['dedupe'], baseExecaArgsForDedupe)
406401
} else {
407-
await execa(
408-
'npx',
409-
[...npxArgs, 'yarn-deduplicate'],
410-
baseExecaArgsForDedupe
402+
// Redwood projects should not be using yarn 1.x as we specify a version of yarn in the package.json
403+
// with "packageManager": "[email protected]" or similar.
404+
// Although we could (and previous did) automatically run `npx yarn-deduplicate` here, that would require
405+
// the user to have `npx` installed, which is not guaranteed and we do not wish to enforce that.
406+
task.skip(
407+
"Yarn 1.x doesn't support dedupe directly. Please upgrade yarn or use npx with `npx yarn-deduplicate` manually.",
411408
)
412409
}
413410
} catch (e) {
414411
console.log(c.error(e.message))
415412
throw new Error(
416-
'Could not finish de-duplication. For yarn 1.x, please run `npx yarn-deduplicate`, or for yarn 3 run `yarn dedupe` before continuing'
413+
'Could not finish de-duplication. For yarn 1.x, please run `npx yarn-deduplicate`, or for yarn 3 run `yarn dedupe` before continuing',
417414
)
418415
}
419416
await yarnInstall({ verbose })

0 commit comments

Comments
 (0)