@aws-cdk-testing/cli-integ 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/lib/aws.d.ts +8 -2
  2. package/lib/aws.js +22 -8
  3. package/lib/aws.ts +28 -10
  4. package/lib/cli/run-suite.js +2 -1
  5. package/lib/cli/run-suite.ts +1 -1
  6. package/lib/cli/stage-distribution.js +1 -1
  7. package/lib/cli/stage-distribution.ts +0 -5
  8. package/lib/github.js +1 -2
  9. package/lib/github.ts +1 -1
  10. package/lib/integ-test.d.ts +1 -0
  11. package/lib/integ-test.js +3 -2
  12. package/lib/integ-test.ts +4 -1
  13. package/lib/package-sources/release-source.js +1 -1
  14. package/lib/package-sources/release-source.ts +2 -1
  15. package/lib/package-sources/repo-source.d.ts +4 -4
  16. package/lib/package-sources/repo-source.js +5 -5
  17. package/lib/package-sources/repo-source.ts +6 -5
  18. package/lib/proxy.d.ts +13 -0
  19. package/lib/proxy.js +49 -0
  20. package/lib/proxy.ts +64 -0
  21. package/lib/with-aws.d.ts +3 -0
  22. package/lib/with-aws.js +54 -6
  23. package/lib/with-aws.ts +52 -5
  24. package/lib/with-cdk-app.d.ts +11 -0
  25. package/lib/with-cdk-app.js +63 -34
  26. package/lib/with-cdk-app.ts +75 -45
  27. package/lib/with-cli-lib.js +9 -5
  28. package/lib/with-cli-lib.ts +10 -4
  29. package/lib/with-sam.js +2 -1
  30. package/lib/with-sam.ts +1 -0
  31. package/package.json +4 -3
  32. package/resources/cdk-apps/app/app.js +34 -0
  33. package/resources/cli-regression-patches/v2.178.1/NOTES.md +2 -0
  34. package/resources/cli-regression-patches/v2.178.1/skip-tests.txt +1 -0
  35. package/resources/integ.jest.config.js +4 -1
  36. package/tests/cli-integ-tests/bootstrapping.integtest.js +1 -1
  37. package/tests/cli-integ-tests/bootstrapping.integtest.ts +0 -1
  38. package/tests/cli-integ-tests/cli.integtest.js +65 -37
  39. package/tests/cli-integ-tests/cli.integtest.ts +82 -49
  40. package/tests/cli-integ-tests/proxy.integtest.js +147 -0
  41. package/tests/cli-integ-tests/proxy.integtest.ts +167 -0
  42. package/tests/init-javascript/init-javascript.integtest.js +1 -1
  43. package/tests/init-javascript/init-javascript.integtest.ts +0 -1
  44. package/tests/init-typescript-app/init-typescript-app.integtest.js +2 -2
  45. package/tests/init-typescript-app/init-typescript-app.integtest.ts +1 -1
  46. package/bin/query-github.js +0 -54
  47. package/bin/run-suite.d.ts +0 -1
  48. package/bin/run-suite.js +0 -131
  49. package/bin/stage-distribution.d.ts +0 -1
  50. package/bin/stage-distribution.js +0 -217
  51. package/bin/test-root.d.ts +0 -1
  52. package/bin/test-root.js +0 -6
  53. /package/{bin/query-github.d.ts → tests/cli-integ-tests/proxy.integtest.d.ts} +0 -0
@@ -1,5 +1,4 @@
1
1
  import { existsSync, promises as fs } from 'fs';
2
- import * as querystring from 'node:querystring';
3
2
  import * as os from 'os';
4
3
  import * as path from 'path';
5
4
  import {
@@ -23,8 +22,6 @@ import { InvokeCommand } from '@aws-sdk/client-lambda';
23
22
  import { PutObjectLockConfigurationCommand } from '@aws-sdk/client-s3';
24
23
  import { CreateTopicCommand, DeleteTopicCommand } from '@aws-sdk/client-sns';
25
24
  import { AssumeRoleCommand, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
26
- import * as mockttp from 'mockttp';
27
- import { CompletedRequest } from 'mockttp';
28
25
  import {
29
26
  cloneDirectory,
30
27
  integTest,
@@ -41,6 +38,7 @@ import {
41
38
  withSamIntegrationFixture,
42
39
  withSpecificFixture,
43
40
  } from '../../lib';
41
+ import { awsActionsFromRequests, startProxyServer } from '../../lib/proxy';
44
42
 
45
43
  jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime
46
44
 
@@ -1264,7 +1262,6 @@ integTest(
1264
1262
  integTest(
1265
1263
  'cdk diff doesnt show resource metadata changes',
1266
1264
  withDefaultFixture(async (fixture) => {
1267
-
1268
1265
  // GIVEN - small initial stack with default resource metadata
1269
1266
  await fixture.cdkDeploy('metadata');
1270
1267
 
@@ -1284,7 +1281,6 @@ integTest(
1284
1281
  integTest(
1285
1282
  'cdk diff shows resource metadata changes with --no-change-set',
1286
1283
  withDefaultFixture(async (fixture) => {
1287
-
1288
1284
  // GIVEN - small initial stack with default resource metadata
1289
1285
  await fixture.cdkDeploy('metadata');
1290
1286
 
@@ -2256,6 +2252,73 @@ integTest(
2256
2252
  }),
2257
2253
  );
2258
2254
 
2255
+ /**
2256
+ * Create an S3 bucket, orphan that bucket, then import the bucket, with a NodeJSFunction lambda also in the stack.
2257
+ *
2258
+ * Validates fix for https://github.com/aws/aws-cdk/issues/31999 (import fails)
2259
+ */
2260
+ integTest(
2261
+ 'test resource import with construct that requires bundling',
2262
+ withDefaultFixture(async (fixture) => {
2263
+ // GIVEN
2264
+ const outputsFile = path.join(fixture.integTestDir, 'outputs', 'outputs.json');
2265
+ await fs.mkdir(path.dirname(outputsFile), { recursive: true });
2266
+
2267
+ // First, create a stack that includes a NodeJSFunction lambda and one bucket that will be removed from the stack but NOT deleted from AWS.
2268
+ await fixture.cdkDeploy('importable-stack', {
2269
+ modEnv: { INCLUDE_NODEJS_FUNCTION_LAMBDA: '1', INCLUDE_SINGLE_BUCKET: '1', RETAIN_SINGLE_BUCKET: '1' },
2270
+ options: ['--outputs-file', outputsFile],
2271
+ });
2272
+
2273
+ try {
2274
+ // Second, now the bucket we will remove is in the stack and has a logicalId. We can now make the resource mapping file.
2275
+ // This resource mapping file will be used to tell the import operation what bucket to bring into the stack.
2276
+ const fullStackName = fixture.fullStackName('importable-stack');
2277
+ const outputs = JSON.parse((await fs.readFile(outputsFile, { encoding: 'utf-8' })).toString());
2278
+ const bucketLogicalId = outputs[fullStackName].BucketLogicalId;
2279
+ const bucketName = outputs[fullStackName].BucketName;
2280
+ const bucketResourceMap = {
2281
+ [bucketLogicalId]: {
2282
+ BucketName: bucketName,
2283
+ },
2284
+ };
2285
+ const mappingFile = path.join(fixture.integTestDir, 'outputs', 'mapping.json');
2286
+ await fs.writeFile(mappingFile, JSON.stringify(bucketResourceMap), { encoding: 'utf-8' });
2287
+
2288
+ // Third, remove the bucket from the stack, but don't delete the bucket from AWS.
2289
+ await fixture.cdkDeploy('importable-stack', {
2290
+ modEnv: { INCLUDE_NODEJS_FUNCTION_LAMBDA: '1', INCLUDE_SINGLE_BUCKET: '0', RETAIN_SINGLE_BUCKET: '0' },
2291
+ });
2292
+ const cfnTemplateBeforeImport = await fixture.aws.cloudFormation.send(
2293
+ new GetTemplateCommand({ StackName: fullStackName }),
2294
+ );
2295
+ expect(cfnTemplateBeforeImport.TemplateBody).not.toContain(bucketLogicalId);
2296
+
2297
+ // WHEN
2298
+ await fixture.cdk(['import', '--resource-mapping', mappingFile, fixture.fullStackName('importable-stack')], {
2299
+ modEnv: { INCLUDE_NODEJS_FUNCTION_LAMBDA: '1', INCLUDE_SINGLE_BUCKET: '1', RETAIN_SINGLE_BUCKET: '0' },
2300
+ });
2301
+
2302
+ // THEN
2303
+ const describeStacksResponse = await fixture.aws.cloudFormation.send(
2304
+ new DescribeStacksCommand({ StackName: fullStackName }),
2305
+ );
2306
+ const cfnTemplateAfterImport = await fixture.aws.cloudFormation.send(
2307
+ new GetTemplateCommand({ StackName: fullStackName }),
2308
+ );
2309
+
2310
+ // If bundling is skipped during import for NodeJSFunction lambda, then the operation should fail and exit
2311
+ expect(describeStacksResponse.Stacks![0].StackStatus).toEqual('IMPORT_COMPLETE');
2312
+
2313
+ // If the import operation is successful, the template should contain the imported bucket
2314
+ expect(cfnTemplateAfterImport.TemplateBody).toContain(bucketLogicalId);
2315
+ } finally {
2316
+ // Clean up the resources we created
2317
+ await fixture.cdkDestroy('importable-stack');
2318
+ }
2319
+ }),
2320
+ );
2321
+
2259
2322
  /**
2260
2323
  * Create a queue, orphan that queue, then import the queue.
2261
2324
  *
@@ -2838,7 +2901,6 @@ integTest(
2838
2901
  );
2839
2902
 
2840
2903
  integTest('cdk notices are displayed correctly', withDefaultFixture(async (fixture) => {
2841
-
2842
2904
  const cache = {
2843
2905
  expiration: 4125963264000, // year 2100 so we never overwrite the cache
2844
2906
  notices: [
@@ -2872,65 +2934,36 @@ integTest('cdk notices are displayed correctly', withDefaultFixture(async (fixtu
2872
2934
 
2873
2935
  // assert dynamic environments are resolved
2874
2936
  expect(output).toContain(`AffectedEnvironments:<aws://${await fixture.aws.account()}/${fixture.aws.region}>`);
2875
-
2876
2937
  }));
2877
2938
 
2878
2939
  integTest('requests go through a proxy when configured',
2879
2940
  withDefaultFixture(async (fixture) => {
2880
- // Set up key and certificate
2881
- const { key, cert } = await mockttp.generateCACertificate();
2882
- const certDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-'));
2883
- const certPath = path.join(certDir, 'cert.pem');
2884
- const keyPath = path.join(certDir, 'key.pem');
2885
- await fs.writeFile(keyPath, key);
2886
- await fs.writeFile(certPath, cert);
2887
-
2888
- const proxyServer = mockttp.getLocal({
2889
- https: { keyPath, certPath },
2890
- });
2891
-
2892
- // We don't need to modify any request, so the proxy
2893
- // passes through all requests to the target host.
2894
- const endpoint = await proxyServer
2895
- .forAnyRequest()
2896
- .thenPassThrough();
2897
-
2898
- proxyServer.enableDebug();
2899
- await proxyServer.start();
2900
-
2901
- // The proxy is now ready to intercept requests
2902
-
2941
+ const proxyServer = await startProxyServer();
2903
2942
  try {
2943
+ // Delete notices cache if it exists
2944
+ await fs.rm(path.join(process.env.HOME ?? os.userInfo().homedir, '.cdk/cache/notices.json'), { force: true });
2945
+
2904
2946
  await fixture.cdkDeploy('test-2', {
2905
2947
  captureStderr: true,
2906
2948
  options: [
2907
2949
  '--proxy', proxyServer.url,
2908
- '--ca-bundle-path', certPath,
2950
+ '--ca-bundle-path', proxyServer.certPath,
2909
2951
  ],
2910
2952
  modEnv: {
2911
2953
  CDK_HOME: fixture.integTestDir,
2912
2954
  },
2913
2955
  });
2914
- } finally {
2915
- await fs.rm(certDir, { recursive: true, force: true });
2916
- await proxyServer.stop();
2917
- }
2918
2956
 
2919
- const requests = await endpoint.getSeenRequests();
2957
+ const requests = await proxyServer.getSeenRequests();
2920
2958
 
2921
- expect(requests.map(req => req.url))
2922
- .toContain('https://cli.cdk.dev-tools.aws.dev/notices.json');
2959
+ expect(requests.map(req => req.url))
2960
+ .toContain('https://cli.cdk.dev-tools.aws.dev/notices.json');
2923
2961
 
2924
- const actionsUsed = actions(requests);
2925
- expect(actionsUsed).toContain('AssumeRole');
2926
- expect(actionsUsed).toContain('CreateChangeSet');
2962
+ const actionsUsed = awsActionsFromRequests(requests);
2963
+ expect(actionsUsed).toContain('AssumeRole');
2964
+ expect(actionsUsed).toContain('CreateChangeSet');
2965
+ } finally {
2966
+ await proxyServer.stop();
2967
+ }
2927
2968
  }),
2928
2969
  );
2929
-
2930
- function actions(requests: CompletedRequest[]): string[] {
2931
- return [...new Set(requests
2932
- .map(req => req.body.buffer.toString('utf-8'))
2933
- .map(body => querystring.decode(body))
2934
- .map(x => x.Action as string)
2935
- .filter(action => action != null))];
2936
- }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const fs_1 = require("fs");
5
+ const os = require("os");
6
+ const path = require("path");
7
+ const integ_test_1 = require("../../lib/integ-test");
8
+ const proxy_1 = require("../../lib/proxy");
9
+ const with_cdk_app_1 = require("../../lib/with-cdk-app");
10
+ const docker = (_a = process.env.CDK_DOCKER) !== null && _a !== void 0 ? _a : 'docker';
11
+ (0, integ_test_1.integTest)('all calls from isolated container go through proxy', (0, with_cdk_app_1.withDefaultFixture)(async (fixture) => {
12
+ // Find the 'cdk' command and make sure it is mounted into the container
13
+ const cdkFullpath = (await fixture.shell(['which', 'cdk'])).trim();
14
+ let cdkTop = findMountableParent(cdkFullpath);
15
+ // Run a 'cdk deploy' inside the container
16
+ const commands = [
17
+ `env ${renderEnv(fixture.cdkShellEnv())} ${cdkFullpath} ${fixture.cdkDeployCommandLine('test-2').join(' ')} -v`,
18
+ ];
19
+ await runInIsolatedContainer(fixture, [cdkTop], commands);
20
+ }));
21
+ async function runInIsolatedContainer(fixture, pathsToMount, testCommands) {
22
+ pathsToMount.push(`${process.env.HOME}`, fixture.integTestDir);
23
+ // Resolve credential provider to an access key that we can pass into the container
24
+ const credentials = await fixture.aws.credentials();
25
+ const proxy = await (0, proxy_1.startProxyServer)(fixture.integTestDir);
26
+ try {
27
+ const proxyPort = proxy.port;
28
+ const setupCommands = [
29
+ 'apt-get update -qq',
30
+ 'apt-get install -qqy nodejs > /dev/null',
31
+ ...isolatedDockerCommands(proxyPort, proxy.certPath),
32
+ ];
33
+ const scriptName = path.join(fixture.integTestDir, 'script.sh');
34
+ // Write a script file
35
+ await fs_1.promises.writeFile(scriptName, [
36
+ '#!/bin/bash',
37
+ 'set -x',
38
+ 'set -eu',
39
+ ...setupCommands,
40
+ ...testCommands,
41
+ ].join('\n'), 'utf-8');
42
+ await fs_1.promises.chmod(scriptName, 0o755);
43
+ // Run commands in a Docker shell
44
+ await fixture.shell([
45
+ docker, 'run', '--net=bridge', '--rm',
46
+ ...pathsToMount.flatMap(p => ['-v', `${p}:${p}`]),
47
+ ...['HOME', 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN'].flatMap(e => ['-e', e]),
48
+ '-w', fixture.integTestDir,
49
+ '--cap-add=NET_ADMIN',
50
+ 'public.ecr.aws/ubuntu/ubuntu:24.04_stable',
51
+ `${scriptName}`,
52
+ ], {
53
+ stdio: 'inherit',
54
+ modEnv: {
55
+ AWS_ACCESS_KEY_ID: credentials.accessKeyId,
56
+ AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
57
+ AWS_SESSION_TOKEN: credentials.sessionToken,
58
+ },
59
+ });
60
+ }
61
+ finally {
62
+ await proxy.stop();
63
+ }
64
+ }
65
+ /**
66
+ * Return the commands necessary to isolate the inside of the container from the internet,
67
+ * except by going through the proxy
68
+ */
69
+ function isolatedDockerCommands(proxyPort, caBundlePath) {
70
+ let defaultBridgeIp = '172.17.0.1';
71
+ // The host's default IP is different on CodeBuild than it is on other Docker systems.
72
+ if (process.env.CODEBUILD_BUILD_ARN) {
73
+ defaultBridgeIp = '172.18.0.1';
74
+ }
75
+ return [
76
+ 'echo Working...',
77
+ 'apt-get install -qqy curl net-tools iputils-ping dnsutils iptables > /dev/null',
78
+ '',
79
+ // Looking up `host.docker.internal` is necessary on MacOS Finch and Docker Desktop
80
+ // on Mac. The magic IP address is necessary on CodeBuild and GitHub Actions.
81
+ //
82
+ // I tried `--add-host=host.docker.internal:host-gateway` on the Linuxes but
83
+ // it doesn't change anything on either GHA or CodeBuild, so we're left with this
84
+ // backup solution.
85
+ 'gateway=$(dig +short host.docker.internal)',
86
+ 'if [[ -z "$gateway" ]]; then',
87
+ ` gateway=${defaultBridgeIp}`,
88
+ 'fi',
89
+ '',
90
+ '# Some iptables manipulation; there might be unnecessary commands in here, not an expert',
91
+ 'iptables -F',
92
+ 'iptables -X',
93
+ 'iptables -P INPUT DROP',
94
+ 'iptables -P OUTPUT DROP',
95
+ 'iptables -P FORWARD DROP',
96
+ 'iptables -A INPUT -i lo -j ACCEPT',
97
+ 'iptables -A OUTPUT -o lo -j ACCEPT',
98
+ 'iptables -A OUTPUT -d $gateway -j ACCEPT',
99
+ 'iptables -A INPUT -s $gateway -j ACCEPT',
100
+ '',
101
+ '',
102
+ `if [[ ! -f ${caBundlePath} ]]; then`,
103
+ ` echo "Could not find ${caBundlePath}, this will probably not go well. Exiting." >&2`,
104
+ ' exit 1',
105
+ 'fi',
106
+ '',
107
+ '# Configure a bunch of tools to work with the proxy',
108
+ 'echo "+-------------------------------------------------------------------------------------+"',
109
+ 'echo "| Direct network traffic has been blocked, everything must go through the proxy. |"',
110
+ 'echo "+-------------------------------------------------------------------------------------+"',
111
+ `export HTTP_PROXY=http://$gateway:${proxyPort}/`,
112
+ `export HTTPS_PROXY=http://$gateway:${proxyPort}/`,
113
+ `export NODE_EXTRA_CA_CERTS=${caBundlePath}`,
114
+ `export AWS_CA_BUNDLE=${caBundlePath}`,
115
+ `export SSL_CERT_FILE=${caBundlePath}`,
116
+ 'echo "Acquire::http::proxy \"$HTTP_PROXY\";" >> /etc/apt/apt.conf.d/95proxies',
117
+ 'echo "Acquire::https::proxy \"$HTTPS_PROXY\";" >> /etc/apt/apt.conf.d/95proxies',
118
+ ];
119
+ }
120
+ function renderEnv(env) {
121
+ return Object.entries(env).filter(([_, v]) => v).map(([k, v]) => `${k}='${v}'`).join(' ');
122
+ }
123
+ /**
124
+ * Find a broadly mountable parent of the given directory
125
+ *
126
+ * We don't want to just mount the top-level directory, because
127
+ * it could end up being `/var` (top-level dir of tmpdir on Mac).
128
+ */
129
+ function findMountableParent(dir) {
130
+ const candidates = [
131
+ os.tmpdir(),
132
+ process.env.TMPDIR,
133
+ process.env.HOME,
134
+ ];
135
+ for (const cand of candidates) {
136
+ if (cand === undefined) {
137
+ continue;
138
+ }
139
+ if (dir.startsWith(cand)) {
140
+ const suffix = dir.substring(cand.length);
141
+ const firstChildDir = suffix.split('/')[0];
142
+ return path.join(cand, firstChildDir);
143
+ }
144
+ }
145
+ return dir;
146
+ }
147
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHkuaW50ZWd0ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicHJveHkuaW50ZWd0ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJCQUFvQztBQUNwQyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLHFEQUFpRDtBQUNqRCwyQ0FBbUQ7QUFDbkQseURBQXlFO0FBRXpFLE1BQU0sTUFBTSxHQUFHLE1BQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLG1DQUFJLFFBQVEsQ0FBQztBQUVsRCxJQUFBLHNCQUFTLEVBQ1Asb0RBQW9ELEVBQ3BELElBQUEsaUNBQWtCLEVBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQ25DLHdFQUF3RTtJQUN4RSxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbkUsSUFBSSxNQUFNLEdBQUcsbUJBQW1CLENBQUMsV0FBVyxDQUFDLENBQUM7SUFFOUMsMENBQTBDO0lBQzFDLE1BQU0sUUFBUSxHQUFHO1FBQ2YsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksV0FBVyxJQUFJLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUs7S0FDaEgsQ0FBQztJQUVGLE1BQU0sc0JBQXNCLENBQUMsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDNUQsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUVGLEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUFvQixFQUFFLFlBQXNCLEVBQUUsWUFBc0I7SUFDeEcsWUFBWSxDQUFDLElBQUksQ0FDZixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQ3JCLE9BQU8sQ0FBQyxZQUFZ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QyxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTNDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDeEMsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBpbnRlZ1Rlc3QgfSBmcm9tICcuLi8uLi9saWIvaW50ZWctdGVzdCc7XG5pbXBvcnQgeyBzdGFydFByb3h5U2VydmVyIH0gZnJvbSAnLi4vLi4vbGliL3Byb3h5JztcbmltcG9ydCB7IFRlc3RGaXh0dXJlLCB3aXRoRGVmYXVsdEZpeHR1cmUgfSBmcm9tICcuLi8uLi9saWIvd2l0aC1jZGstYXBwJztcblxuY29uc3QgZG9ja2VyID0gcHJvY2Vzcy5lbnYuQ0RLX0RPQ0tFUiA/PyAnZG9ja2VyJztcblxuaW50ZWdUZXN0KFxuICAnYWxsIGNhbGxzIGZyb20gaXNvbGF0ZWQgY29udGFpbmVyIGdvIHRocm91Z2ggcHJveHknLFxuICB3aXRoRGVmYXVsdEZpeHR1cmUoYXN5bmMgKGZpeHR1cmUpID0+IHtcbiAgICAvLyBGaW5kIHRoZSAnY2RrJyBjb21tYW5kIGFuZCBtYWtlIHN1cmUgaXQgaXMgbW91bnRlZCBpbnRvIHRoZSBjb250YWluZXJcbiAgICBjb25zdCBjZGtGdWxscGF0aCA9IChhd2FpdCBmaXh0dXJlLnNoZWxsKFsnd2hpY2gnLCAnY2RrJ10pKS50cmltKCk7XG4gICAgbGV0IGNka1RvcCA9IGZpbmRNb3VudGFibGVQYXJlbnQoY2RrRnVsbHBhdGgpO1xuXG4gICAgLy8gUnVuIGEgJ2NkayBkZXBsb3knIGluc2lkZSB0aGUgY29udGFpbmVyXG4gICAgY29uc3QgY29tbWFuZHMgPSBbXG4gICAgICBgZW52ICR7cmVuZGVyRW52KGZpeHR1cmUuY2RrU2hlbGxFbnYoKSl9ICR7Y2RrRnVsbHBhdGh9ICR7Zml4dHVyZS5jZGtEZXBsb3lDb21tYW5kTGluZSgndGVzdC0yJykuam9pbignICcpfSAtdmAsXG4gICAgXTtcblxuICAgIGF3YWl0IHJ1bkluSXNvbGF0ZWRDb250YWluZXIoZml4dHVyZSwgW2Nka1RvcF0sIGNvbW1hbmRzKTtcbiAgfSksXG4pO1xuXG5hc3luYyBmdW5jdGlvbiBydW5Jbklzb2xhdGVkQ29udGFpbmVyKGZpeHR1cmU6IFRlc3RGaXh0dXJlLCBwYXRoc1RvTW91bnQ6IHN0cmluZ1tdLCB0ZXN0Q29tbWFuZHM6IHN0cmluZ1tdKSB7XG4gIHBhdGhzVG9Nb3VudC5wdXNoKFxuICAgIGAke3Byb2Nlc3MuZW52LkhPTUV9YCxcbiAgICBmaXh0dXJlLmludGVnVGVzdERpcixcbiAgKTtcblxuICAvLyBSZXNvbHZlIGNyZWRlbnRpYWwgcHJvdmlkZXIgdG8gYW4gYWNjZXNzIGtleSB0aGF0IHdlIGNhbiBwYXNzIGludG8gdGhlIGNvbnRhaW5lclxuICBjb25zdCBjcmVkZW50aWFscyA9IGF3YWl0IGZpeHR1cmUuYXdzLmNyZWRlbnRpYWxzKCk7XG5cbiAgY29uc3QgcHJveHkgPSBhd2FpdCBzdGFydFByb3h5U2VydmVyKGZpeHR1cmUuaW50ZWdUZXN0RGlyKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcm94eVBvcnQgPSBwcm94eS5wb3J0O1xuXG4gICAgY29uc3Qgc2V0dXBDb21tYW5kcyA9IFtcbiAgICAgICdhcHQtZ2V0IHVwZGF0ZSAtcXEnLFxuICAgICAgJ2FwdC1nZXQgaW5zdGFsbCAtcXF5IG5vZGVqcyA+IC9kZXYvbnVsbCcsXG4gICAgICAuLi5pc29sYXRlZERvY2tlckNvbW1hbmRzKHByb3h5UG9ydCwgcHJveHkuY2VydFBhdGgpLFxuICAgIF07XG5cbiAgICBjb25zdCBzY3JpcHROYW1lID0gcGF0aC5qb2luKGZpeHR1cmUuaW50ZWdUZXN0RGlyLCAnc2NyaXB0LnNoJyk7XG5cbiAgICAvLyBXcml0ZSBhIHNjcmlwdCBmaWxlXG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHNjcmlwdE5hbWUsIFtcbiAgICAgICcjIS9iaW4vYmFzaCcsXG4gICAgICAnc2V0IC14JyxcbiAgICAgICdzZXQgLWV1JyxcbiAgICAgIC4uLnNldHVwQ29tbWFuZHMsXG4gICAgICAuLi50ZXN0Q29tbWFuZHMsXG4gICAgXS5qb2luKCdcXG4nKSwgJ3V0Zi04Jyk7XG5cbiAgICBhd2FpdCBmcy5jaG1vZChzY3JpcHROYW1lLCAwbzc1NSk7XG5cbiAgICAvLyBSdW4gY29tbWFuZHMgaW4gYSBEb2NrZXIgc2hlbGxcbiAgICBhd2FpdCBmaXh0dXJlLnNoZWxsKFtcbiAgICAgIGRvY2tlciwgJ3J1bicsICctLW5ldD1icmlkZ2UnLCAnLS1ybScsXG4gICAgICAuLi5wYXRoc1RvTW91bnQuZmxhdE1hcChwID0+IFsnLXYnLCBgJHtwfToke3B9YF0pLFxuICAgICAgLi4uWydIT01FJywgJ0FXU19BQ0NFU1NfS0VZX0lEJywgJ0FXU19TRUNSRVRfQUNDRVNTX0tFWScsICdBV1NfU0VTU0lPTl9UT0tFTiddLmZsYXRNYXAoZSA9PiBbJy1lJywgZV0pLFxuICAgICAgJy13JywgZml4dHVyZS5pbnRlZ1Rlc3REaXIsXG4gICAgICAnLS1jYXAtYWRkPU5FVF9BRE1JTicsXG4gICAgICAncHVibGljLmVjci5hd3MvdWJ1bnR1L3VidW50dToyNC4wNF9zdGFibGUnLFxuICAgICAgYCR7c2NyaXB0TmFtZX1gLFxuICAgIF0sIHtcbiAgICAgIHN0ZGlvOiAnaW5oZXJpdCcsXG4gICAgICBtb2RFbnY6IHtcbiAgICAgICAgQVdTX0FDQ0VTU19LRVlfSUQ6IGNyZWRlbnRpYWxzLmFjY2Vzc0tleUlkLFxuICAgICAgICBBV1NfU0VDUkVUX0FDQ0VTU19LRVk6IGNyZWRlbnRpYWxzLnNlY3JldEFjY2Vzc0tleSxcbiAgICAgICAgQVdTX1NFU1NJT05fVE9LRU46IGNyZWRlbnRpYWxzLnNlc3Npb25Ub2tlbixcbiAgICAgIH0sXG4gICAgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgcHJveHkuc3RvcCgpO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJuIHRoZSBjb21tYW5kcyBuZWNlc3NhcnkgdG8gaXNvbGF0ZSB0aGUgaW5zaWRlIG9mIHRoZSBjb250YWluZXIgZnJvbSB0aGUgaW50ZXJuZXQsXG4gKiBleGNlcHQgYnkgZ29pbmcgdGhyb3VnaCB0aGUgcHJveHlcbiAqL1xuZnVuY3Rpb24gaXNvbGF0ZWREb2NrZXJDb21tYW5kcyhwcm94eVBvcnQ6IG51bWJlciwgY2FCdW5kbGVQYXRoOiBzdHJpbmcpIHtcbiAgbGV0IGRlZmF1bHRCcmlkZ2VJcCA9ICcxNzIuMTcuMC4xJztcblxuICAvLyBUaGUgaG9zdCdzIGRlZmF1bHQgSVAgaXMgZGlmZmVyZW50IG9uIENvZGVCdWlsZCB0aGFuIGl0IGlzIG9uIG90aGVyIERvY2tlciBzeXN0ZW1zLlxuICBpZiAocHJvY2Vzcy5lbnYuQ09ERUJVSUxEX0JVSUxEX0FSTikge1xuICAgIGRlZmF1bHRCcmlkZ2VJcCA9ICcxNzIuMTguMC4xJztcbiAgfVxuXG4gIHJldHVybiBbXG4gICAgJ2VjaG8gV29ya2luZy4uLicsXG4gICAgJ2FwdC1nZXQgaW5zdGFsbCAtcXF5IGN1cmwgbmV0LXRvb2xzIGlwdXRpbHMtcGluZyBkbnN1dGlscyBpcHRhYmxlcyA+IC9kZXYvbnVsbCcsXG4gICAgJycsXG4gICAgLy8gTG9va2luZyB1cCBgaG9zdC5kb2NrZXIuaW50ZXJuYWxgIGlzIG5lY2Vzc2FyeSBvbiBNYWNPUyBGaW5jaCBhbmQgRG9ja2VyIERlc2t0b3BcbiAgICAvLyBvbiBNYWMuIFRoZSBtYWdpYyBJUCBhZGRyZXNzIGlzIG5lY2Vzc2FyeSBvbiBDb2RlQnVpbGQgYW5kIEdpdEh1YiBBY3Rpb25zLlxuICAgIC8vXG4gICAgLy8gSSB0cmllZCBgLS1hZGQtaG9zdD1ob3N0LmRvY2tlci5pbnRlcm5hbDpob3N0LWdhdGV3YXlgIG9uIHRoZSBMaW51eGVzIGJ1dFxuICAgIC8vIGl0IGRvZXNuJ3QgY2hhbmdlIGFueXRoaW5nIG9uIGVpdGhlciBHSEEgb3IgQ29kZUJ1aWxkLCBzbyB3ZSdyZSBsZWZ0IHdpdGggdGhpc1xuICAgIC8vIGJhY2t1cCBzb2x1dGlvbi5cbiAgICAnZ2F0ZXdheT0kKGRpZyArc2hvcnQgaG9zdC5kb2NrZXIuaW50ZXJuYWwpJyxcbiAgICAnaWYgW1sgLXogXCIkZ2F0ZXdheVwiIF1dOyB0aGVuJyxcbiAgICBgICBnYXRld2F5PSR7ZGVmYXVsdEJyaWRnZUlwfWAsXG4gICAgJ2ZpJyxcbiAgICAnJyxcbiAgICAnIyBTb21lIGlwdGFibGVzIG1hbmlwdWxhdGlvbjsgdGhlcmUgbWlnaHQgYmUgdW5uZWNlc3NhcnkgY29tbWFuZHMgaW4gaGVyZSwgbm90IGFuIGV4cGVydCcsXG4gICAgJ2lwdGFibGVzIC1GJyxcbiAgICAnaXB0YWJsZXMgLVgnLFxuICAgICdpcHRhYmxlcyAtUCBJTlBVVCBEUk9QJyxcbiAgICAnaXB0YWJsZXMgLVAgT1VUUFVUIERST1AnLFxuICAgICdpcHRhYmxlcyAtUCBGT1JXQVJEIERST1AnLFxuICAgICdpcHRhYmxlcyAtQSBJTlBVVCAtaSBsbyAtaiBBQ0NFUFQnLFxuICAgICdpcHRhYmxlcyAtQSBPVVRQVVQgLW8gbG8gLWogQUNDRVBUJyxcbiAgICAnaXB0YWJsZXMgLUEgT1VUUFVUIC1kICRnYXRld2F5IC1qIEFDQ0VQVCcsXG4gICAgJ2lwdGFibGVzIC1BIElOUFVUIC1zICRnYXRld2F5IC1qIEFDQ0VQVCcsXG4gICAgJycsXG4gICAgJycsXG4gICAgYGlmIFtbICEgLWYgJHtjYUJ1bmRsZVBhdGh9IF1dOyB0aGVuYCxcbiAgICBgICAgIGVjaG8gXCJDb3VsZCBub3QgZmluZCAke2NhQnVuZGxlUGF0aH0sIHRoaXMgd2lsbCBwcm9iYWJseSBub3QgZ28gd2VsbC4gRXhpdGluZy5cIiA+JjJgLFxuICAgICcgICAgZXhpdCAxJyxcbiAgICAnZmknLFxuICAgICcnLFxuICAgICcjIENvbmZpZ3VyZSBhIGJ1bmNoIG9mIHRvb2xzIHRvIHdvcmsgd2l0aCB0aGUgcHJveHknLFxuICAgICdlY2hvIFwiKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXCInLFxuICAgICdlY2hvIFwifCAgRGlyZWN0IG5ldHdvcmsgdHJhZmZpYyBoYXMgYmVlbiBibG9ja2VkLCBldmVyeXRoaW5nIG11c3QgZ28gdGhyb3VnaCB0aGUgcHJveHkuICAgICB8XCInLFxuICAgICdlY2hvIFwiKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXCInLFxuICAgIGBleHBvcnQgSFRUUF9QUk9YWT1odHRwOi8vJGdhdGV3YXk6JHtwcm94eVBvcnR9L2AsXG4gICAgYGV4cG9ydCBIVFRQU19QUk9YWT1odHRwOi8vJGdhdGV3YXk6JHtwcm94eVBvcnR9L2AsXG4gICAgYGV4cG9ydCBOT0RFX0VYVFJBX0NBX0NFUlRTPSR7Y2FCdW5kbGVQYXRofWAsXG4gICAgYGV4cG9ydCBBV1NfQ0FfQlVORExFPSR7Y2FCdW5kbGVQYXRofWAsXG4gICAgYGV4cG9ydCBTU0xfQ0VSVF9GSUxFPSR7Y2FCdW5kbGVQYXRofWAsXG4gICAgJ2VjaG8gXCJBY3F1aXJlOjpodHRwOjpwcm94eSBcXFwiJEhUVFBfUFJPWFlcXFwiO1wiID4+IC9ldGMvYXB0L2FwdC5jb25mLmQvOTVwcm94aWVzJyxcbiAgICAnZWNobyBcIkFjcXVpcmU6Omh0dHBzOjpwcm94eSBcXFwiJEhUVFBTX1BST1hZXFxcIjtcIiA+PiAvZXRjL2FwdC9hcHQuY29uZi5kLzk1cHJveGllcycsXG4gIF07XG59XG5cbmZ1bmN0aW9uIHJlbmRlckVudihlbnY6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4pIHtcbiAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGVudikuZmlsdGVyKChbXywgdl0pID0+IHYpLm1hcCgoW2ssIHZdKSA9PiBgJHtrfT0nJHt2fSdgKS5qb2luKCcgJyk7XG59XG5cbi8qKlxuICogRmluZCBhIGJyb2FkbHkgbW91bnRhYmxlIHBhcmVudCBvZiB0aGUgZ2l2ZW4gZGlyZWN0b3J5XG4gKlxuICogV2UgZG9uJ3Qgd2FudCB0byBqdXN0IG1vdW50IHRoZSB0b3AtbGV2ZWwgZGlyZWN0b3J5LCBiZWNhdXNlXG4gKiBpdCBjb3VsZCBlbmQgdXAgYmVpbmcgYC92YXJgICh0b3AtbGV2ZWwgZGlyIG9mIHRtcGRpciBvbiBNYWMpLlxuICovXG5mdW5jdGlvbiBmaW5kTW91bnRhYmxlUGFyZW50KGRpcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY2FuZGlkYXRlcyA9IFtcbiAgICBvcy50bXBkaXIoKSxcbiAgICBwcm9jZXNzLmVudi5UTVBESVIsXG4gICAgcHJvY2Vzcy5lbnYuSE9NRSxcbiAgXTtcbiAgZm9yIChjb25zdCBjYW5kIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICBpZiAoY2FuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZGlyLnN0YXJ0c1dpdGgoY2FuZCkpIHtcbiAgICAgIGNvbnN0IHN1ZmZpeCA9IGRpci5zdWJzdHJpbmcoY2FuZC5sZW5ndGgpO1xuICAgICAgY29uc3QgZmlyc3RDaGlsZERpciA9IHN1ZmZpeC5zcGxpdCgnLycpWzBdO1xuXG4gICAgICByZXR1cm4gcGF0aC5qb2luKGNhbmQsIGZpcnN0Q2hpbGREaXIpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZGlyO1xufVxuIl19
@@ -0,0 +1,167 @@
1
+ import { promises as fs } from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { integTest } from '../../lib/integ-test';
5
+ import { startProxyServer } from '../../lib/proxy';
6
+ import { TestFixture, withDefaultFixture } from '../../lib/with-cdk-app';
7
+
8
+ const docker = process.env.CDK_DOCKER ?? 'docker';
9
+
10
+ integTest(
11
+ 'all calls from isolated container go through proxy',
12
+ withDefaultFixture(async (fixture) => {
13
+ // Find the 'cdk' command and make sure it is mounted into the container
14
+ const cdkFullpath = (await fixture.shell(['which', 'cdk'])).trim();
15
+ let cdkTop = findMountableParent(cdkFullpath);
16
+
17
+ // Run a 'cdk deploy' inside the container
18
+ const commands = [
19
+ `env ${renderEnv(fixture.cdkShellEnv())} ${cdkFullpath} ${fixture.cdkDeployCommandLine('test-2').join(' ')} -v`,
20
+ ];
21
+
22
+ await runInIsolatedContainer(fixture, [cdkTop], commands);
23
+ }),
24
+ );
25
+
26
+ async function runInIsolatedContainer(fixture: TestFixture, pathsToMount: string[], testCommands: string[]) {
27
+ pathsToMount.push(
28
+ `${process.env.HOME}`,
29
+ fixture.integTestDir,
30
+ );
31
+
32
+ // Resolve credential provider to an access key that we can pass into the container
33
+ const credentials = await fixture.aws.credentials();
34
+
35
+ const proxy = await startProxyServer(fixture.integTestDir);
36
+ try {
37
+ const proxyPort = proxy.port;
38
+
39
+ const setupCommands = [
40
+ 'apt-get update -qq',
41
+ 'apt-get install -qqy nodejs > /dev/null',
42
+ ...isolatedDockerCommands(proxyPort, proxy.certPath),
43
+ ];
44
+
45
+ const scriptName = path.join(fixture.integTestDir, 'script.sh');
46
+
47
+ // Write a script file
48
+ await fs.writeFile(scriptName, [
49
+ '#!/bin/bash',
50
+ 'set -x',
51
+ 'set -eu',
52
+ ...setupCommands,
53
+ ...testCommands,
54
+ ].join('\n'), 'utf-8');
55
+
56
+ await fs.chmod(scriptName, 0o755);
57
+
58
+ // Run commands in a Docker shell
59
+ await fixture.shell([
60
+ docker, 'run', '--net=bridge', '--rm',
61
+ ...pathsToMount.flatMap(p => ['-v', `${p}:${p}`]),
62
+ ...['HOME', 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN'].flatMap(e => ['-e', e]),
63
+ '-w', fixture.integTestDir,
64
+ '--cap-add=NET_ADMIN',
65
+ 'public.ecr.aws/ubuntu/ubuntu:24.04_stable',
66
+ `${scriptName}`,
67
+ ], {
68
+ stdio: 'inherit',
69
+ modEnv: {
70
+ AWS_ACCESS_KEY_ID: credentials.accessKeyId,
71
+ AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
72
+ AWS_SESSION_TOKEN: credentials.sessionToken,
73
+ },
74
+ });
75
+ } finally {
76
+ await proxy.stop();
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Return the commands necessary to isolate the inside of the container from the internet,
82
+ * except by going through the proxy
83
+ */
84
+ function isolatedDockerCommands(proxyPort: number, caBundlePath: string) {
85
+ let defaultBridgeIp = '172.17.0.1';
86
+
87
+ // The host's default IP is different on CodeBuild than it is on other Docker systems.
88
+ if (process.env.CODEBUILD_BUILD_ARN) {
89
+ defaultBridgeIp = '172.18.0.1';
90
+ }
91
+
92
+ return [
93
+ 'echo Working...',
94
+ 'apt-get install -qqy curl net-tools iputils-ping dnsutils iptables > /dev/null',
95
+ '',
96
+ // Looking up `host.docker.internal` is necessary on MacOS Finch and Docker Desktop
97
+ // on Mac. The magic IP address is necessary on CodeBuild and GitHub Actions.
98
+ //
99
+ // I tried `--add-host=host.docker.internal:host-gateway` on the Linuxes but
100
+ // it doesn't change anything on either GHA or CodeBuild, so we're left with this
101
+ // backup solution.
102
+ 'gateway=$(dig +short host.docker.internal)',
103
+ 'if [[ -z "$gateway" ]]; then',
104
+ ` gateway=${defaultBridgeIp}`,
105
+ 'fi',
106
+ '',
107
+ '# Some iptables manipulation; there might be unnecessary commands in here, not an expert',
108
+ 'iptables -F',
109
+ 'iptables -X',
110
+ 'iptables -P INPUT DROP',
111
+ 'iptables -P OUTPUT DROP',
112
+ 'iptables -P FORWARD DROP',
113
+ 'iptables -A INPUT -i lo -j ACCEPT',
114
+ 'iptables -A OUTPUT -o lo -j ACCEPT',
115
+ 'iptables -A OUTPUT -d $gateway -j ACCEPT',
116
+ 'iptables -A INPUT -s $gateway -j ACCEPT',
117
+ '',
118
+ '',
119
+ `if [[ ! -f ${caBundlePath} ]]; then`,
120
+ ` echo "Could not find ${caBundlePath}, this will probably not go well. Exiting." >&2`,
121
+ ' exit 1',
122
+ 'fi',
123
+ '',
124
+ '# Configure a bunch of tools to work with the proxy',
125
+ 'echo "+-------------------------------------------------------------------------------------+"',
126
+ 'echo "| Direct network traffic has been blocked, everything must go through the proxy. |"',
127
+ 'echo "+-------------------------------------------------------------------------------------+"',
128
+ `export HTTP_PROXY=http://$gateway:${proxyPort}/`,
129
+ `export HTTPS_PROXY=http://$gateway:${proxyPort}/`,
130
+ `export NODE_EXTRA_CA_CERTS=${caBundlePath}`,
131
+ `export AWS_CA_BUNDLE=${caBundlePath}`,
132
+ `export SSL_CERT_FILE=${caBundlePath}`,
133
+ 'echo "Acquire::http::proxy \"$HTTP_PROXY\";" >> /etc/apt/apt.conf.d/95proxies',
134
+ 'echo "Acquire::https::proxy \"$HTTPS_PROXY\";" >> /etc/apt/apt.conf.d/95proxies',
135
+ ];
136
+ }
137
+
138
+ function renderEnv(env: Record<string, string | undefined>) {
139
+ return Object.entries(env).filter(([_, v]) => v).map(([k, v]) => `${k}='${v}'`).join(' ');
140
+ }
141
+
142
+ /**
143
+ * Find a broadly mountable parent of the given directory
144
+ *
145
+ * We don't want to just mount the top-level directory, because
146
+ * it could end up being `/var` (top-level dir of tmpdir on Mac).
147
+ */
148
+ function findMountableParent(dir: string): string {
149
+ const candidates = [
150
+ os.tmpdir(),
151
+ process.env.TMPDIR,
152
+ process.env.HOME,
153
+ ];
154
+ for (const cand of candidates) {
155
+ if (cand === undefined) {
156
+ continue;
157
+ }
158
+
159
+ if (dir.startsWith(cand)) {
160
+ const suffix = dir.substring(cand.length);
161
+ const firstChildDir = suffix.split('/')[0];
162
+
163
+ return path.join(cand, firstChildDir);
164
+ }
165
+ }
166
+ return dir;
167
+ }
@@ -50,4 +50,4 @@ new TestjsStack(app, 'TestjsStack');
50
50
  await fs.writeJson(path.join(context.integTestDir, 'cdk.json'), cdkJson);
51
51
  await shell.shell(['cdk', 'synth']);
52
52
  })));
53
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC1qYXZhc2NyaXB0LmludGVndGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluaXQtamF2YXNjcmlwdC5pbnRlZ3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBNkI7QUFDN0IsK0JBQStCO0FBQy9CLG1DQUF5RjtBQUV6RixDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7SUFDdkMsSUFBQSxlQUFTLEVBQUMsbUJBQW1CLFFBQVEsRUFBRSxFQUFFLElBQUEsNEJBQXNCLEVBQUMsSUFBQSxrQkFBWSxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUM3RixNQUFNLEtBQUssR0FBRyxpQkFBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUUxQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNqRSxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG9EQUFvRDtRQUN0RixNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFMUMsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDdEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFBLGVBQVMsRUFBQyw2QkFBNkIsRUFBRSxJQUFBLDRCQUFzQixFQUFDLElBQUEsa0JBQVksRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDN0YsdUVBQXVFO0lBQ3ZFLE1BQU0sS0FBSyxHQUFHLGlCQUFXLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLE1BQU0sT0FBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBRTFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBRTlELHFCQUFxQjtJQUNyQixNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLG9CQUFvQixDQUFDLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBdUIzRSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFFeEIsMkNBQTJDO0lBQzNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUMvRSxPQUFPLENBQUMsR0FBRyxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFekUsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFFdEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IGludGVnVGVzdCwgd2l0aFRlbXBvcmFyeURpcmVjdG9yeSwgU2hlbGxIZWxwZXIsIHdpdGhQYWNrYWdlcyB9IGZyb20gJy4uLy4uL2xpYic7XG5cblsnYXBwJywgJ3NhbXBsZS1hcHAnXS5mb3JFYWNoKHRlbXBsYXRlID0+IHtcbiAgaW50ZWdUZXN0KGBpbml0IGphdmFzY3JpcHQgJHt0ZW1wbGF0ZX1gLCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5KHdpdGhQYWNrYWdlcyhhc3luYyAoY29udGV4dCkgPT4ge1xuICAgIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gICAgYXdhaXQgY29udGV4dC5wYWNrYWdlcy5tYWtlQ2xpQXZhaWxhYmxlKCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ2NkaycsICdpbml0JywgJy1sJywgJ2phdmFzY3JpcHQnLCB0ZW1wbGF0ZV0pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ3BydW5lJ10pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2xzJ10pOyAvLyB0aGlzIHdpbGwgZmFpbCBpZiB3ZSBoYXZlIHVubWV0IHBlZXIgZGVwZW5kZW5jaWVzXG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAncnVuJywgJ3Rlc3QnXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ2NkaycsICdzeW50aCddKTtcbiAgfSkpKTtcbn0pO1xuXG5pbnRlZ1Rlc3QoJ1Rlc3QgaW1wb3J0aW5nIENESyBmcm9tIEVTTScsIHdpdGhUZW1wb3JhcnlEaXJlY3Rvcnkod2l0aFBhY2thZ2VzKGFzeW5jIChjb250ZXh0KSA9PiB7XG4gIC8vIFVzZSAnY2RrIGluaXQgLWw9amF2YXNjcmlwdCcgdG8gZ2V0IHNldCB1cCwgYnV0IHVzZSBhIGRpZmZlcmVudCBmaWxlXG4gIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gIGF3YWl0IGNvbnRleHQucGFja2FnZXMubWFrZUNsaUF2YWlsYWJsZSgpO1xuXG4gIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAnamF2YXNjcmlwdCcsICdhcHAnXSk7XG5cbiAgLy8gUmV3cml0ZSBzb21lIGZpbGVzXG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICduZXctZW50cnlwb2ludC5tanMnKSwgYFxuLy8gVGVzdCBtdWx0aXBsZSBzdHlsZXMgb2YgaW1wb3J0c1xuaW1wb3J0IHsgU3RhY2ssIGF3c19zbnMgYXMgc25zIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgU3FzU3Vic2NyaXB0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNucy1zdWJzY3JpcHRpb25zJztcbmltcG9ydCAqIGFzIHNxcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3FzJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5cbmNsYXNzIFRlc3Rqc1N0YWNrIGV4dGVuZHMgU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZSwgaWQsIHByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBjb25zdCBxdWV1ZSA9IG5ldyBzcXMuUXVldWUodGhpcywgJ1Rlc3Rqc1F1ZXVlJywge1xuICAgICAgdmlzaWJpbGl0eVRpbWVvdXQ6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDMwMClcbiAgICB9KTtcblxuICAgIGNvbnN0IHRvcGljID0gbmV3IHNucy5Ub3BpYyh0aGlzLCAnVGVzdGpzVG9waWMnKTtcblxuICAgIHRvcGljLmFkZFN1YnNjcmlwdGlvbihuZXcgU3FzU3Vic2NyaXB0aW9uKHF1ZXVlKSk7XG4gIH1cbn1cblxuY29uc3QgYXBwID0gbmV3IGNkay5BcHAoKTtcbm5ldyBUZXN0anNTdGFjayhhcHAsICdUZXN0anNTdGFjaycpO1xuYCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KTtcblxuICAvLyBSZXdyaXRlICdjZGsuanNvbicgdG8gdXNlIG5ldyBlbnRyeXBvaW50XG4gIGNvbnN0IGNka0pzb24gPSBhd2FpdCBmcy5yZWFkSnNvbihwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICdjZGsuanNvbicpKTtcbiAgY2RrSnNvbi5hcHAgPSAnbm9kZSBuZXctZW50cnlwb2ludC5tanMnO1xuICBhd2FpdCBmcy53cml0ZUpzb24ocGF0aC5qb2luKGNvbnRleHQuaW50ZWdUZXN0RGlyLCAnY2RrLmpzb24nKSwgY2RrSnNvbik7XG5cbiAgYXdhaXQgc2hlbGwuc2hlbGwoWydjZGsnLCAnc3ludGgnXSk7XG5cbn0pKSk7XG4iXX0=
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC1qYXZhc2NyaXB0LmludGVndGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluaXQtamF2YXNjcmlwdC5pbnRlZ3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBNkI7QUFDN0IsK0JBQStCO0FBQy9CLG1DQUF5RjtBQUV6RixDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7SUFDdkMsSUFBQSxlQUFTLEVBQUMsbUJBQW1CLFFBQVEsRUFBRSxFQUFFLElBQUEsNEJBQXNCLEVBQUMsSUFBQSxrQkFBWSxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUM3RixNQUFNLEtBQUssR0FBRyxpQkFBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUUxQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNqRSxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG9EQUFvRDtRQUN0RixNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFMUMsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDdEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFBLGVBQVMsRUFBQyw2QkFBNkIsRUFBRSxJQUFBLDRCQUFzQixFQUFDLElBQUEsa0JBQVksRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDN0YsdUVBQXVFO0lBQ3ZFLE1BQU0sS0FBSyxHQUFHLGlCQUFXLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLE1BQU0sT0FBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBRTFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBRTlELHFCQUFxQjtJQUNyQixNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLG9CQUFvQixDQUFDLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBdUIzRSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFFeEIsMkNBQTJDO0lBQzNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUMvRSxPQUFPLENBQUMsR0FBRyxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFekUsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IGludGVnVGVzdCwgd2l0aFRlbXBvcmFyeURpcmVjdG9yeSwgU2hlbGxIZWxwZXIsIHdpdGhQYWNrYWdlcyB9IGZyb20gJy4uLy4uL2xpYic7XG5cblsnYXBwJywgJ3NhbXBsZS1hcHAnXS5mb3JFYWNoKHRlbXBsYXRlID0+IHtcbiAgaW50ZWdUZXN0KGBpbml0IGphdmFzY3JpcHQgJHt0ZW1wbGF0ZX1gLCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5KHdpdGhQYWNrYWdlcyhhc3luYyAoY29udGV4dCkgPT4ge1xuICAgIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gICAgYXdhaXQgY29udGV4dC5wYWNrYWdlcy5tYWtlQ2xpQXZhaWxhYmxlKCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ2NkaycsICdpbml0JywgJy1sJywgJ2phdmFzY3JpcHQnLCB0ZW1wbGF0ZV0pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ3BydW5lJ10pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2xzJ10pOyAvLyB0aGlzIHdpbGwgZmFpbCBpZiB3ZSBoYXZlIHVubWV0IHBlZXIgZGVwZW5kZW5jaWVzXG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAncnVuJywgJ3Rlc3QnXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ2NkaycsICdzeW50aCddKTtcbiAgfSkpKTtcbn0pO1xuXG5pbnRlZ1Rlc3QoJ1Rlc3QgaW1wb3J0aW5nIENESyBmcm9tIEVTTScsIHdpdGhUZW1wb3JhcnlEaXJlY3Rvcnkod2l0aFBhY2thZ2VzKGFzeW5jIChjb250ZXh0KSA9PiB7XG4gIC8vIFVzZSAnY2RrIGluaXQgLWw9amF2YXNjcmlwdCcgdG8gZ2V0IHNldCB1cCwgYnV0IHVzZSBhIGRpZmZlcmVudCBmaWxlXG4gIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gIGF3YWl0IGNvbnRleHQucGFja2FnZXMubWFrZUNsaUF2YWlsYWJsZSgpO1xuXG4gIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAnamF2YXNjcmlwdCcsICdhcHAnXSk7XG5cbiAgLy8gUmV3cml0ZSBzb21lIGZpbGVzXG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICduZXctZW50cnlwb2ludC5tanMnKSwgYFxuLy8gVGVzdCBtdWx0aXBsZSBzdHlsZXMgb2YgaW1wb3J0c1xuaW1wb3J0IHsgU3RhY2ssIGF3c19zbnMgYXMgc25zIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgU3FzU3Vic2NyaXB0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNucy1zdWJzY3JpcHRpb25zJztcbmltcG9ydCAqIGFzIHNxcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3FzJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5cbmNsYXNzIFRlc3Rqc1N0YWNrIGV4dGVuZHMgU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZSwgaWQsIHByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBjb25zdCBxdWV1ZSA9IG5ldyBzcXMuUXVldWUodGhpcywgJ1Rlc3Rqc1F1ZXVlJywge1xuICAgICAgdmlzaWJpbGl0eVRpbWVvdXQ6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDMwMClcbiAgICB9KTtcblxuICAgIGNvbnN0IHRvcGljID0gbmV3IHNucy5Ub3BpYyh0aGlzLCAnVGVzdGpzVG9waWMnKTtcblxuICAgIHRvcGljLmFkZFN1YnNjcmlwdGlvbihuZXcgU3FzU3Vic2NyaXB0aW9uKHF1ZXVlKSk7XG4gIH1cbn1cblxuY29uc3QgYXBwID0gbmV3IGNkay5BcHAoKTtcbm5ldyBUZXN0anNTdGFjayhhcHAsICdUZXN0anNTdGFjaycpO1xuYCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KTtcblxuICAvLyBSZXdyaXRlICdjZGsuanNvbicgdG8gdXNlIG5ldyBlbnRyeXBvaW50XG4gIGNvbnN0IGNka0pzb24gPSBhd2FpdCBmcy5yZWFkSnNvbihwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICdjZGsuanNvbicpKTtcbiAgY2RrSnNvbi5hcHAgPSAnbm9kZSBuZXctZW50cnlwb2ludC5tanMnO1xuICBhd2FpdCBmcy53cml0ZUpzb24ocGF0aC5qb2luKGNvbnRleHQuaW50ZWdUZXN0RGlyLCAnY2RrLmpzb24nKSwgY2RrSnNvbik7XG5cbiAgYXdhaXQgc2hlbGwuc2hlbGwoWydjZGsnLCAnc3ludGgnXSk7XG59KSkpO1xuIl19
@@ -55,5 +55,4 @@ new TestjsStack(app, 'TestjsStack');
55
55
  await fs.writeJson(path.join(context.integTestDir, 'cdk.json'), cdkJson);
56
56
 
57
57
  await shell.shell(['cdk', 'synth']);
58
-
59
58
  })));
@@ -34,7 +34,7 @@ TYPESCRIPT_VERSIONS.forEach(tsVersion => {
34
34
  await removeDevDependencies(context);
35
35
  await shell.shell(['npm', 'install', '--save-dev', `typescript@${tsVersion}`]);
36
36
  // After we've removed devDependencies we need to re-install ts-node because it's necessary for `cdk synth`
37
- await shell.shell(['npm', 'install', '--save-dev', `ts-node@^10`]);
37
+ await shell.shell(['npm', 'install', '--save-dev', 'ts-node@^10']);
38
38
  await shell.shell(['npm', 'install']); // Older versions of npm require this to be a separate step from the one above
39
39
  await shell.shell(['npx', 'tsc', '--version']);
40
40
  await shell.shell(['npm', 'prune']);
@@ -51,4 +51,4 @@ async function removeDevDependencies(context) {
51
51
  delete pj.devDependencies;
52
52
  await fs_1.promises.writeFile(filename, JSON.stringify(pj, undefined, 2), { encoding: 'utf-8' });
53
53
  }
54
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC10eXBlc2NyaXB0LWFwcC5pbnRlZ3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbml0LXR5cGVzY3JpcHQtYXBwLmludGVndGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDJCQUFvQztBQUNwQyw2QkFBNkI7QUFDN0IsbUNBQW9IO0FBQ3BILHVDQUE4RjtBQUU5RixDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7SUFDdkMsSUFBQSxlQUFTLEVBQUMsbUJBQW1CLFFBQVEsRUFBRSxFQUFFLElBQUEsNEJBQXNCLEVBQUMsSUFBQSxrQkFBWSxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUM3RixNQUFNLEtBQUssR0FBRyxpQkFBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUUxQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUVqRSxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG9EQUFvRDtRQUN0RixNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRTFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxP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MUIsTUFBTSxhQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztBQUN4RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgaW50ZWdUZXN0LCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5LCBTaGVsbEhlbHBlciwgd2l0aFBhY2thZ2VzLCBUZW1wb3JhcnlEaXJlY3RvcnlDb250ZXh0IH0gZnJvbSAnLi4vLi4vbGliJztcbmltcG9ydCB7IHR5cGVzY3JpcHRWZXJzaW9uc1N5bmMsIHR5cGVzY3JpcHRWZXJzaW9uc1lvdW5nZXJUaGFuRGF5c1N5bmMgfSBmcm9tICcuLi8uLi9saWIvbnBtJztcblxuWydhcHAnLCAnc2FtcGxlLWFwcCddLmZvckVhY2godGVtcGxhdGUgPT4ge1xuICBpbnRlZ1Rlc3QoYHR5cGVzY3JpcHQgaW5pdCAke3RlbXBsYXRlfWAsIHdpdGhUZW1wb3JhcnlEaXJlY3Rvcnkod2l0aFBhY2thZ2VzKGFzeW5jIChjb250ZXh0KSA9PiB7XG4gICAgY29uc3Qgc2hlbGwgPSBTaGVsbEhlbHBlci5mcm9tQ29udGV4dChjb250ZXh0KTtcbiAgICBhd2FpdCBjb250ZXh0LnBhY2thZ2VzLm1ha2VDbGlBdmFpbGFibGUoKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAndHlwZXNjcmlwdCcsIHRlbXBsYXRlXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdwcnVuZSddKTtcbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdscyddKTsgLy8gdGhpcyB3aWxsIGZhaWwgaWYgd2UgaGF2ZSB1bm1ldCBwZWVyIGRlcGVuZGVuY2llc1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ3J1bicsICdidWlsZCddKTtcbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdydW4nLCAndGVzdCddKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ3N5bnRoJ10pO1xuICB9KSkpO1xufSk7XG5cbi8vIFNhbWUgYXMgaHR0cHM6Ly9naXRodWIuY29tL0RlZmluaXRlbHlUeXBlZC9EZWZpbml0ZWx5VHlwZWQ/dGFiPXJlYWRtZS1vdi1maWxlI3N1cHBvcnQtd2luZG93XG5jb25zdCBUWVBFU0NSSVBUX1ZFUlNJT05fQUdFX0RBWVMgPSAyICogMzY1O1xuXG5jb25zdCBUWVBFU0NSSVBUX1ZFUlNJT05TID0gdHlwZXNjcmlwdFZlcnNpb25zWW91bmdlclRoYW5EYXlzU3luYyhUWVBFU0NSSVBUX1ZFUlNJT05fQUdFX0RBWVMsIHR5cGVzY3JpcHRWZXJzaW9uc1N5bmMoKSk7XG5cbi8qKlxuICogVGVzdCBvdXIgZ2VuZXJhdGVkIGNvZGUgd2l0aCB2YXJpb3VzIHZlcnNpb25zIG9mIFR5cGVTY3JpcHRcbiAqL1xuVFlQRVNDUklQVF9WRVJTSU9OUy5mb3JFYWNoKHRzVmVyc2lvbiA9PiB7XG4gIGludGVnVGVzdChgdHlwZXNjcmlwdCAke3RzVmVyc2lvbn0gaW5pdCBhcHBgLCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5KHdpdGhQYWNrYWdlcyhhc3luYyAoY29udGV4dCkgPT4ge1xuICAgIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gICAgYXdhaXQgY29udGV4dC5wYWNrYWdlcy5tYWtlQ2xpQXZhaWxhYmxlKCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25vZGUnLCAnLS12ZXJzaW9uJ10pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJy0tdmVyc2lvbiddKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAndHlwZXNjcmlwdCcsICdhcHAnLCAnLS1nZW5lcmF0ZS1vbmx5J10pO1xuXG4gICAgLy8gTmVjZXNzYXJ5IGJlY2F1c2UgcmVjZW50IHZlcnNpb25zIG9mIHRzLWplc3QgcmVxdWlyZSBUeXBlU2NyaXB0Pj00LjMgYnV0IHdlXG4gICAgLy8gc3RpbGwgd2FudCB0byB0ZXN0IHdpdGggb2xkZXIgdmVyc2lvbnMgYXMgd2VsbC5cbiAgICBhd2FpdCByZW1vdmVEZXZEZXBlbmRlbmNpZXMoY29udGV4dCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdpbnN0YWxsJywgJy0tc2F2ZS1kZXYnLCBgdHlwZXNjcmlwdEAke3RzVmVyc2lvbn1gXSk7XG5cbiAgICAvLyBBZnRlciB3ZSd2ZSByZW1vdmVkIGRldkRlcGVuZGVuY2llcyB3ZSBuZWVkIHRvIHJlLWluc3RhbGwgdHMtbm9kZSBiZWNhdXNlIGl0J3MgbmVjZXNzYXJ5IGZvciBgY2RrIHN5bnRoYFxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2luc3RhbGwnLCAnLS1zYXZlLWRldicsIGB0cy1ub2RlQF4xMGBdKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2luc3RhbGwnXSk7IC8vIE9sZGVyIHZlcnNpb25zIG9mIG5wbSByZXF1aXJlIHRoaXMgdG8gYmUgYSBzZXBhcmF0ZSBzdGVwIGZyb20gdGhlIG9uZSBhYm92ZVxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnB4JywgJ3RzYycsICctLXZlcnNpb24nXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAncHJ1bmUnXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAnbHMnXSk7IC8vIHRoaXMgd2lsbCBmYWlsIGlmIHdlIGhhdmUgdW5tZXQgcGVlciBkZXBlbmRlbmNpZXNcblxuICAgIC8vIFdlIGp1c3QgcmVtb3ZlZCB0aGUgJ2plc3QnIGRlcGVuZGVuY3kgc28gcmVtb3ZlIHRoZSB0ZXN0cyBhcyB3ZWxsIGJlY2F1c2UgdGhleSB3b24ndCBjb21waWxlXG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWydybScsICctcmYnLCAndGVzdC8nXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdydW4nLCAnYnVpbGQnXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWydjZGsnLCAnc3ludGgnXSk7XG4gIH0pKSk7XG59KTtcblxuYXN5bmMgZnVuY3Rpb24gcmVtb3ZlRGV2RGVwZW5kZW5jaWVzKGNvbnRleHQ6IFRlbXBvcmFyeURpcmVjdG9yeUNvbnRleHQpIHtcbiAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICdwYWNrYWdlLmpzb24nKTtcbiAgY29uc3QgcGogPSBKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVuYW1lLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pKTtcbiAgZGVsZXRlIHBqLmRldkRlcGVuZGVuY2llcztcbiAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVuYW1lLCBKU09OLnN0cmluZ2lmeShwaiwgdW5kZWZpbmVkLCAyKSwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KTtcbn1cbiJdfQ==
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC10eXBlc2NyaXB0LWFwcC5pbnRlZ3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbml0LXR5cGVzY3JpcHQtYXBwLmludGVndGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDJCQUFvQztBQUNwQyw2QkFBNkI7QUFDN0IsbUNBQW9IO0FBQ3BILHVDQUE4RjtBQUU5RixDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7SUFDdkMsSUFBQSxlQUFTLEVBQUMsbUJBQW1CLFFBQVEsRUFBRSxFQUFFLElBQUEsNEJBQXNCLEVBQUMsSUFBQSxrQkFBWSxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUM3RixNQUFNLEtBQUssR0FBRyxpQkFBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUUxQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUVqRSxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG9EQUFvRDtRQUN0RixNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRTFDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxP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MUIsTUFBTSxhQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztBQUN4RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgaW50ZWdUZXN0LCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5LCBTaGVsbEhlbHBlciwgd2l0aFBhY2thZ2VzLCBUZW1wb3JhcnlEaXJlY3RvcnlDb250ZXh0IH0gZnJvbSAnLi4vLi4vbGliJztcbmltcG9ydCB7IHR5cGVzY3JpcHRWZXJzaW9uc1N5bmMsIHR5cGVzY3JpcHRWZXJzaW9uc1lvdW5nZXJUaGFuRGF5c1N5bmMgfSBmcm9tICcuLi8uLi9saWIvbnBtJztcblxuWydhcHAnLCAnc2FtcGxlLWFwcCddLmZvckVhY2godGVtcGxhdGUgPT4ge1xuICBpbnRlZ1Rlc3QoYHR5cGVzY3JpcHQgaW5pdCAke3RlbXBsYXRlfWAsIHdpdGhUZW1wb3JhcnlEaXJlY3Rvcnkod2l0aFBhY2thZ2VzKGFzeW5jIChjb250ZXh0KSA9PiB7XG4gICAgY29uc3Qgc2hlbGwgPSBTaGVsbEhlbHBlci5mcm9tQ29udGV4dChjb250ZXh0KTtcbiAgICBhd2FpdCBjb250ZXh0LnBhY2thZ2VzLm1ha2VDbGlBdmFpbGFibGUoKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAndHlwZXNjcmlwdCcsIHRlbXBsYXRlXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdwcnVuZSddKTtcbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdscyddKTsgLy8gdGhpcyB3aWxsIGZhaWwgaWYgd2UgaGF2ZSB1bm1ldCBwZWVyIGRlcGVuZGVuY2llc1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ3J1bicsICdidWlsZCddKTtcbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdydW4nLCAndGVzdCddKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ3N5bnRoJ10pO1xuICB9KSkpO1xufSk7XG5cbi8vIFNhbWUgYXMgaHR0cHM6Ly9naXRodWIuY29tL0RlZmluaXRlbHlUeXBlZC9EZWZpbml0ZWx5VHlwZWQ/dGFiPXJlYWRtZS1vdi1maWxlI3N1cHBvcnQtd2luZG93XG5jb25zdCBUWVBFU0NSSVBUX1ZFUlNJT05fQUdFX0RBWVMgPSAyICogMzY1O1xuXG5jb25zdCBUWVBFU0NSSVBUX1ZFUlNJT05TID0gdHlwZXNjcmlwdFZlcnNpb25zWW91bmdlclRoYW5EYXlzU3luYyhUWVBFU0NSSVBUX1ZFUlNJT05fQUdFX0RBWVMsIHR5cGVzY3JpcHRWZXJzaW9uc1N5bmMoKSk7XG5cbi8qKlxuICogVGVzdCBvdXIgZ2VuZXJhdGVkIGNvZGUgd2l0aCB2YXJpb3VzIHZlcnNpb25zIG9mIFR5cGVTY3JpcHRcbiAqL1xuVFlQRVNDUklQVF9WRVJTSU9OUy5mb3JFYWNoKHRzVmVyc2lvbiA9PiB7XG4gIGludGVnVGVzdChgdHlwZXNjcmlwdCAke3RzVmVyc2lvbn0gaW5pdCBhcHBgLCB3aXRoVGVtcG9yYXJ5RGlyZWN0b3J5KHdpdGhQYWNrYWdlcyhhc3luYyAoY29udGV4dCkgPT4ge1xuICAgIGNvbnN0IHNoZWxsID0gU2hlbGxIZWxwZXIuZnJvbUNvbnRleHQoY29udGV4dCk7XG4gICAgYXdhaXQgY29udGV4dC5wYWNrYWdlcy5tYWtlQ2xpQXZhaWxhYmxlKCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25vZGUnLCAnLS12ZXJzaW9uJ10pO1xuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJy0tdmVyc2lvbiddKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnY2RrJywgJ2luaXQnLCAnLWwnLCAndHlwZXNjcmlwdCcsICdhcHAnLCAnLS1nZW5lcmF0ZS1vbmx5J10pO1xuXG4gICAgLy8gTmVjZXNzYXJ5IGJlY2F1c2UgcmVjZW50IHZlcnNpb25zIG9mIHRzLWplc3QgcmVxdWlyZSBUeXBlU2NyaXB0Pj00LjMgYnV0IHdlXG4gICAgLy8gc3RpbGwgd2FudCB0byB0ZXN0IHdpdGggb2xkZXIgdmVyc2lvbnMgYXMgd2VsbC5cbiAgICBhd2FpdCByZW1vdmVEZXZEZXBlbmRlbmNpZXMoY29udGV4dCk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdpbnN0YWxsJywgJy0tc2F2ZS1kZXYnLCBgdHlwZXNjcmlwdEAke3RzVmVyc2lvbn1gXSk7XG5cbiAgICAvLyBBZnRlciB3ZSd2ZSByZW1vdmVkIGRldkRlcGVuZGVuY2llcyB3ZSBuZWVkIHRvIHJlLWluc3RhbGwgdHMtbm9kZSBiZWNhdXNlIGl0J3MgbmVjZXNzYXJ5IGZvciBgY2RrIHN5bnRoYFxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2luc3RhbGwnLCAnLS1zYXZlLWRldicsICd0cy1ub2RlQF4xMCddKTtcblxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnBtJywgJ2luc3RhbGwnXSk7IC8vIE9sZGVyIHZlcnNpb25zIG9mIG5wbSByZXF1aXJlIHRoaXMgdG8gYmUgYSBzZXBhcmF0ZSBzdGVwIGZyb20gdGhlIG9uZSBhYm92ZVxuICAgIGF3YWl0IHNoZWxsLnNoZWxsKFsnbnB4JywgJ3RzYycsICctLXZlcnNpb24nXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAncHJ1bmUnXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWyducG0nLCAnbHMnXSk7IC8vIHRoaXMgd2lsbCBmYWlsIGlmIHdlIGhhdmUgdW5tZXQgcGVlciBkZXBlbmRlbmNpZXNcblxuICAgIC8vIFdlIGp1c3QgcmVtb3ZlZCB0aGUgJ2plc3QnIGRlcGVuZGVuY3kgc28gcmVtb3ZlIHRoZSB0ZXN0cyBhcyB3ZWxsIGJlY2F1c2UgdGhleSB3b24ndCBjb21waWxlXG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWydybScsICctcmYnLCAndGVzdC8nXSk7XG5cbiAgICBhd2FpdCBzaGVsbC5zaGVsbChbJ25wbScsICdydW4nLCAnYnVpbGQnXSk7XG4gICAgYXdhaXQgc2hlbGwuc2hlbGwoWydjZGsnLCAnc3ludGgnXSk7XG4gIH0pKSk7XG59KTtcblxuYXN5bmMgZnVuY3Rpb24gcmVtb3ZlRGV2RGVwZW5kZW5jaWVzKGNvbnRleHQ6IFRlbXBvcmFyeURpcmVjdG9yeUNvbnRleHQpIHtcbiAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLmpvaW4oY29udGV4dC5pbnRlZ1Rlc3REaXIsICdwYWNrYWdlLmpzb24nKTtcbiAgY29uc3QgcGogPSBKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVuYW1lLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pKTtcbiAgZGVsZXRlIHBqLmRldkRlcGVuZGVuY2llcztcbiAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVuYW1lLCBKU09OLnN0cmluZ2lmeShwaiwgdW5kZWZpbmVkLCAyKSwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KTtcbn1cbiJdfQ==
@@ -44,7 +44,7 @@ TYPESCRIPT_VERSIONS.forEach(tsVersion => {
44
44
  await shell.shell(['npm', 'install', '--save-dev', `typescript@${tsVersion}`]);
45
45
 
46
46
  // After we've removed devDependencies we need to re-install ts-node because it's necessary for `cdk synth`
47
- await shell.shell(['npm', 'install', '--save-dev', `ts-node@^10`]);
47
+ await shell.shell(['npm', 'install', '--save-dev', 'ts-node@^10']);
48
48
 
49
49
  await shell.shell(['npm', 'install']); // Older versions of npm require this to be a separate step from the one above
50
50
  await shell.shell(['npx', 'tsc', '--version']);