@@ -9,7 +9,7 @@ import fs from 'fs-extra';
99import path from 'path' ;
1010import os from 'os' ;
1111import logger from '@docusaurus/logger' ;
12- import execa from 'execa' ;
12+ import { execa } from 'execa' ;
1313import { hasSSHProtocol , buildSshUrl , buildHttpsUrl } from '@docusaurus/utils' ;
1414import { loadContext , type LoadContextParams } from '../server/site' ;
1515import { build } from './build/build' ;
@@ -30,14 +30,16 @@ const debugMode = !!process.env.DOCUSAURUS_DEPLOY_DEBUG;
3030
3131// Log executed commands so that user can figure out mistakes on his own
3232// for example: https://github.com/facebook/docusaurus/issues/3875
33- function exec ( cmd : string , options ?: { log ?: boolean ; failfast ?: boolean } ) {
33+ async function exec (
34+ file : string ,
35+ args : string [ ] ,
36+ options ?: { log ?: boolean ; failfast ?: boolean } ,
37+ ) {
3438 const log = options ?. log ?? true ;
35- const failfast = options ?. failfast ?? false ;
39+ const failfast = options ?. failfast ?? true ;
40+ const cmd = [ file , ...args ] . join ( ' ' ) ;
3641 try {
37- // TODO migrate to execa(file,[...args]) instead
38- // Use async/await everything
39- // Avoid execa.command: the args need to be escaped manually
40- const result = execa . commandSync ( cmd ) ;
42+ const result = await execa ( file , args , { reject : false } ) ;
4143 if ( log || debugMode ) {
4244 logger . info `code=${ obfuscateGitPass (
4345 cmd ,
@@ -48,7 +50,8 @@ function exec(cmd: string, options?: {log?: boolean; failfast?: boolean}) {
4850 }
4951 if ( failfast && result . exitCode !== 0 ) {
5052 throw new Error (
51- `Command returned unexpected exitCode ${ result . exitCode } ` ,
53+ `Command returned unexpected exitCode ${ result . exitCode }
54+ ${ result . stderr } `,
5255 ) ;
5356 }
5457 return result ;
@@ -63,14 +66,8 @@ In CWD code=${process.cwd()}`,
6366 }
6467}
6568
66- // Execa escape args and add necessary quotes automatically
67- // When using Execa.command, the args containing spaces must be escaped manually
68- function escapeArg ( arg : string ) : string {
69- return arg . replaceAll ( ' ' , '\\ ' ) ;
70- }
71-
72- function hasGit ( ) {
73- return exec ( 'git --version' ) . exitCode === 0 ;
69+ async function hasGit ( ) {
70+ return ( await exec ( 'git' , [ '--version' ] , { failfast : false } ) ) . exitCode === 0 ;
7471}
7572
7673export async function deploy (
@@ -93,26 +90,22 @@ This behavior can have SEO impacts and create relative link issues.
9390 }
9491
9592 logger . info ( 'Deploy command invoked...' ) ;
96- if ( ! hasGit ( ) ) {
93+ if ( ! ( await hasGit ( ) ) ) {
9794 throw new Error ( 'Git not installed or not added to PATH!' ) ;
9895 }
9996
10097 // Source repo is the repo from where the command is invoked
101- const { stdout} = exec ( 'git remote get-url origin' , {
98+ const { stdout} = await exec ( 'git' , [ ' remote' , ' get-url' , ' origin'] , {
10299 log : false ,
103- failfast : true ,
104100 } ) ;
105101 const sourceRepoUrl = stdout . trim ( ) ;
106102
107103 // The source branch; defaults to the currently checked out branch
108104 const sourceBranch =
109105 process . env . CURRENT_BRANCH ??
110- exec ( 'git rev-parse --abbrev-ref HEAD' , {
111- log : false ,
112- failfast : true ,
113- } )
114- ?. stdout ?. toString ( )
115- . trim ( ) ;
106+ (
107+ await exec ( 'git' , [ 'rev-parse' , '--abbrev-ref' , 'HEAD' ] , { log : false } )
108+ ) . stdout . trim ( ) ;
116109
117110 const gitUser = process . env . GIT_USER ;
118111
@@ -157,10 +150,7 @@ This behavior can have SEO impacts and create relative link issues.
157150 const isPullRequest =
158151 process . env . CI_PULL_REQUEST ?? process . env . CIRCLE_PULL_REQUEST ;
159152 if ( isPullRequest ) {
160- exec ( 'echo "Skipping deploy on a pull request."' , {
161- log : false ,
162- failfast : true ,
163- } ) ;
153+ logger . info ( 'Skipping deploy on a pull request.' ) ;
164154 process . exit ( 0 ) ;
165155 }
166156
@@ -225,7 +215,9 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
225215
226216 // Save the commit hash that triggers publish-gh-pages before checking
227217 // out to deployment branch.
228- const currentCommit = exec ( 'git rev-parse HEAD' ) ?. stdout ?. toString ( ) . trim ( ) ;
218+ const currentCommit = (
219+ await exec ( 'git' , [ 'rev-parse' , 'HEAD' ] )
220+ ) . stdout . trim ( ) ;
229221
230222 const runDeploy = async ( outputDirectory : string ) => {
231223 const targetDirectory = cliOptions . targetDir ?? '.' ;
@@ -238,22 +230,26 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
238230 // Clones the repo into the temp folder and checks out the target branch.
239231 // If the branch doesn't exist, it creates a new one based on the
240232 // repository default branch.
241- if (
242- exec (
243- `git clone --depth 1 --branch ${ deploymentBranch } ${ deploymentRepoURL } ${ escapeArg (
244- toPath ,
245- ) } `,
246- ) . exitCode !== 0
247- ) {
248- exec ( `git clone --depth 1 ${ deploymentRepoURL } ${ escapeArg ( toPath ) } ` ) ;
249- exec ( `git checkout -b ${ deploymentBranch } ` ) ;
233+ const cloneResult = await exec (
234+ 'git' ,
235+ [
236+ 'clone' ,
237+ '--depth' ,
238+ '1' ,
239+ '--branch' ,
240+ deploymentBranch ,
241+ deploymentRepoURL ,
242+ toPath ,
243+ ] ,
244+ { failfast : false } ,
245+ ) ;
246+ if ( cloneResult . exitCode !== 0 ) {
247+ await exec ( 'git' , [ 'clone' , '--depth' , '1' , deploymentRepoURL , toPath ] ) ;
248+ await exec ( 'git' , [ 'checkout' , '-b' , deploymentBranch ] ) ;
250249 }
251250
252251 // Clear out any existing contents in the target directory
253- exec ( `git rm -rf ${ escapeArg ( targetDirectory ) } ` , {
254- log : false ,
255- failfast : true ,
256- } ) ;
252+ await exec ( 'git' , [ 'rm' , '-rf' , targetDirectory ] , { log : false } ) ;
257253
258254 const targetPath = path . join ( toPath , targetDirectory ) ;
259255 try {
@@ -262,32 +258,37 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
262258 logger . error `Copying build assets from path=${ fromPath } to path=${ targetPath } failed.` ;
263259 throw err ;
264260 }
265- exec ( 'git add --all' , { failfast : true } ) ;
261+ await exec ( 'git' , [ ' add' , ' --all'] ) ;
266262
267263 const gitUserName = process . env . GIT_USER_NAME ;
268264 if ( gitUserName ) {
269- exec ( ` git config user.name ${ escapeArg ( gitUserName ) } ` , { failfast : true } ) ;
265+ await exec ( ' git' , [ ' config' , ' user.name' , gitUserName ] ) ;
270266 }
271267
272268 const gitUserEmail = process . env . GIT_USER_EMAIL ;
273269 if ( gitUserEmail ) {
274- exec ( `git config user.email ${ escapeArg ( gitUserEmail ) } ` , {
275- failfast : true ,
276- } ) ;
270+ await exec ( 'git' , [ 'config' , 'user.email' , gitUserEmail ] ) ;
277271 }
278272
279273 const commitMessage =
280274 process . env . CUSTOM_COMMIT_MESSAGE ??
281275 `Deploy website - based on ${ currentCommit } ` ;
282- const commitResults = exec (
283- `git commit -m ${ escapeArg ( commitMessage ) } --allow-empty` ,
276+ // The commit might return a non-zero value when site is up to date.
277+ const commitResults = await exec (
278+ 'git' ,
279+ [ 'commit' , '-m' , commitMessage , '--allow-empty' ] ,
280+ { failfast : false } ,
281+ ) ;
282+ const pushResult = await exec (
283+ 'git' ,
284+ [ 'push' , '--force' , 'origin' , deploymentBranch ] ,
285+ { failfast : false } ,
284286 ) ;
285- if ( exec ( `git push --force origin ${ deploymentBranch } ` ) . exitCode !== 0 ) {
287+ if ( pushResult . exitCode !== 0 ) {
286288 throw new Error (
287289 'Running "git push" command failed. Does the GitHub user account you are using have push access to the repository?' ,
288290 ) ;
289291 } else if ( commitResults . exitCode === 0 ) {
290- // The commit might return a non-zero value when site is up to date.
291292 let websiteURL ;
292293 if ( githubHost === 'github.com' ) {
293294 websiteURL = projectName . includes ( '.github.io' )
@@ -297,7 +298,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
297298 // GitHub enterprise hosting.
298299 websiteURL = `https://${ githubHost } /pages/${ organizationName } /${ projectName } /` ;
299300 }
300- exec ( `echo " Website is live at ${ websiteURL } ."` , { failfast : true } ) ;
301+ logger . success ` Website is live at url= ${ websiteURL } .` ;
301302 process . exit ( 0 ) ;
302303 }
303304 } ;
0 commit comments