From e102c29af8f48584c7817271554e0b8d9be6214f Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:49:35 +0200 Subject: [PATCH 01/17] feat: execa --- packages/create-docusaurus/package.json | 1 + packages/create-docusaurus/src/index.ts | 44 ++++++++------- .../package.json | 3 +- packages/docusaurus-utils/package.json | 1 + .../src/__tests__/lastUpdateUtils.test.ts | 2 + packages/docusaurus-utils/src/gitUtils.ts | 56 ++++++++++--------- packages/docusaurus/package.json | 1 + packages/docusaurus/src/commands/deploy.ts | 44 +++++++++------ yarn.lock | 33 ++--------- 9 files changed, 92 insertions(+), 93 deletions(-) diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index d02a87e1990b..a59c59ea35d9 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -25,6 +25,7 @@ "@docusaurus/logger": "3.4.0", "@docusaurus/utils": "3.4.0", "commander": "^5.1.0", + "execa": "5.1.1", "fs-extra": "^11.1.1", "lodash": "^4.17.21", "prompts": "^2.4.2", diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 769fb4885213..26315d65cfdd 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -10,7 +10,7 @@ import {fileURLToPath} from 'url'; import path from 'path'; import _ from 'lodash'; import logger from '@docusaurus/logger'; -import shell from 'shelljs'; +import execa from 'execa'; import prompts, {type Choice} from 'prompts'; import supportsColor from 'supports-color'; import {escapeShellArg, askPreferredLanguage} from '@docusaurus/utils'; @@ -70,9 +70,9 @@ function findPackageManagerFromUserAgent(): PackageManager | undefined { } async function askForPackageManagerChoice(): Promise { - const hasYarn = shell.exec('yarn --version', {silent: true}).code === 0; - const hasPnpm = shell.exec('pnpm --version', {silent: true}).code === 0; - const hasBun = shell.exec('bun --version', {silent: true}).code === 0; + const hasYarn = (await execa.command('yarn --version')).exitCode === 0; + const hasPnpm = (await execa.command('pnpm --version')).exitCode === 0; + const hasBun = (await execa.command('bun --version')).exitCode === 0; if (!hasYarn && !hasPnpm && !hasBun) { return 'npm'; @@ -533,7 +533,7 @@ export default async function init( const gitCloneCommand = `${gitCommand} ${escapeShellArg( source.url, )} ${escapeShellArg(dest)}`; - if (shell.exec(gitCloneCommand).code !== 0) { + if (execa.command(gitCloneCommand).exitCode !== 0) { logger.error`Cloning Git template failed!`; process.exit(1); } @@ -583,24 +583,28 @@ export default async function init( const cdpath = path.relative('.', dest); const pkgManager = await getPackageManager(dest, cliOptions); if (!cliOptions.skipInstall) { - shell.cd(dest); + await execa.command(`cd ${dest}`); logger.info`Installing dependencies with name=${pkgManager}...`; + // ... + if ( - shell.exec( - pkgManager === 'yarn' - ? 'yarn' - : pkgManager === 'bun' - ? 'bun install' - : `${pkgManager} install --color always`, - { - env: { - ...process.env, - // Force coloring the output, since the command is invoked by - // shelljs, which is not an interactive shell - ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), + ( + await execa.command( + pkgManager === 'yarn' + ? 'yarn' + : pkgManager === 'bun' + ? 'bun install' + : `${pkgManager} install --color always`, + { + env: { + ...process.env, + // Force coloring the output, since the command is invoked by + // shelljs, which is not an interactive shell + ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), + }, }, - }, - ).code !== 0 + ) + ).exitCode !== 0 ) { logger.error('Dependency installation failed.'); logger.info`The site directory has already been created, and you can retry by typing: diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 777777e932b8..cb3ec2b6210f 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -57,8 +57,7 @@ "@types/js-yaml": "^4.0.5", "@types/picomatch": "^2.3.0", "commander": "^5.1.0", - "picomatch": "^2.3.1", - "shelljs": "^0.8.5" + "picomatch": "^2.3.1" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 5b34b45733e9..f9ef2f8e836e 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -22,6 +22,7 @@ "@docusaurus/utils-common": "3.4.0", "@svgr/webpack": "^8.1.0", "escape-string-regexp": "^4.0.0", + "execa": "5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", diff --git a/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts b/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts index 14e907e99462..925f55dcd4f8 100644 --- a/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts @@ -10,6 +10,7 @@ import fs from 'fs-extra'; import path from 'path'; import {createTempRepo} from '@testing-utils/git'; import shell from 'shelljs'; +// import execa from 'execa'; import { getGitLastUpdate, LAST_UPDATE_FALLBACK, @@ -69,6 +70,7 @@ describe('getGitLastUpdate', () => { }); it('git does not exist', async () => { + // TODO how to mock execa command ? const mock = jest.spyOn(shell, 'which').mockImplementationOnce(() => null); const consoleMock = jest .spyOn(console, 'warn') diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts index 39a3ad754a0c..8f940544fbad 100644 --- a/packages/docusaurus-utils/src/gitUtils.ts +++ b/packages/docusaurus-utils/src/gitUtils.ts @@ -8,9 +8,16 @@ import path from 'path'; import fs from 'fs-extra'; import _ from 'lodash'; -import shell from 'shelljs'; // TODO replace with async-first version - -const realHasGitFn = () => !!shell.which('git'); +import execa from 'execa'; + +const realHasGitFn = async () => { + try { + await execa('git', ['--version']); + return true; + } catch (error) { + return false; + } +}; // The hasGit call is synchronous IO so we memoize it // The user won't install Git in the middle of a build anyway... @@ -123,30 +130,29 @@ export async function getFileCommitDate( file, )}"`; - const result = await new Promise<{ - code: number; - stdout: string; - stderr: string; - }>((resolve) => { - shell.exec( - command, - { - // Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048 - cwd: path.dirname(file), - silent: true, - }, - (code, stdout, stderr) => { - resolve({code, stdout, stderr}); - }, - ); - }); - - if (result.code !== 0) { - throw new Error( - `Failed to retrieve the git history for file "${file}" with exit code ${result.code}: ${result.stderr}`, - ); + async function executeCommand(cmd: string, filepath: string) { + try { + const {exitCode, stdout, stderr} = await execa(cmd, { + cwd: path.dirname(filepath), + shell: true, + }); + + if (exitCode !== 0) { + throw new Error( + `Failed to retrieve the git history for file "${file}" with exit code ${exitCode}: ${stderr}`, + ); + } + + return {code: exitCode, stdout, stderr}; + } catch (error) { + console.error('Error executing command:', error); + throw error; + } } + // Usage + const result = await executeCommand(command, file); + // We only parse the output line starting with our "RESULT:" prefix // See why https://github.com/facebook/docusaurus/pull/10022 const regex = includeAuthor diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index c1090dbe2afd..54463e193420 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -69,6 +69,7 @@ "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", + "execa": "5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "html-minifier-terser": "^7.2.0", diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 2e23a8e3efb1..7b17d0822855 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -9,7 +9,7 @@ import fs from 'fs-extra'; import path from 'path'; import os from 'os'; import logger from '@docusaurus/logger'; -import shell from 'shelljs'; +import execa from 'execa'; import {hasSSHProtocol, buildSshUrl, buildHttpsUrl} from '@docusaurus/utils'; import {loadContext, type LoadContextParams} from '../server/site'; import {build} from './build'; @@ -32,8 +32,10 @@ function obfuscateGitPass(str: string) { // for example: https://github.com/facebook/docusaurus/issues/3875 function shellExecLog(cmd: string) { try { - const result = shell.exec(cmd); - logger.info`code=${obfuscateGitPass(cmd)} subdue=${`code: ${result.code}`}`; + const result = execa.command(cmd); + logger.info`code=${obfuscateGitPass( + cmd, + )} subdue=${`code: ${result.exitCode}`}`; return result; } catch (err) { logger.error`code=${obfuscateGitPass(cmd)}`; @@ -61,19 +63,21 @@ This behavior can have SEO impacts and create relative link issues. } logger.info('Deploy command invoked...'); - if (!shell.which('git')) { + try { + await execa.command('git --version'); + } catch (err) { throw new Error('Git not installed or on the PATH!'); } // Source repo is the repo from where the command is invoked - const sourceRepoUrl = shell - .exec('git remote get-url origin', {silent: true}) - .stdout.trim(); + // TODO silent + const {stdout} = await execa.command('git remote get-url origin'); + const sourceRepoUrl = stdout.trim(); // The source branch; defaults to the currently checked out branch const sourceBranch = process.env.CURRENT_BRANCH ?? - shell.exec('git rev-parse --abbrev-ref HEAD', {silent: true}).stdout.trim(); + execa.command('git rev-parse --abbrev-ref HEAD')?.stdout?.toString().trim(); const gitUser = process.env.GIT_USER; @@ -118,8 +122,8 @@ This behavior can have SEO impacts and create relative link issues. const isPullRequest = process.env.CI_PULL_REQUEST ?? process.env.CIRCLE_PULL_REQUEST; if (isPullRequest) { - shell.echo('Skipping deploy on a pull request.'); - shell.exit(0); + await execa.command('echo "Skipping deploy on a pull request."'); + process.exit(0); } // github.io indicates organization repos that deploy via default branch. All @@ -183,7 +187,9 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); // Save the commit hash that triggers publish-gh-pages before checking // out to deployment branch. - const currentCommit = shellExecLog('git rev-parse HEAD').stdout.trim(); + const currentCommit = shellExecLog('git rev-parse HEAD') + ?.stdout?.toString() + .trim(); const runDeploy = async (outputDirectory: string) => { const targetDirectory = cliOptions.targetDir ?? '.'; @@ -191,7 +197,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); const toPath = await fs.mkdtemp( path.join(os.tmpdir(), `${projectName}-${deploymentBranch}`), ); - shell.cd(toPath); + await execa.command(`cd ${toPath}`); // Clones the repo into the temp folder and checks out the target branch. // If the branch doesn't exist, it creates a new one based on the @@ -199,7 +205,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); if ( shellExecLog( `git clone --depth 1 --branch ${deploymentBranch} ${deploymentRepoURL} "${toPath}"`, - ).code !== 0 + ).exitCode !== 0 ) { shellExecLog(`git clone --depth 1 ${deploymentRepoURL} "${toPath}"`); shellExecLog(`git checkout -b ${deploymentBranch}`); @@ -232,12 +238,12 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); `Deploy website - based on ${currentCommit}`; const commitResults = shellExecLog(`git commit -m "${commitMessage}"`); if ( - shellExecLog(`git push --force origin ${deploymentBranch}`).code !== 0 + shellExecLog(`git push --force origin ${deploymentBranch}`).exitCode !== 0 ) { throw new Error( 'Running "git push" command failed. Does the GitHub user account you are using have push access to the repository?', ); - } else if (commitResults.code === 0) { + } else if (commitResults.exitCode === 0) { // The commit might return a non-zero value when site is up to date. let websiteURL = ''; if (githubHost === 'github.com') { @@ -248,8 +254,12 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); // GitHub enterprise hosting. websiteURL = `https://${githubHost}/pages/${organizationName}/${projectName}/`; } - shell.echo(`Website is live at "${websiteURL}".`); - shell.exit(0); + try { + await execa.command(`echo "Website is live at ${websiteURL}."`); + process.exit(0); + } catch (err) { + throw new Error(`Failed to execute command: ${err}`); + } } }; diff --git a/yarn.lock b/yarn.lock index 461971db46db..f25897322ae3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7410,7 +7410,7 @@ execa@5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^5.0.0: +execa@5.1.1, execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -15245,16 +15245,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15353,14 +15344,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17025,7 +17009,7 @@ workbox-window@7.0.0, workbox-window@^7.0.0: "@types/trusted-types" "^2.0.2" workbox-core "7.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17043,15 +17027,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 8178e69c45da415a5403628bd3af85f8f9eeb407 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:10:02 +0100 Subject: [PATCH 02/17] deps --- packages/create-docusaurus/package.json | 1 - packages/docusaurus-utils/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index f8cada1cdfb6..5ebe1e4b188f 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -30,7 +30,6 @@ "lodash": "^4.17.21", "prompts": "^2.4.2", "semver": "^7.5.4", - "shelljs": "^0.8.5", "supports-color": "^9.4.0", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 7d3f289add2d..7dde60ae3a3d 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -34,7 +34,6 @@ "micromatch": "^4.0.5", "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", "tslib": "^2.6.0", "url-loader": "^4.1.1", "utility-types": "^3.10.0", From e3a314c3b28e659539c61315135cd67131957582 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:10:28 +0100 Subject: [PATCH 03/17] fix getGitLastUpdate test mock --- .../src/__tests__/lastUpdateUtils.test.ts | 12 +++++++----- packages/docusaurus-utils/src/gitUtils.ts | 5 ++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts b/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts index 925f55dcd4f8..48dbe85220a8 100644 --- a/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/lastUpdateUtils.test.ts @@ -9,13 +9,13 @@ import {jest} from '@jest/globals'; import fs from 'fs-extra'; import path from 'path'; import {createTempRepo} from '@testing-utils/git'; -import shell from 'shelljs'; -// import execa from 'execa'; +import execa from 'execa'; + import { getGitLastUpdate, LAST_UPDATE_FALLBACK, readLastUpdateData, -} from '@docusaurus/utils'; +} from '../lastUpdateUtils'; describe('getGitLastUpdate', () => { const {repoDir} = createTempRepo(); @@ -70,8 +70,10 @@ describe('getGitLastUpdate', () => { }); it('git does not exist', async () => { - // TODO how to mock execa command ? - const mock = jest.spyOn(shell, 'which').mockImplementationOnce(() => null); + const mock = jest.spyOn(execa, 'sync').mockImplementationOnce(() => { + throw new Error('Git does not exist'); + }); + const consoleMock = jest .spyOn(console, 'warn') .mockImplementation(() => {}); diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts index 8f940544fbad..8d08c035cdbe 100644 --- a/packages/docusaurus-utils/src/gitUtils.ts +++ b/packages/docusaurus-utils/src/gitUtils.ts @@ -10,10 +10,9 @@ import fs from 'fs-extra'; import _ from 'lodash'; import execa from 'execa'; -const realHasGitFn = async () => { +const realHasGitFn = () => { try { - await execa('git', ['--version']); - return true; + return execa.sync('git', ['--version']).exitCode === 0; } catch (error) { return false; } From 043a3735f24f480dd311a19ca8612d621307cf73 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:24:13 +0100 Subject: [PATCH 04/17] remove useless try/catch --- packages/docusaurus-utils/src/gitUtils.ts | 25 ++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts index 8d08c035cdbe..83f3760aff07 100644 --- a/packages/docusaurus-utils/src/gitUtils.ts +++ b/packages/docusaurus-utils/src/gitUtils.ts @@ -130,23 +130,16 @@ export async function getFileCommitDate( )}"`; async function executeCommand(cmd: string, filepath: string) { - try { - const {exitCode, stdout, stderr} = await execa(cmd, { - cwd: path.dirname(filepath), - shell: true, - }); - - if (exitCode !== 0) { - throw new Error( - `Failed to retrieve the git history for file "${file}" with exit code ${exitCode}: ${stderr}`, - ); - } - - return {code: exitCode, stdout, stderr}; - } catch (error) { - console.error('Error executing command:', error); - throw error; + const {exitCode, stdout, stderr} = await execa(cmd, { + cwd: path.dirname(filepath), + shell: true, + }); + if (exitCode !== 0) { + throw new Error( + `Failed to retrieve the git history for file "${file}" with exit code ${exitCode}: ${stderr}`, + ); } + return {code: exitCode, stdout, stderr}; } // Usage From 786b5389636571879b0a30feef381483b295a668 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:29:46 +0100 Subject: [PATCH 05/17] remove shelljs deps --- packages/docusaurus/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index a476e4c1fcaa..41c9124f8a56 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -69,7 +69,6 @@ "react-router-dom": "^5.3.4", "semver": "^7.5.4", "serve-handler": "^6.1.6", - "shelljs": "^0.8.5", "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", From 3af9292f321e6318dcdc2906005775dd7f6edf5e Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:30:43 +0100 Subject: [PATCH 06/17] fix create-docusaurus --- packages/create-docusaurus/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 26315d65cfdd..07fee261cb04 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -583,7 +583,7 @@ export default async function init( const cdpath = path.relative('.', dest); const pkgManager = await getPackageManager(dest, cliOptions); if (!cliOptions.skipInstall) { - await execa.command(`cd ${dest}`); + await execa('cd', [dest]); logger.info`Installing dependencies with name=${pkgManager}...`; // ... From 13b950853180a110c7bbb3a071c11c5c69508044 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:31:21 +0100 Subject: [PATCH 07/17] fix beforeCli --- packages/docusaurus/bin/beforeCli.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus/bin/beforeCli.mjs b/packages/docusaurus/bin/beforeCli.mjs index ca81a6ab45ef..7283b545eff5 100644 --- a/packages/docusaurus/bin/beforeCli.mjs +++ b/packages/docusaurus/bin/beforeCli.mjs @@ -10,7 +10,7 @@ import fs from 'fs-extra'; import path from 'path'; import {createRequire} from 'module'; -import shell from 'shelljs'; +import execa from 'execa'; import {logger} from '@docusaurus/logger'; import semver from 'semver'; import updateNotifier from 'update-notifier'; @@ -111,8 +111,8 @@ export default async function beforeCli() { return undefined; } - const yarnVersionResult = shell.exec('yarn --version', {silent: true}); - if (yarnVersionResult?.code === 0) { + const yarnVersionResult = await execa('yarn', ['--version']); + if (yarnVersionResult.exitCode === 0) { const majorVersion = parseInt( yarnVersionResult.stdout?.trim().split('.')[0] ?? '', 10, From a43279b964eff454de35aa950ed35e6520ea0043 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 27 Feb 2025 18:37:56 +0100 Subject: [PATCH 08/17] regen lockfile update --- yarn.lock | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 63d060344720..e8ca49a55e9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8409,7 +8409,7 @@ execa@5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@5.1.1, execa@^5.0.0: +execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -16817,7 +16817,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -16938,7 +16947,14 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18689,7 +18705,7 @@ workbox-window@7.1.0, workbox-window@^7.0.0: "@types/trusted-types" "^2.0.2" workbox-core "7.1.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -18707,6 +18723,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 91fd175cbb949d697a1f21fd63ce7a3c46d6d9fa Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 09:03:44 +0100 Subject: [PATCH 09/17] regen lockfile update --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index e8ca49a55e9a..32055d13f765 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8409,7 +8409,7 @@ execa@5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^5.0.0: +execa@5.1.1, execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== From bae2262825f8aa6fd34dea75d533d378475cdac8 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 09:05:28 +0100 Subject: [PATCH 10/17] fix create-docusaurus logger ESM import problem --- packages/create-docusaurus/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 07fee261cb04..0d0ffa38e09e 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -9,7 +9,7 @@ import fs from 'fs-extra'; import {fileURLToPath} from 'url'; import path from 'path'; import _ from 'lodash'; -import logger from '@docusaurus/logger'; +import {logger} from '@docusaurus/logger'; import execa from 'execa'; import prompts, {type Choice} from 'prompts'; import supportsColor from 'supports-color'; From 46eaae95974b8ea0ff8a2c4c12a2a3f93d78b3b3 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 11:45:05 +0100 Subject: [PATCH 11/17] simplify getFileCommitDate --- packages/docusaurus-utils/src/gitUtils.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts index 83f3760aff07..104bf736340a 100644 --- a/packages/docusaurus-utils/src/gitUtils.ts +++ b/packages/docusaurus-utils/src/gitUtils.ts @@ -129,22 +129,16 @@ export async function getFileCommitDate( file, )}"`; - async function executeCommand(cmd: string, filepath: string) { - const {exitCode, stdout, stderr} = await execa(cmd, { - cwd: path.dirname(filepath), - shell: true, - }); - if (exitCode !== 0) { - throw new Error( - `Failed to retrieve the git history for file "${file}" with exit code ${exitCode}: ${stderr}`, - ); - } - return {code: exitCode, stdout, stderr}; + const result = await execa(command, { + cwd: path.dirname(file), + shell: true, + }); + if (result.exitCode !== 0) { + throw new Error( + `Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}`, + ); } - // Usage - const result = await executeCommand(command, file); - // We only parse the output line starting with our "RESULT:" prefix // See why https://github.com/facebook/docusaurus/pull/10022 const regex = includeAuthor From 8f8ce762466fad0c95e60741b0f80d402f701f27 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 11:57:05 +0100 Subject: [PATCH 12/17] simplify --- packages/docusaurus/bin/beforeCli.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus/bin/beforeCli.mjs b/packages/docusaurus/bin/beforeCli.mjs index 7283b545eff5..4662c38b4377 100644 --- a/packages/docusaurus/bin/beforeCli.mjs +++ b/packages/docusaurus/bin/beforeCli.mjs @@ -111,7 +111,7 @@ export default async function beforeCli() { return undefined; } - const yarnVersionResult = await execa('yarn', ['--version']); + const yarnVersionResult = await execa.command('yarn --version'); if (yarnVersionResult.exitCode === 0) { const majorVersion = parseInt( yarnVersionResult.stdout?.trim().split('.')[0] ?? '', From 4d5751376a609c2ad817026d1c173a4afab19b21 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 12:25:37 +0100 Subject: [PATCH 13/17] add deploy debug mode --- packages/docusaurus/src/commands/deploy.ts | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 16001f444379..ff79925fdc86 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -26,21 +26,35 @@ function obfuscateGitPass(str: string) { return gitPass ? str.replace(gitPass, 'GIT_PASS') : str; } +const debugMode = !!process.env.DOCUSAURUS_DEPLOY_DEBUG; + // Log executed commands so that user can figure out mistakes on his own // for example: https://github.com/facebook/docusaurus/issues/3875 function shellExecLog(cmd: string) { try { - const result = execa.command(cmd); + const result = execa.commandSync(cmd); logger.info`code=${obfuscateGitPass( cmd, )} subdue=${`code: ${result.exitCode}`}`; + if (debugMode) { + console.log(result); + } return result; } catch (err) { - logger.error`code=${obfuscateGitPass(cmd)}`; - throw err; + throw new Error( + logger.interpolate`Error while executing command code=${obfuscateGitPass( + cmd, + )} +In CWD code=${process.cwd()}`, + {cause: err}, + ); } } +function hasGit() { + return shellExecLog('git --version').exitCode === 0; +} + export async function deploy( siteDirParam: string = '.', cliOptions: Partial = {}, @@ -61,10 +75,8 @@ This behavior can have SEO impacts and create relative link issues. } logger.info('Deploy command invoked...'); - try { - await execa.command('git --version'); - } catch (err) { - throw new Error('Git not installed or on the PATH!'); + if (!hasGit()) { + throw new Error('Git not installed or not added to PATH!'); } // Source repo is the repo from where the command is invoked From 056373b467bb32241b0627bcce03372be7ed170a Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 12:43:46 +0100 Subject: [PATCH 14/17] improve deploy script --- packages/docusaurus/src/commands/deploy.ts | 65 +++++++++++++--------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index ff79925fdc86..1b6138f1f5c0 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -30,15 +30,24 @@ const debugMode = !!process.env.DOCUSAURUS_DEPLOY_DEBUG; // Log executed commands so that user can figure out mistakes on his own // for example: https://github.com/facebook/docusaurus/issues/3875 -function shellExecLog(cmd: string) { +function exec(cmd: string, options?: {log?: boolean; failfast?: boolean}) { + const log = options?.log ?? true; + const failfast = options?.failfast ?? false; try { const result = execa.commandSync(cmd); - logger.info`code=${obfuscateGitPass( - cmd, - )} subdue=${`code: ${result.exitCode}`}`; + if (log || debugMode) { + logger.info`code=${obfuscateGitPass( + cmd, + )} subdue=${`code: ${result.exitCode}`}`; + } if (debugMode) { console.log(result); } + if (failfast && result.exitCode !== 0) { + throw new Error( + `Command returned unexpected exitCode ${result.exitCode}`, + ); + } return result; } catch (err) { throw new Error( @@ -52,7 +61,7 @@ In CWD code=${process.cwd()}`, } function hasGit() { - return shellExecLog('git --version').exitCode === 0; + return exec('git --version').exitCode === 0; } export async function deploy( @@ -80,14 +89,21 @@ This behavior can have SEO impacts and create relative link issues. } // Source repo is the repo from where the command is invoked - // TODO silent - const {stdout} = await execa.command('git remote get-url origin'); + const {stdout} = exec('git remote get-url origin', { + log: false, + failfast: true, + }); const sourceRepoUrl = stdout.trim(); // The source branch; defaults to the currently checked out branch const sourceBranch = process.env.CURRENT_BRANCH ?? - execa.command('git rev-parse --abbrev-ref HEAD')?.stdout?.toString().trim(); + exec('git rev-parse --abbrev-ref HEAD', { + log: false, + failfast: true, + }) + ?.stdout?.toString() + .trim(); const gitUser = process.env.GIT_USER; @@ -132,7 +148,10 @@ This behavior can have SEO impacts and create relative link issues. const isPullRequest = process.env.CI_PULL_REQUEST ?? process.env.CIRCLE_PULL_REQUEST; if (isPullRequest) { - await execa.command('echo "Skipping deploy on a pull request."'); + exec('echo "Skipping deploy on a pull request."', { + log: false, + failfast: true, + }); process.exit(0); } @@ -197,9 +216,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); // Save the commit hash that triggers publish-gh-pages before checking // out to deployment branch. - const currentCommit = shellExecLog('git rev-parse HEAD') - ?.stdout?.toString() - .trim(); + const currentCommit = exec('git rev-parse HEAD')?.stdout?.toString().trim(); const runDeploy = async (outputDirectory: string) => { const targetDirectory = cliOptions.targetDir ?? '.'; @@ -207,22 +224,22 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); const toPath = await fs.mkdtemp( path.join(os.tmpdir(), `${projectName}-${deploymentBranch}`), ); - await execa.command(`cd ${toPath}`); + exec(`cd ${toPath}`, {failfast: true}); // Clones the repo into the temp folder and checks out the target branch. // If the branch doesn't exist, it creates a new one based on the // repository default branch. if ( - shellExecLog( + exec( `git clone --depth 1 --branch ${deploymentBranch} ${deploymentRepoURL} "${toPath}"`, ).exitCode !== 0 ) { - shellExecLog(`git clone --depth 1 ${deploymentRepoURL} "${toPath}"`); - shellExecLog(`git checkout -b ${deploymentBranch}`); + exec(`git clone --depth 1 ${deploymentRepoURL} "${toPath}"`); + exec(`git checkout -b ${deploymentBranch}`); } // Clear out any existing contents in the target directory - shellExecLog(`git rm -rf ${targetDirectory}`); + exec(`git rm -rf ${targetDirectory}`, {log: false, failfast: true}); const targetPath = path.join(toPath, targetDirectory); try { @@ -231,25 +248,23 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); logger.error`Copying build assets from path=${fromPath} to path=${targetPath} failed.`; throw err; } - shellExecLog('git add --all'); + exec('git add --all'); const gitUserName = process.env.GIT_USER_NAME; if (gitUserName) { - shellExecLog(`git config user.name "${gitUserName}"`); + exec(`git config user.name "${gitUserName}"`, {failfast: true}); } const gitUserEmail = process.env.GIT_USER_EMAIL; if (gitUserEmail) { - shellExecLog(`git config user.email "${gitUserEmail}"`); + exec(`git config user.email "${gitUserEmail}"`, {failfast: true}); } const commitMessage = process.env.CUSTOM_COMMIT_MESSAGE ?? `Deploy website - based on ${currentCommit}`; - const commitResults = shellExecLog(`git commit -m "${commitMessage}"`); - if ( - shellExecLog(`git push --force origin ${deploymentBranch}`).exitCode !== 0 - ) { + const commitResults = exec(`git commit -m "${commitMessage}"`); + if (exec(`git push --force origin ${deploymentBranch}`).exitCode !== 0) { throw new Error( 'Running "git push" command failed. Does the GitHub user account you are using have push access to the repository?', ); @@ -265,7 +280,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); websiteURL = `https://${githubHost}/pages/${organizationName}/${projectName}/`; } try { - await execa.command(`echo "Website is live at ${websiteURL}."`); + exec(`echo "Website is live at ${websiteURL}."`, {failfast: true}); process.exit(0); } catch (err) { throw new Error(`Failed to execute command: ${err}`); From 0522307833fdd33b6a37b7c1185cdc4f83cefbbb Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 12:55:46 +0100 Subject: [PATCH 15/17] improve deploy script --- packages/docusaurus/src/commands/deploy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 1b6138f1f5c0..6e7fe82d5838 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -224,7 +224,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); const toPath = await fs.mkdtemp( path.join(os.tmpdir(), `${projectName}-${deploymentBranch}`), ); - exec(`cd ${toPath}`, {failfast: true}); + process.chdir(toPath); // Clones the repo into the temp folder and checks out the target branch. // If the branch doesn't exist, it creates a new one based on the @@ -248,7 +248,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); logger.error`Copying build assets from path=${fromPath} to path=${targetPath} failed.`; throw err; } - exec('git add --all'); + exec('git add --all', {failfast: true}); const gitUserName = process.env.GIT_USER_NAME; if (gitUserName) { From 3a9f2b6a893cd32d24bedd2dbf2955b2fb8aeca0 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 13:18:04 +0100 Subject: [PATCH 16/17] fix deploy script --- packages/docusaurus/src/commands/deploy.ts | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 6e7fe82d5838..2891ca9bd423 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -34,6 +34,9 @@ function exec(cmd: string, options?: {log?: boolean; failfast?: boolean}) { const log = options?.log ?? true; const failfast = options?.failfast ?? false; try { + // TODO migrate to execa(file,[...args]) instead + // Use async/await everything + // Avoid execa.command: the args need to be escaped manually const result = execa.commandSync(cmd); if (log || debugMode) { logger.info`code=${obfuscateGitPass( @@ -60,6 +63,12 @@ In CWD code=${process.cwd()}`, } } +// Execa escape args and add necessary quotes automatically +// When using Execa.command, the args containing spaces must be escaped manually +function escapeArg(arg: string): string { + return arg.replaceAll(' ', '\\ '); +} + function hasGit() { return exec('git --version').exitCode === 0; } @@ -231,15 +240,20 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); // repository default branch. if ( exec( - `git clone --depth 1 --branch ${deploymentBranch} ${deploymentRepoURL} "${toPath}"`, + `git clone --depth 1 --branch ${deploymentBranch} ${deploymentRepoURL} ${escapeArg( + toPath, + )}`, ).exitCode !== 0 ) { - exec(`git clone --depth 1 ${deploymentRepoURL} "${toPath}"`); + exec(`git clone --depth 1 ${deploymentRepoURL} ${escapeArg(toPath)}`); exec(`git checkout -b ${deploymentBranch}`); } // Clear out any existing contents in the target directory - exec(`git rm -rf ${targetDirectory}`, {log: false, failfast: true}); + exec(`git rm -rf ${escapeArg(targetDirectory)}`, { + log: false, + failfast: true, + }); const targetPath = path.join(toPath, targetDirectory); try { @@ -252,18 +266,22 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); const gitUserName = process.env.GIT_USER_NAME; if (gitUserName) { - exec(`git config user.name "${gitUserName}"`, {failfast: true}); + exec(`git config user.name ${escapeArg(gitUserName)}`, {failfast: true}); } const gitUserEmail = process.env.GIT_USER_EMAIL; if (gitUserEmail) { - exec(`git config user.email "${gitUserEmail}"`, {failfast: true}); + exec(`git config user.email ${escapeArg(gitUserEmail)}`, { + failfast: true, + }); } const commitMessage = process.env.CUSTOM_COMMIT_MESSAGE ?? `Deploy website - based on ${currentCommit}`; - const commitResults = exec(`git commit -m "${commitMessage}"`); + const commitResults = exec( + `git commit -m ${escapeArg(commitMessage)} --allow-empty`, + ); if (exec(`git push --force origin ${deploymentBranch}`).exitCode !== 0) { throw new Error( 'Running "git push" command failed. Does the GitHub user account you are using have push access to the repository?', From 9cb83e35a065c67ecd184cf89ccd6d63e432817d Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 28 Feb 2025 13:22:59 +0100 Subject: [PATCH 17/17] use process.chdir --- packages/create-docusaurus/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts index 0d0ffa38e09e..f38f0f2287a3 100755 --- a/packages/create-docusaurus/src/index.ts +++ b/packages/create-docusaurus/src/index.ts @@ -583,7 +583,7 @@ export default async function init( const cdpath = path.relative('.', dest); const pkgManager = await getPackageManager(dest, cliOptions); if (!cliOptions.skipInstall) { - await execa('cd', [dest]); + process.chdir(dest); logger.info`Installing dependencies with name=${pkgManager}...`; // ...