Skip to content

Commit 49ec0ac

Browse files
Merge branch 'develop'
2 parents c353d20 + dd572fd commit 49ec0ac

File tree

20 files changed

+770
-57
lines changed

20 files changed

+770
-57
lines changed

aws_lambda_builders/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
# Changing version will trigger a new release!
66
# Please make the version change as the last step of your development.
7-
__version__ = "1.33.0"
7+
__version__ = "1.34.0"
88
RPC_PROTOCOL_VERSION = "0.3"

aws_lambda_builders/actions.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import os
77
import shutil
88
from pathlib import Path
9-
from typing import Iterator, Set, Tuple, Union
9+
from typing import Iterator, Optional, Set, Tuple, Union
1010

1111
from aws_lambda_builders import utils
1212
from aws_lambda_builders.utils import copytree, create_symlink_or_copy
@@ -169,14 +169,15 @@ class CopyDependenciesAction(BaseAction):
169169

170170
PURPOSE = Purpose.COPY_DEPENDENCIES
171171

172-
def __init__(self, source_dir, artifact_dir, destination_dir, maintain_symlinks=False):
172+
def __init__(self, source_dir, artifact_dir, destination_dir, maintain_symlinks=False, manifest_dir=None):
173173
self.source_dir = source_dir
174174
self.artifact_dir = artifact_dir
175175
self.dest_dir = destination_dir
176+
self.manifest_dir = manifest_dir
176177
self.maintain_symlinks = maintain_symlinks
177178

178179
def execute(self):
179-
deps_manager = DependencyManager(self.source_dir, self.artifact_dir, self.dest_dir)
180+
deps_manager = DependencyManager(self.source_dir, self.artifact_dir, self.dest_dir, self.manifest_dir)
180181

181182
for dependencies_source, new_destination in deps_manager.yield_source_dest():
182183
if os.path.islink(dependencies_source) and self.maintain_symlinks:
@@ -198,13 +199,14 @@ class MoveDependenciesAction(BaseAction):
198199

199200
PURPOSE = Purpose.MOVE_DEPENDENCIES
200201

201-
def __init__(self, source_dir, artifact_dir, destination_dir):
202+
def __init__(self, source_dir, artifact_dir, destination_dir, manifest_dir=None):
202203
self.source_dir = source_dir
203204
self.artifact_dir = artifact_dir
204205
self.dest_dir = destination_dir
206+
self.manifest_dir = manifest_dir
205207

206208
def execute(self):
207-
deps_manager = DependencyManager(self.source_dir, self.artifact_dir, self.dest_dir)
209+
deps_manager = DependencyManager(self.source_dir, self.artifact_dir, self.dest_dir, self.manifest_dir)
208210

209211
for dependencies_source, new_destination in deps_manager.yield_source_dest():
210212
# shutil.move can't create subfolders if this is the first file in that folder
@@ -256,10 +258,11 @@ class DependencyManager:
256258
# This allows for the installation of dependencies in the source directory
257259
IGNORE_LIST = ["node_modules"]
258260

259-
def __init__(self, source_dir, artifact_dir, destination_dir) -> None:
261+
def __init__(self, source_dir, artifact_dir, destination_dir, manifest_dir=None) -> None:
260262
self._source_dir: str = source_dir
261263
self._artifact_dir: str = artifact_dir
262264
self._dest_dir: str = destination_dir
265+
self._manifest_dir: Optional[str] = manifest_dir
263266
self._dependencies: Set[str] = set()
264267

265268
def yield_source_dest(self) -> Iterator[Tuple[str, str]]:
@@ -268,12 +271,13 @@ def yield_source_dest(self) -> Iterator[Tuple[str, str]]:
268271
yield os.path.join(self._artifact_dir, dep), os.path.join(self._dest_dir, dep)
269272

270273
def _set_dependencies(self) -> None:
271-
source = self._get_source_files_exclude_deps()
274+
source = self._get_source_files_exclude_deps(self._source_dir)
275+
manifest = self._get_source_files_exclude_deps(self._manifest_dir) if self._manifest_dir else set()
272276
artifact = set(os.listdir(self._artifact_dir))
273-
self._dependencies = artifact - source
277+
self._dependencies = artifact - (source.union(manifest))
274278

275-
def _get_source_files_exclude_deps(self) -> Set[str]:
276-
source_files = set(os.listdir(self._source_dir))
279+
def _get_source_files_exclude_deps(self, dir_path: str) -> Set[str]:
280+
source_files = set(os.listdir(dir_path))
277281
for item in self.IGNORE_LIST:
278282
if item in source_files:
279283
source_files.remove(item)

aws_lambda_builders/workflows/nodejs_npm/workflow.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,25 +74,49 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
7474

7575
npm_copy_npmrc_and_lockfile = NodejsNpmrcAndLockfileCopyAction(tar_package_dir, source_dir, osutils=osutils)
7676

77+
self.manifest_dir = self.osutils.dirname(self.manifest_path)
78+
is_building_in_source = self.build_dir == self.source_dir
79+
is_external_manifest = self.manifest_dir != self.source_dir
7780
self.actions = [
7881
npm_pack,
7982
npm_copy_npmrc_and_lockfile,
8083
CopySourceAction(tar_package_dir, artifacts_dir, excludes=self.EXCLUDED_FILES),
8184
]
8285

86+
if is_external_manifest:
87+
# npm pack only copies source code if the manifest is in the same directory as the source code, we need to
88+
# copy the source code if the customer specified a different manifest path
89+
self.actions.append(CopySourceAction(self.source_dir, artifacts_dir, excludes=self.EXCLUDED_FILES))
90+
8391
if self.download_dependencies:
8492
self.actions.append(
8593
NodejsNpmWorkflow.get_install_action(
8694
source_dir=source_dir,
87-
install_dir=self.build_dir,
95+
# run npm install in the directory where the manifest (package.json) exists if customer is building
96+
# in source, and manifest directory is different from source.
97+
# This will let NPM find the local dependencies that are defined in the manifest file (they are
98+
# usually defined as relative to the manifest location, and that is why we run `npm install` in the
99+
# manifest directory instead of source directory).
100+
# If customer is not building in source, so it is ok to run `npm install` in the build
101+
# directory (the artifacts directory in this case), as the local dependencies are not supported.
102+
install_dir=self.manifest_dir if is_building_in_source and is_external_manifest else self.build_dir,
88103
subprocess_npm=subprocess_npm,
89104
osutils=osutils,
90105
build_options=self.options,
91-
install_links=self.build_dir == self.source_dir,
106+
install_links=is_building_in_source,
92107
)
93108
)
94109

95-
if self.download_dependencies and self.build_dir == self.source_dir:
110+
if is_building_in_source and is_external_manifest:
111+
# Since we run `npm install` in the manifest directory, so we need to link the node_modules directory in
112+
# the source directory.
113+
source_dependencies_path = os.path.join(self.source_dir, "node_modules")
114+
manifest_dependencies_path = os.path.join(self.manifest_dir, "node_modules")
115+
self.actions.append(
116+
LinkSinglePathAction(source=manifest_dependencies_path, dest=source_dependencies_path)
117+
)
118+
119+
if self.download_dependencies and is_building_in_source:
96120
self.actions += self._actions_for_linking_source_dependencies_to_artifacts
97121

98122
# if no dependencies dir, just cleanup artifacts and we're done
@@ -107,9 +131,7 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
107131
# then copy them into the artifacts dir
108132
elif self.combine_dependencies:
109133
self.actions.append(
110-
CopySourceAction(
111-
self.dependencies_dir, artifacts_dir, maintain_symlinks=self.build_dir == self.source_dir
112-
)
134+
CopySourceAction(self.dependencies_dir, artifacts_dir, maintain_symlinks=is_building_in_source)
113135
)
114136

115137
self.actions += self._actions_for_cleanup
@@ -145,6 +167,7 @@ def _actions_for_updating_dependencies_dir(self):
145167
artifact_dir=self.artifacts_dir,
146168
destination_dir=self.dependencies_dir,
147169
maintain_symlinks=self.build_dir == self.source_dir,
170+
manifest_dir=self.manifest_dir,
148171
)
149172
)
150173
else:
@@ -153,6 +176,7 @@ def _actions_for_updating_dependencies_dir(self):
153176
source_dir=self.source_dir,
154177
artifact_dir=self.artifacts_dir,
155178
destination_dir=self.dependencies_dir,
179+
manifest_dir=self.manifest_dir,
156180
)
157181
)
158182

aws_lambda_builders/workflows/nodejs_npm_esbuild/workflow.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
import json
66
import logging
7+
import os
78
from pathlib import Path
89

910
from aws_lambda_builders.actions import (
1011
CleanUpAction,
1112
CopySourceAction,
13+
LinkSinglePathAction,
1214
LinkSourceAction,
1315
MoveDependenciesAction,
1416
)
@@ -53,6 +55,10 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
5355
self.osutils = osutils or OSUtils()
5456
self.subprocess_npm = SubprocessNpm(self.osutils)
5557
self.subprocess_esbuild = self._get_esbuild_subprocess()
58+
self.manifest_dir = self.osutils.dirname(self.manifest_path)
59+
60+
is_building_in_source = self.build_dir == self.source_dir
61+
is_external_manifest = self.manifest_dir != self.source_dir
5662

5763
bundler_config = self.get_build_properties()
5864

@@ -80,22 +86,45 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
8086
# if we're building in the source directory, we don't have to copy the source code
8187
self.actions = (
8288
[]
83-
if self.build_dir == self.source_dir
89+
if is_building_in_source
8490
else [CopySourceAction(source_dir=self.source_dir, dest_dir=self.build_dir, excludes=self.EXCLUDED_FILES)]
8591
)
8692

93+
if is_external_manifest and not is_building_in_source:
94+
# copy the manifest file (package.json) to the build directory in case if the manifest file is not in the
95+
# same directory as the source code, and customer is not building in source.
96+
self.actions.append(
97+
CopySourceAction(source_dir=self.manifest_dir, dest_dir=self.build_dir, excludes=self.EXCLUDED_FILES)
98+
)
99+
87100
if self.download_dependencies:
88101
self.actions.append(
89102
NodejsNpmWorkflow.get_install_action(
90103
source_dir=source_dir,
91-
install_dir=self.build_dir,
104+
# run npm install in the directory where the manifest (package.json) exists if customer is building
105+
# in source, and manifest directory is different from source.
106+
# This will let NPM find the local dependencies that are defined in the manifest file (they are
107+
# usually defined as relative to the manifest location, and that is why we run `npm install` in the
108+
# manifest directory instead of source directory).
109+
# If customer is not building in source, so it is ok to run `npm install` in the build
110+
# directory (the artifacts directory in this case), as the local dependencies are not supported.
111+
install_dir=self.manifest_dir if is_building_in_source and is_external_manifest else self.build_dir,
92112
subprocess_npm=self.subprocess_npm,
93113
osutils=self.osutils,
94114
build_options=self.options,
95-
install_links=self.build_dir == self.source_dir,
115+
install_links=is_building_in_source,
96116
)
97117
)
98118

119+
if is_building_in_source and is_external_manifest:
120+
# Since we run `npm install` in the manifest directory, so we need to link the node_modules directory in
121+
# the source directory.
122+
source_dependencies_path = os.path.join(self.source_dir, "node_modules")
123+
manifest_dependencies_path = os.path.join(self.manifest_dir, "node_modules")
124+
self.actions.append(
125+
LinkSinglePathAction(source=manifest_dependencies_path, dest=source_dependencies_path)
126+
)
127+
99128
bundle_action = EsbuildBundleAction(
100129
working_directory=self.build_dir,
101130
output_directory=self.artifacts_dir,
@@ -109,7 +138,7 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
109138
# If there's no dependencies_dir, just bundle and we're done.
110139
# Same thing if we're building in the source directory (since the dependencies persist in
111140
# the source directory, we don't want to move them or symlink them back to the source)
112-
if not self.dependencies_dir or self.build_dir == self.source_dir:
141+
if not self.dependencies_dir or is_building_in_source:
113142
self.actions.append(bundle_action)
114143
return
115144

@@ -118,7 +147,7 @@ def __init__(self, source_dir, artifacts_dir, scratch_dir, manifest_path, runtim
118147
self.actions += [
119148
bundle_action,
120149
CleanUpAction(self.dependencies_dir),
121-
MoveDependenciesAction(self.source_dir, self.scratch_dir, self.dependencies_dir),
150+
MoveDependenciesAction(self.source_dir, self.scratch_dir, self.dependencies_dir, self.manifest_dir),
122151
]
123152
else:
124153
# if we're reusing dependencies, then we need to symlink them before bundling

requirements/dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
coverage==7.2.6
1+
coverage==7.2.7
22
flake8==3.3.0; python_version < '3.8'
33
flake8==3.8.4; python_version >= '3.8'
44
pytest-cov==4.1.0

0 commit comments

Comments
 (0)