@@ -733,6 +733,14 @@ def npm_requirements_step(path, prefix=None, required=False, tmp_dir=None):
733
733
requirements = path
734
734
if os .path .isdir (path ):
735
735
requirements = os .path .join (path , "package.json" )
736
+ npm_lock_file = os .path .join (path , "package-lock.json" )
737
+ else :
738
+ npm_lock_file = os .path .join (os .path .dirname (path ), "package-lock.json" )
739
+
740
+ if os .path .isfile (npm_lock_file ):
741
+ hash (npm_lock_file )
742
+ log .info ("Added npm lock file: %s" , npm_lock_file )
743
+
736
744
if not os .path .isfile (requirements ):
737
745
if required :
738
746
raise RuntimeError ("File not found: {}" .format (requirements ))
@@ -1088,7 +1096,7 @@ def install_pip_requirements(query, requirements_file, tmp_dir):
1088
1096
ok = True
1089
1097
elif docker_file or docker_build_root :
1090
1098
raise ValueError (
1091
- "docker_image must be specified " " for a custom image future references"
1099
+ "docker_image must be specified for a custom image future references"
1092
1100
)
1093
1101
1094
1102
working_dir = os .getcwd ()
@@ -1108,7 +1116,7 @@ def install_pip_requirements(query, requirements_file, tmp_dir):
1108
1116
elif OSX :
1109
1117
# Workaround for OSX when XCode command line tools'
1110
1118
# python becomes the main system python interpreter
1111
- os_path = "{}:/Library/Developer/CommandLineTools" " /usr/bin" .format (
1119
+ os_path = "{}:/Library/Developer/CommandLineTools/usr/bin" .format (
1112
1120
os .environ ["PATH" ]
1113
1121
)
1114
1122
subproc_env = os .environ .copy ()
@@ -1390,14 +1398,15 @@ def install_npm_requirements(query, requirements_file, tmp_dir):
1390
1398
ok = True
1391
1399
elif docker_file or docker_build_root :
1392
1400
raise ValueError (
1393
- "docker_image must be specified " " for a custom image future references"
1401
+ "docker_image must be specified for a custom image future references"
1394
1402
)
1395
1403
1396
1404
log .info ("Installing npm requirements: %s" , requirements_file )
1397
1405
with tempdir (tmp_dir ) as temp_dir :
1398
- requirements_filename = os .path .basename (requirements_file )
1399
- target_file = os .path .join (temp_dir , requirements_filename )
1400
- shutil .copyfile (requirements_file , target_file )
1406
+ temp_copy = TemporaryCopy (os .path .dirname (requirements_file ), temp_dir , log )
1407
+ temp_copy .add (os .path .basename (requirements_file ))
1408
+ temp_copy .add ("package-lock.json" , required = False )
1409
+ temp_copy .copy_to_target_dir ()
1401
1410
1402
1411
subproc_env = None
1403
1412
npm_exec = "npm"
@@ -1442,10 +1451,63 @@ def install_npm_requirements(query, requirements_file, tmp_dir):
1442
1451
"available in system PATH" .format (runtime )
1443
1452
) from e
1444
1453
1445
- os . remove ( target_file )
1454
+ temp_copy . remove_from_target_dir ( )
1446
1455
yield temp_dir
1447
1456
1448
1457
1458
+ class TemporaryCopy :
1459
+ """Temporarily copy files to a specified location and remove them when
1460
+ not needed.
1461
+ """
1462
+
1463
+ def __init__ (self , source_dir_path , target_dir_path , logger = None ):
1464
+ """Initialise with a target and a source directories."""
1465
+ self .source_dir_path = source_dir_path
1466
+ self .target_dir_path = target_dir_path
1467
+ self ._filenames = []
1468
+ self ._logger = logger
1469
+
1470
+ def _make_source_path (self , filename ):
1471
+ return os .path .join (self .source_dir_path , filename )
1472
+
1473
+ def _make_target_path (self , filename ):
1474
+ return os .path .join (self .target_dir_path , filename )
1475
+
1476
+ def add (self , filename , * , required = True ):
1477
+ """Add a file to be copied from from source to target directory
1478
+ when `TemporaryCopy.copy_to_target_dir()` is called.
1479
+
1480
+ By default, the file must exist in the source directory. Set `required`
1481
+ to `False` if the file is optional.
1482
+ """
1483
+ if os .path .exists (self ._make_source_path (filename )):
1484
+ self ._filenames .append (filename )
1485
+ elif required :
1486
+ raise RuntimeError ("File not found: {}" .format (filename ))
1487
+
1488
+ def copy_to_target_dir (self ):
1489
+ """Copy files (added so far) to the target directory."""
1490
+ for filename in self ._filenames :
1491
+ if self ._logger :
1492
+ self ._logger .info ("Copying temporarily '%s'" , filename )
1493
+
1494
+ shutil .copyfile (
1495
+ self ._make_source_path (filename ),
1496
+ self ._make_target_path (filename ),
1497
+ )
1498
+
1499
+ def remove_from_target_dir (self ):
1500
+ """Remove files (added so far) from the target directory."""
1501
+ for filename in self ._filenames :
1502
+ if self ._logger :
1503
+ self ._logger .info ("Removing temporarily copied '%s'" , filename )
1504
+
1505
+ try :
1506
+ os .remove (self ._make_target_path (filename ))
1507
+ except FileNotFoundError :
1508
+ pass
1509
+
1510
+
1449
1511
def docker_image_id_command (tag ):
1450
1512
""""""
1451
1513
docker_cmd = ["docker" , "images" , "--format={{.ID}}" , tag ]
@@ -1649,7 +1711,7 @@ def prepare_command(args):
1649
1711
timestamp = timestamp_now_ns ()
1650
1712
was_missing = True
1651
1713
else :
1652
- timestamp = "<WARNING: Missing lambda zip artifacts " " wouldn't be restored>"
1714
+ timestamp = "<WARNING: Missing lambda zip artifacts wouldn't be restored>"
1653
1715
1654
1716
# Replace variables in the build command with calculated values.
1655
1717
build_data = {
0 commit comments