@@ -20,6 +20,7 @@ import { IPackageJson } from '@rushstack/node-core-library';
20
20
21
21
export const RUSH_JSON_FILENAME : string = 'rush.json' ;
22
22
const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME : string = 'RUSH_TEMP_FOLDER' ;
23
+ const INSTALL_RUN_LOCKFILE_PATH_VARIABLE : 'INSTALL_RUN_LOCKFILE_PATH' = 'INSTALL_RUN_LOCKFILE_PATH' ;
23
24
const INSTALLED_FLAG_FILENAME : string = 'installed.flag' ;
24
25
const NODE_MODULES_FOLDER_NAME : string = 'node_modules' ;
25
26
const PACKAGE_JSON_FILENAME : string = 'package.json' ;
@@ -334,29 +335,50 @@ function _isPackageAlreadyInstalled(packageInstallFolder: string): boolean {
334
335
}
335
336
}
336
337
338
+ /**
339
+ * Delete a file. Fail silently if it does not exist.
340
+ */
341
+ function _deleteFile ( file : string ) : void {
342
+ try {
343
+ fs . unlinkSync ( file ) ;
344
+ } catch ( err ) {
345
+ if ( err . code !== 'ENOENT' && err . code !== 'ENOTDIR' ) {
346
+ throw err ;
347
+ }
348
+ }
349
+ }
350
+
337
351
/**
338
352
* Removes the following files and directories under the specified folder path:
339
353
* - installed.flag
340
354
* -
341
355
* - node_modules
342
356
*/
343
- function _cleanInstallFolder ( rushTempFolder : string , packageInstallFolder : string ) : void {
357
+ function _cleanInstallFolder (
358
+ rushTempFolder : string ,
359
+ packageInstallFolder : string ,
360
+ lockFilePath : string | undefined
361
+ ) : void {
344
362
try {
345
363
const flagFile : string = path . resolve ( packageInstallFolder , INSTALLED_FLAG_FILENAME ) ;
346
- if ( fs . existsSync ( flagFile ) ) {
347
- fs . unlinkSync ( flagFile ) ;
348
- }
364
+ _deleteFile ( flagFile ) ;
349
365
350
366
const packageLockFile : string = path . resolve ( packageInstallFolder , 'package-lock.json' ) ;
351
- if ( fs . existsSync ( packageLockFile ) ) {
352
- fs . unlinkSync ( packageLockFile ) ;
353
- }
367
+ if ( lockFilePath ) {
368
+ fs . copyFileSync ( lockFilePath , packageLockFile ) ;
369
+ } else {
370
+ // Not running `npm ci`, so need to cleanup
371
+ _deleteFile ( packageLockFile ) ;
354
372
355
- const nodeModulesFolder : string = path . resolve ( packageInstallFolder , NODE_MODULES_FOLDER_NAME ) ;
356
- if ( fs . existsSync ( nodeModulesFolder ) ) {
357
- const rushRecyclerFolder : string = _ensureAndJoinPath ( rushTempFolder , 'rush-recycler' ) ;
373
+ const nodeModulesFolder : string = path . resolve ( packageInstallFolder , NODE_MODULES_FOLDER_NAME ) ;
374
+ if ( fs . existsSync ( nodeModulesFolder ) ) {
375
+ const rushRecyclerFolder : string = _ensureAndJoinPath ( rushTempFolder , 'rush-recycler' ) ;
358
376
359
- fs . renameSync ( nodeModulesFolder , path . join ( rushRecyclerFolder , `install-run-${ Date . now ( ) . toString ( ) } ` ) ) ;
377
+ fs . renameSync (
378
+ nodeModulesFolder ,
379
+ path . join ( rushRecyclerFolder , `install-run-${ Date . now ( ) . toString ( ) } ` )
380
+ ) ;
381
+ }
360
382
}
361
383
} catch ( e ) {
362
384
throw new Error ( `Error cleaning the package install folder (${ packageInstallFolder } ): ${ e } ` ) ;
@@ -386,18 +408,24 @@ function _createPackageJson(packageInstallFolder: string, name: string, version:
386
408
/**
387
409
* Run "npm install" in the package install folder.
388
410
*/
389
- function _installPackage ( logger : ILogger , packageInstallFolder : string , name : string , version : string ) : void {
411
+ function _installPackage (
412
+ logger : ILogger ,
413
+ packageInstallFolder : string ,
414
+ name : string ,
415
+ version : string ,
416
+ command : 'install' | 'ci'
417
+ ) : void {
390
418
try {
391
419
logger . info ( `Installing ${ name } ...` ) ;
392
420
const npmPath : string = getNpmPath ( ) ;
393
- const result : childProcess . SpawnSyncReturns < Buffer > = childProcess . spawnSync ( npmPath , [ 'install' ] , {
421
+ const result : childProcess . SpawnSyncReturns < Buffer > = childProcess . spawnSync ( npmPath , [ command ] , {
394
422
stdio : 'inherit' ,
395
423
cwd : packageInstallFolder ,
396
424
env : process . env
397
425
} ) ;
398
426
399
427
if ( result . status !== 0 ) {
400
- throw new Error ( ' "npm install " encountered an error' ) ;
428
+ throw new Error ( ` "npm ${ command } " encountered an error` ) ;
401
429
}
402
430
403
431
logger . info ( `Successfully installed ${ name } @${ version } ` ) ;
@@ -432,7 +460,8 @@ export function installAndRun(
432
460
packageName : string ,
433
461
packageVersion : string ,
434
462
packageBinName : string ,
435
- packageBinArgs : string [ ]
463
+ packageBinArgs : string [ ] ,
464
+ lockFilePath : string | undefined = process . env [ INSTALL_RUN_LOCKFILE_PATH_VARIABLE ]
436
465
) : number {
437
466
const rushJsonFolder : string = findRushJsonFolder ( ) ;
438
467
const rushCommonFolder : string = path . join ( rushJsonFolder , 'common' ) ;
@@ -445,13 +474,14 @@ export function installAndRun(
445
474
446
475
if ( ! _isPackageAlreadyInstalled ( packageInstallFolder ) ) {
447
476
// The package isn't already installed
448
- _cleanInstallFolder ( rushTempFolder , packageInstallFolder ) ;
477
+ _cleanInstallFolder ( rushTempFolder , packageInstallFolder , lockFilePath ) ;
449
478
450
479
const sourceNpmrcFolder : string = path . join ( rushCommonFolder , 'config' , 'rush' ) ;
451
480
_syncNpmrc ( logger , sourceNpmrcFolder , packageInstallFolder ) ;
452
481
453
482
_createPackageJson ( packageInstallFolder , packageName , packageVersion ) ;
454
- _installPackage ( logger , packageInstallFolder , packageName , packageVersion ) ;
483
+ const command : 'install' | 'ci' = lockFilePath ? 'ci' : 'install' ;
484
+ _installPackage ( logger , packageInstallFolder , packageName , packageVersion , command ) ;
455
485
_writeFlagFile ( packageInstallFolder ) ;
456
486
}
457
487
0 commit comments