@@ -163,7 +163,7 @@ export class Job {
163163 for ( const rule of this . rules ) {
164164 try {
165165 if ( rule [ 'if' ] ) {
166- const output = childProcess . execSync ( `[ ${ rule [ 'if' ] } ] && exit 0 || exit 1` , { cwd : this . cwd , env : this . getEnvs ( ) } ) ;
166+ const output = childProcess . execSync ( `if [ ${ rule [ 'if' ] } ]; then exit 0; else exit 1; fi ` , { cwd : this . cwd , env : this . getEnvs ( ) , shell : 'bash' } ) ;
167167 if ( output . length > 0 ) {
168168 process . stderr . write ( `Rule output ${ output } ` ) ;
169169 }
@@ -233,7 +233,7 @@ export class Job {
233233
234234 const startTime = process . hrtime ( ) ;
235235 const prescripts = this . beforeScripts . concat ( this . scripts ) ;
236- this . prescriptsExitCode = await this . exec ( prescripts ) ;
236+ this . prescriptsExitCode = await this . execScripts ( prescripts ) ;
237237 this . started = true ;
238238 if ( this . afterScripts . length === 0 && this . prescriptsExitCode > 0 && ! this . allowFailure ) {
239239 process . stderr . write ( `${ this . getExitedString ( startTime , this . prescriptsExitCode , false ) } \n` ) ;
@@ -262,7 +262,7 @@ export class Job {
262262
263263 this . afterScriptsExitCode = 0 ;
264264 if ( this . afterScripts . length > 0 ) {
265- this . afterScriptsExitCode = await this . exec ( this . afterScripts ) ;
265+ this . afterScriptsExitCode = await this . execScripts ( this . afterScripts ) ;
266266 }
267267
268268 if ( this . afterScriptsExitCode > 0 ) {
@@ -285,68 +285,51 @@ export class Job {
285285 return this . name ;
286286 }
287287
288- private async exec ( scripts : string [ ] ) : Promise < number > {
288+ private async execScripts ( scripts : string [ ] ) : Promise < number > {
289289 if ( scripts . length === 0 ) {
290- return Promise . resolve ( 0 ) ;
290+ return Promise . reject ( new Error ( `'scripts:' empty for ${ this . name } ` ) ) ;
291291 }
292292
293+ const jobName = this . name ;
293294 const jobNameStr = this . getJobNameString ( ) ;
294295 const outputFilesPath = this . getOutputFilesPath ( ) ;
296+ const scriptPath = `${ this . cwd } .gitlab-ci-local/shell/${ jobName } .sh` ;
297+
298+ await fs . ensureFile ( scriptPath ) ;
299+ await fs . chmod ( scriptPath , '755' ) ;
300+ await fs . truncate ( scriptPath ) ;
301+
302+
303+ await fs . appendFile ( scriptPath , `#!/bin/bash\n` ) ;
304+ await fs . appendFile ( scriptPath , `set -e\n` ) ;
305+
306+ for ( const line of scripts ) {
307+ await fs . appendFile ( scriptPath , `echo '${ c . green ( `\$ ${ line . replace ( / [ ' ] / g, "\\''" ) } ` ) } '\n` ) ;
308+ await fs . appendFile ( scriptPath , `${ line } \n` ) ;
309+ }
295310
296311 return new Promise ( ( resolve , reject ) => {
297- const bash = childProcess . spawn ( "bash" , { cwd : this . cwd , env : this . getEnvs ( ) } ) ;
298- bash . on ( "error" , ( err ) => {
299- reject ( err ) ;
300- } ) ;
301- bash . on ( "close" , ( signal ) => {
302- resolve ( signal ) ;
303- } ) ;
304-
305- const nextCmd = ( ) => {
306- const script = scripts . shift ( ) ;
307- if ( ! script ) {
308- bash . stdin . write ( "exit 0\n" ) ;
309- } else {
310- process . stdout . write ( `${ jobNameStr } ${ c . green ( `\$ ${ script } ` ) } \n` ) ;
311- bash . stdin . write ( `${ script } ;echo GCL_MARKER=$?\n` ) ;
312- }
313- } ;
314-
315- bash . stdout . on ( "data" , ( e ) => {
316- const out = `${ e } ` ;
317- const regExec = / G C L _ M A R K E R = (?< exitCode > \d * ) / . exec ( out ) ;
318- const stripped = out . replace ( / G C L _ M A R K E R = \d * \n / , "" ) ;
319-
320- if ( stripped !== "" ) {
321- for ( const line of stripped . split ( / \r ? \n / ) ) {
322- if ( line !== "" ) {
323- fs . appendFileSync ( outputFilesPath , `${ line } \n` ) ;
324- process . stdout . write ( `${ jobNameStr } ${ c . greenBright ( ">" ) } ${ line } \n` ) ;
325- }
312+ const p = childProcess . exec ( `${ scriptPath } ` , { env : this . envs , cwd : this . cwd , shell : 'bash' } ) ;
313+
314+ const outFunc = ( e : any , stream : NodeJS . WriteStream , colorize : ( str : string ) => string ) => {
315+ for ( const line of `${ e } ` . split ( / \r ? \n / ) ) {
316+ if ( line . length === 0 ) continue ;
317+ stream . write ( `${ jobNameStr } ` ) ;
318+ if ( ! line . startsWith ( '\u001b[32m$' ) ) {
319+ stream . write ( `${ colorize ( ">" ) } ` ) ;
326320 }
321+ stream . write ( `${ line } \n` ) ;
322+ fs . appendFileSync ( outputFilesPath , `${ line } \n` ) ;
327323 }
324+ }
328325
329- if ( regExec && regExec . groups && regExec . groups . exitCode && regExec . groups . exitCode === "0" ) {
330- nextCmd ( ) ;
331- } else if ( regExec && regExec . groups && regExec . groups . exitCode && regExec . groups . exitCode !== "0" ) {
332- bash . stdin . write ( `exit ${ regExec . groups . exitCode } \n` ) ;
333- } else if ( regExec ) {
334- reject ( `GCL_MARKER was not parsed correctly ${ JSON . stringify ( regExec ) } ` ) ;
335- }
336- } ) ;
337- bash . stderr . on ( "data" , ( e ) => {
338- const err = `${ e } ` ;
339- if ( err !== "" ) {
340- for ( const line of err . split ( / \r ? \n / ) ) {
341- if ( line !== "" ) {
342- fs . appendFileSync ( outputFilesPath , `${ line } \n` ) ;
343- process . stderr . write ( `${ jobNameStr } ${ c . redBright ( ">" ) } ${ line } \n` ) ;
344- }
345- }
346- }
347- } ) ;
326+ // @ts -ignore
327+ p . stdout . on ( "data" , ( e ) => outFunc ( e , process . stdout , ( s ) => c . greenBright ( s ) ) ) ;
328+ // @ts -ignore
329+ p . stderr . on ( "data" , ( e ) => outFunc ( e , process . stderr , ( s ) => c . redBright ( s ) ) ) ;
348330
349- nextCmd ( ) ;
331+ p . on ( "error" , ( err ) => reject ( err ) ) ;
332+ p . on ( "close" , ( signal ) => resolve ( signal ) ) ;
350333 } ) ;
351334 }
352335
0 commit comments