Skip to content

Commit fffe6e4

Browse files
authored
Merge pull request #361 from aws/develop
chore: Merge develop to master
2 parents 3a95de8 + 70797c0 commit fffe6e4

File tree

18 files changed

+349
-70
lines changed

18 files changed

+349
-70
lines changed

aws_lambda_builders/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
22
AWS Lambda Builder Library
33
"""
4-
__version__ = "1.15.0"
4+
__version__ = "1.16.0"
55
RPC_PROTOCOL_VERSION = "0.3"

aws_lambda_builders/validator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
SUPPORTED_RUNTIMES = {
1414
"nodejs12.x": [ARM64, X86_64],
1515
"nodejs14.x": [ARM64, X86_64],
16+
"nodejs16.x": [ARM64, X86_64],
1617
"python3.6": [X86_64],
1718
"python3.7": [X86_64],
1819
"python3.8": [ARM64, X86_64],

aws_lambda_builders/workflows/nodejs_npm/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,6 @@ def is_windows(self):
5353
def parse_json(self, path):
5454
with open(path) as json_file:
5555
return json.load(json_file)
56+
57+
def check_output(self, path):
58+
return subprocess.check_output(["node", path])

aws_lambda_builders/workflows/nodejs_npm_esbuild/actions.py

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def __init__(
5454
5555
:type skip_deps: bool
5656
:param skip_deps: if dependencies should be omitted from bundling
57+
58+
:type bundler_config: Dict[str,Any]
59+
:param bundler_config: the bundler configuration
5760
"""
5861
super(EsbuildBundleAction, self).__init__()
5962
self.scratch_dir = scratch_dir
@@ -71,38 +74,29 @@ def execute(self):
7174
:raises lambda_builders.actions.ActionFailedError: when esbuild packaging fails
7275
"""
7376

74-
if self.ENTRY_POINTS not in self.bundler_config:
75-
raise ActionFailedError(f"{self.ENTRY_POINTS} not set ({self.bundler_config})")
76-
77-
entry_points = self.bundler_config[self.ENTRY_POINTS]
78-
79-
if not isinstance(entry_points, list):
80-
raise ActionFailedError(f"{self.ENTRY_POINTS} must be a list ({self.bundler_config})")
81-
82-
if not entry_points:
83-
raise ActionFailedError(f"{self.ENTRY_POINTS} must not be empty ({self.bundler_config})")
84-
85-
entry_paths = [self.osutils.joinpath(self.scratch_dir, entry_point) for entry_point in entry_points]
86-
87-
LOG.debug("NODEJS building %s using esbuild to %s", entry_paths, self.artifacts_dir)
88-
89-
explicit_entry_points = []
90-
for entry_path, entry_point in zip(entry_paths, entry_points):
91-
explicit_entry_points.append(self._get_explicit_file_type(entry_point, entry_path))
77+
explicit_entry_points = self._construct_esbuild_entry_points()
9278

9379
args = explicit_entry_points + ["--bundle", "--platform=node", "--format=cjs"]
9480
minify = self.bundler_config.get("minify", True)
9581
sourcemap = self.bundler_config.get("sourcemap", True)
9682
target = self.bundler_config.get("target", "es2020")
83+
external = self.bundler_config.get("external", [])
84+
loader = self.bundler_config.get("loader", [])
9785
if minify:
9886
args.append("--minify")
9987
if sourcemap:
10088
args.append("--sourcemap")
89+
if external:
90+
args.extend(map(lambda x: f"--external:{x}", external))
91+
if loader:
92+
args.extend(map(lambda x: f"--loader:{x}", loader))
93+
10194
args.append("--target={}".format(target))
10295
args.append("--outdir={}".format(self.artifacts_dir))
10396

10497
if self.skip_deps:
10598
LOG.info("Running custom esbuild using Node.js")
99+
# Don't pass externals because the esbuild.js template makes everything external
106100
script = EsbuildBundleAction._get_node_esbuild_template(
107101
explicit_entry_points, target, self.artifacts_dir, minify, sourcemap
108102
)
@@ -132,6 +126,30 @@ def _run_external_esbuild_in_nodejs(self, script):
132126
except EsbuildExecutionError as ex:
133127
raise ActionFailedError(str(ex))
134128

129+
def _construct_esbuild_entry_points(self):
130+
"""
131+
Construct the list of explicit entry points
132+
"""
133+
if self.ENTRY_POINTS not in self.bundler_config:
134+
raise ActionFailedError(f"{self.ENTRY_POINTS} not set ({self.bundler_config})")
135+
136+
entry_points = self.bundler_config[self.ENTRY_POINTS]
137+
138+
if not isinstance(entry_points, list):
139+
raise ActionFailedError(f"{self.ENTRY_POINTS} must be a list ({self.bundler_config})")
140+
141+
if not entry_points:
142+
raise ActionFailedError(f"{self.ENTRY_POINTS} must not be empty ({self.bundler_config})")
143+
144+
entry_paths = [self.osutils.joinpath(self.scratch_dir, entry_point) for entry_point in entry_points]
145+
146+
LOG.debug("NODEJS building %s using esbuild to %s", entry_paths, self.artifacts_dir)
147+
148+
explicit_entry_points = []
149+
for entry_path, entry_point in zip(entry_paths, entry_points):
150+
explicit_entry_points.append(self._get_explicit_file_type(entry_point, entry_path))
151+
return explicit_entry_points
152+
135153
@staticmethod
136154
def _get_node_esbuild_template(entry_points, target, out_dir, minify, sourcemap):
137155
"""

tests/integration/workflows/nodejs_npm/test_nodejs_npm.py

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,30 @@ def setUp(self):
2929
self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
3030

3131
self.builder = LambdaBuilder(language="nodejs", dependency_manager="npm", application_framework=None)
32-
self.runtime = "nodejs12.x"
3332

3433
def tearDown(self):
3534
shutil.rmtree(self.artifacts_dir)
3635
shutil.rmtree(self.scratch_dir)
3736
shutil.rmtree(self.dependencies_dir)
3837

39-
def test_builds_project_without_dependencies(self):
38+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
39+
def test_builds_project_without_dependencies(self, runtime):
4040
source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
4141

4242
self.builder.build(
4343
source_dir,
4444
self.artifacts_dir,
4545
self.scratch_dir,
4646
os.path.join(source_dir, "package.json"),
47-
runtime=self.runtime,
47+
runtime=runtime,
4848
)
4949

5050
expected_files = {"package.json", "included.js"}
5151
output_files = set(os.listdir(self.artifacts_dir))
5252
self.assertEqual(expected_files, output_files)
5353

54-
def test_builds_project_without_manifest(self):
54+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
55+
def test_builds_project_without_manifest(self, runtime):
5556
source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-manifest")
5657

5758
with mock.patch.object(logger, "warning") as mock_warning:
@@ -60,38 +61,40 @@ def test_builds_project_without_manifest(self):
6061
self.artifacts_dir,
6162
self.scratch_dir,
6263
os.path.join(source_dir, "package.json"),
63-
runtime=self.runtime,
64+
runtime=runtime,
6465
)
6566

6667
expected_files = {"app.js"}
6768
output_files = set(os.listdir(self.artifacts_dir))
6869
mock_warning.assert_called_once_with("package.json file not found. Continuing the build without dependencies.")
6970
self.assertEqual(expected_files, output_files)
7071

71-
def test_builds_project_and_excludes_hidden_aws_sam(self):
72+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
73+
def test_builds_project_and_excludes_hidden_aws_sam(self, runtime):
7274
source_dir = os.path.join(self.TEST_DATA_FOLDER, "excluded-files")
7375

7476
self.builder.build(
7577
source_dir,
7678
self.artifacts_dir,
7779
self.scratch_dir,
7880
os.path.join(source_dir, "package.json"),
79-
runtime=self.runtime,
81+
runtime=runtime,
8082
)
8183

8284
expected_files = {"package.json", "included.js"}
8385
output_files = set(os.listdir(self.artifacts_dir))
8486
self.assertEqual(expected_files, output_files)
8587

86-
def test_builds_project_with_remote_dependencies(self):
88+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
89+
def test_builds_project_with_remote_dependencies(self, runtime):
8790
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")
8891

8992
self.builder.build(
9093
source_dir,
9194
self.artifacts_dir,
9295
self.scratch_dir,
9396
os.path.join(source_dir, "package.json"),
94-
runtime=self.runtime,
97+
runtime=runtime,
9598
)
9699

97100
expected_files = {"package.json", "included.js", "node_modules"}
@@ -102,15 +105,16 @@ def test_builds_project_with_remote_dependencies(self):
102105
output_modules = set(os.listdir(os.path.join(self.artifacts_dir, "node_modules")))
103106
self.assertEqual(expected_modules, output_modules)
104107

105-
def test_builds_project_with_npmrc(self):
108+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
109+
def test_builds_project_with_npmrc(self, runtime):
106110
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npmrc")
107111

108112
self.builder.build(
109113
source_dir,
110114
self.artifacts_dir,
111115
self.scratch_dir,
112116
os.path.join(source_dir, "package.json"),
113-
runtime=self.runtime,
117+
runtime=runtime,
114118
)
115119

116120
expected_files = {"package.json", "included.js", "node_modules"}
@@ -122,8 +126,20 @@ def test_builds_project_with_npmrc(self):
122126
output_modules = set(os.listdir(os.path.join(self.artifacts_dir, "node_modules")))
123127
self.assertEqual(expected_modules, output_modules)
124128

125-
@parameterized.expand(["package-lock", "shrinkwrap", "package-lock-and-shrinkwrap"])
126-
def test_builds_project_with_lockfile(self, dir_name):
129+
@parameterized.expand(
130+
[
131+
("nodejs12.x", "package-lock"),
132+
("nodejs14.x", "package-lock"),
133+
("nodejs16.x", "package-lock"),
134+
("nodejs12.x", "shrinkwrap"),
135+
("nodejs14.x", "shrinkwrap"),
136+
("nodejs16.x", "shrinkwrap"),
137+
("nodejs12.x", "package-lock-and-shrinkwrap"),
138+
("nodejs14.x", "package-lock-and-shrinkwrap"),
139+
("nodejs16.x", "package-lock-and-shrinkwrap"),
140+
]
141+
)
142+
def test_builds_project_with_lockfile(self, runtime, dir_name):
127143
expected_files_common = {"package.json", "included.js", "node_modules"}
128144
expected_files_by_dir_name = {
129145
"package-lock": {"package-lock.json"},
@@ -138,7 +154,7 @@ def test_builds_project_with_lockfile(self, dir_name):
138154
self.artifacts_dir,
139155
self.scratch_dir,
140156
os.path.join(source_dir, "package.json"),
141-
runtime=self.runtime,
157+
runtime=runtime,
142158
)
143159

144160
expected_files = expected_files_common.union(expected_files_by_dir_name[dir_name])
@@ -147,8 +163,8 @@ def test_builds_project_with_lockfile(self, dir_name):
147163

148164
self.assertEqual(expected_files, output_files)
149165

150-
def test_fails_if_npm_cannot_resolve_dependencies(self):
151-
166+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
167+
def test_fails_if_npm_cannot_resolve_dependencies(self, runtime):
152168
source_dir = os.path.join(self.TEST_DATA_FOLDER, "broken-deps")
153169

154170
with self.assertRaises(WorkflowFailedError) as ctx:
@@ -157,20 +173,21 @@ def test_fails_if_npm_cannot_resolve_dependencies(self):
157173
self.artifacts_dir,
158174
self.scratch_dir,
159175
os.path.join(source_dir, "package.json"),
160-
runtime=self.runtime,
176+
runtime=runtime,
161177
)
162178

163179
self.assertIn("No matching version found for [email protected]", str(ctx.exception))
164180

165-
def test_builds_project_with_remote_dependencies_without_download_dependencies_with_dependencies_dir(self):
181+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
182+
def test_builds_project_with_remote_dependencies_without_download_dependencies_with_dependencies_dir(self, runtime):
166183
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")
167184

168185
self.builder.build(
169186
source_dir,
170187
self.artifacts_dir,
171188
self.scratch_dir,
172189
os.path.join(source_dir, "package.json"),
173-
runtime=self.runtime,
190+
runtime=runtime,
174191
dependencies_dir=self.dependencies_dir,
175192
download_dependencies=False,
176193
)
@@ -179,15 +196,16 @@ def test_builds_project_with_remote_dependencies_without_download_dependencies_w
179196
output_files = set(os.listdir(self.artifacts_dir))
180197
self.assertEqual(expected_files, output_files)
181198

182-
def test_builds_project_with_remote_dependencies_with_download_dependencies_and_dependencies_dir(self):
199+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
200+
def test_builds_project_with_remote_dependencies_with_download_dependencies_and_dependencies_dir(self, runtime):
183201
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")
184202

185203
self.builder.build(
186204
source_dir,
187205
self.artifacts_dir,
188206
self.scratch_dir,
189207
os.path.join(source_dir, "package.json"),
190-
runtime=self.runtime,
208+
runtime=runtime,
191209
dependencies_dir=self.dependencies_dir,
192210
download_dependencies=True,
193211
)
@@ -208,7 +226,10 @@ def test_builds_project_with_remote_dependencies_with_download_dependencies_and_
208226
output_dependencies_files = set(os.listdir(os.path.join(self.dependencies_dir)))
209227
self.assertNotIn(expected_dependencies_files, output_dependencies_files)
210228

211-
def test_builds_project_with_remote_dependencies_without_download_dependencies_without_dependencies_dir(self):
229+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
230+
def test_builds_project_with_remote_dependencies_without_download_dependencies_without_dependencies_dir(
231+
self, runtime
232+
):
212233
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")
213234

214235
with mock.patch.object(logger, "info") as mock_info:
@@ -217,7 +238,7 @@ def test_builds_project_with_remote_dependencies_without_download_dependencies_w
217238
self.artifacts_dir,
218239
self.scratch_dir,
219240
os.path.join(source_dir, "package.json"),
220-
runtime=self.runtime,
241+
runtime=runtime,
221242
dependencies_dir=None,
222243
download_dependencies=False,
223244
)
@@ -231,15 +252,16 @@ def test_builds_project_with_remote_dependencies_without_download_dependencies_w
231252
"artifacts directory. "
232253
)
233254

234-
def test_builds_project_without_combine_dependencies(self):
255+
@parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",)])
256+
def test_builds_project_without_combine_dependencies(self, runtime):
235257
source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")
236258

237259
self.builder.build(
238260
source_dir,
239261
self.artifacts_dir,
240262
self.scratch_dir,
241263
os.path.join(source_dir, "package.json"),
242-
runtime=self.runtime,
264+
runtime=runtime,
243265
dependencies_dir=self.dependencies_dir,
244266
download_dependencies=True,
245267
combine_dependencies=False,

0 commit comments

Comments
 (0)