@aws-cdk-testing/cli-integ 2.173.4 → 3.0.0

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 (81) hide show
  1. package/.eslintrc.js +9 -0
  2. package/LICENSE +2 -1
  3. package/bin/query-github.js +3 -3
  4. package/bin/query-github.ts +56 -0
  5. package/bin/run-suite.js +3 -3
  6. package/bin/run-suite.ts +140 -0
  7. package/bin/stage-distribution.js +3 -2
  8. package/bin/stage-distribution.ts +267 -0
  9. package/bin/test-root.ts +3 -0
  10. package/lib/aws.js +9 -6
  11. package/lib/aws.ts +263 -0
  12. package/lib/corking.ts +33 -0
  13. package/lib/eventually.js +3 -3
  14. package/lib/eventually.ts +42 -0
  15. package/lib/files.js +3 -2
  16. package/lib/files.ts +80 -0
  17. package/lib/github.js +6 -5
  18. package/lib/github.ts +43 -0
  19. package/lib/index.ts +13 -0
  20. package/lib/integ-test.ts +81 -0
  21. package/lib/lists.ts +9 -0
  22. package/lib/memoize.ts +14 -0
  23. package/lib/npm.ts +41 -0
  24. package/lib/package-sources/release-source.js +3 -2
  25. package/lib/package-sources/release-source.ts +81 -0
  26. package/lib/package-sources/repo-source.ts +111 -0
  27. package/lib/package-sources/repo-tools/npm.js +5 -4
  28. package/lib/package-sources/repo-tools/npm.ts +48 -0
  29. package/lib/package-sources/source.ts +35 -0
  30. package/lib/package-sources/subprocess.ts +15 -0
  31. package/lib/resource-pool.js +2 -2
  32. package/lib/resource-pool.ts +140 -0
  33. package/lib/resources.ts +4 -0
  34. package/lib/shell.js +8 -5
  35. package/lib/shell.ts +168 -0
  36. package/lib/staging/codeartifact.js +11 -8
  37. package/lib/staging/codeartifact.ts +387 -0
  38. package/lib/staging/maven.js +5 -3
  39. package/lib/staging/maven.ts +95 -0
  40. package/lib/staging/npm.ts +62 -0
  41. package/lib/staging/nuget.ts +75 -0
  42. package/lib/staging/parallel-shell.js +2 -2
  43. package/lib/staging/parallel-shell.ts +51 -0
  44. package/lib/staging/pypi.ts +50 -0
  45. package/lib/staging/usage-dir.ts +99 -0
  46. package/lib/with-aws.js +3 -2
  47. package/lib/with-aws.ts +67 -0
  48. package/lib/with-cdk-app.js +23 -14
  49. package/lib/with-cdk-app.ts +742 -0
  50. package/lib/with-cli-lib.ts +134 -0
  51. package/lib/with-packages.ts +15 -0
  52. package/lib/with-sam.js +7 -4
  53. package/lib/with-sam.ts +288 -0
  54. package/lib/with-temporary-directory.ts +35 -0
  55. package/lib/with-timeout.ts +33 -0
  56. package/lib/xpmutex.js +2 -2
  57. package/lib/xpmutex.ts +218 -0
  58. package/package.json +84 -62
  59. package/resources/cloud-assemblies/0.36.0/cdk.out +1 -0
  60. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/cdk.out +1 -0
  61. package/resources/cloud-assemblies/1.10.0-request-azs/cdk.out +1 -0
  62. package/tests/cli-integ-tests/bootstrapping.integtest.js +22 -13
  63. package/tests/cli-integ-tests/bootstrapping.integtest.ts +493 -0
  64. package/tests/cli-integ-tests/cli-lib.integtest.js +3 -2
  65. package/tests/cli-integ-tests/cli-lib.integtest.ts +90 -0
  66. package/tests/cli-integ-tests/cli.integtest.js +76 -49
  67. package/tests/cli-integ-tests/cli.integtest.ts +2874 -0
  68. package/tests/cli-integ-tests/garbage-collection.integtest.js +2 -2
  69. package/tests/cli-integ-tests/garbage-collection.integtest.ts +392 -0
  70. package/tests/init-csharp/init-csharp.integtest.ts +15 -0
  71. package/tests/init-fsharp/init-fsharp.integtest.ts +15 -0
  72. package/tests/init-go/init-go.integtest.ts +23 -0
  73. package/tests/init-java/init-java.integtest.ts +14 -0
  74. package/tests/init-javascript/init-javascript.integtest.ts +59 -0
  75. package/tests/init-python/init-python.integtest.ts +20 -0
  76. package/tests/init-typescript-app/init-typescript-app.integtest.ts +66 -0
  77. package/tests/init-typescript-lib/init-typescript-lib.integtest.ts +13 -0
  78. package/tests/tool-integrations/amplify.integtest.ts +43 -0
  79. package/tests/tool-integrations/with-tool-context.ts +14 -0
  80. package/tests/uberpackage/uberpackage.integtest.ts +11 -0
  81. package/resources/cdk-apps/cfn-include-app/.gitignore +0 -1
@@ -20,7 +20,7 @@ async function parallelShell(inputs, block, swallowError) {
20
20
  return;
21
21
  }
22
22
  catch (e) {
23
- switch (swallowError?.(input, output.toString())) {
23
+ switch (swallowError === null || swallowError === void 0 ? void 0 : swallowError(input, output.toString())) {
24
24
  case 'skip':
25
25
  return;
26
26
  case 'retry':
@@ -42,4 +42,4 @@ async function parallelShell(inputs, block, swallowError) {
42
42
  }));
43
43
  await q.onEmpty();
44
44
  }
45
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYWxsZWwtc2hlbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwYXJhbGxlbC1zaGVsbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLHNDQXlDQztBQWxERCxxQ0FBNkI7QUFDN0IsZ0NBQStCO0FBQy9CLHdDQUEwQztBQUkxQzs7R0FFRztBQUNJLEtBQUssVUFBVSxhQUFhLENBQ2pDLE1BQVcsRUFDWCxLQUE2RCxFQUM3RCxZQUFzRDtJQUV0RCx5RkFBeUY7SUFDekYsTUFBTSxDQUFDLEdBQUcsSUFBSSxpQkFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0UsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLElBQUksRUFBRTtRQUM1QyxJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDO1FBQ2xCLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLE1BQU0sR0FBRyxJQUFJLHNCQUFZLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUMzQixPQUFPO1lBQ1QsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsUUFBUSxZQUFZLEVBQUUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDakQsS0FBSyxNQUFNO3dCQUNULE9BQU87b0JBRVQsS0FBSyxPQUFPO3dCQUNWLElBQUksRUFBRSxRQUFRLEdBQUcsQ0FBQyxFQUFFLENBQUM7NEJBQ25CLE1BQU0sSUFBQSxXQUFLLEVBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQzs0QkFDakQsT0FBTyxJQUFJLENBQUMsQ0FBQzs0QkFDYixTQUFTO3dCQUNYLENBQUM7d0JBQ0QsTUFBTTtvQkFFUixLQUFLLE1BQU0sQ0FBQztvQkFDWixLQUFLLFNBQVM7d0JBQ1osTUFBTTtnQkFDVixDQUFDO2dCQUVELHNDQUFzQztnQkFDdEMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDakMsTUFBTSxDQUFDLENBQUM7WUFDVixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFSixNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUNwQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBRdWV1ZSBmcm9tICdwLXF1ZXVlJztcbmltcG9ydCB7IHNsZWVwIH0gZnJvbSAnLi4vYXdzJztcbmltcG9ydCB7IE1lbW9yeVN0cmVhbSB9IGZyb20gJy4uL2NvcmtpbmcnO1xuXG5leHBvcnQgdHlwZSBFcnJvclJlc3BvbnNlID0gJ2ZhaWwnIHwgJ3NraXAnIHwgJ3JldHJ5JztcblxuLyoqXG4gKiBSdW4gYSBmdW5jdGlvbiBpbiBwYXJhbGxlbCB3aXRoIGNhY2hlZCBvdXRwdXRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBhcmFsbGVsU2hlbGw8QT4oXG4gIGlucHV0czogQVtdLFxuICBibG9jazogKHg6IEEsIG91dHB1dDogTm9kZUpTLldyaXRhYmxlU3RyZWFtKSA9PiBQcm9taXNlPHZvaWQ+LFxuICBzd2FsbG93RXJyb3I/OiAoeDogQSwgb3V0cHV0OiBzdHJpbmcpID0+IEVycm9yUmVzcG9uc2UsXG4pIHtcbiAgLy8gTGltaXQgdG8gMTAgZm9yIG5vdywgdG9vIG1hbnkgaW5zdGFuY2VzIG9mIE1hdmVuIGV4aGF1c3QgdGhlIENvZGVCdWlsZCBpbnN0YW5jZSBtZW1vcnlcbiAgY29uc3QgcSA9IG5ldyBQUXVldWUoeyBjb25jdXJyZW5jeTogTnVtYmVyKHByb2Nlc3MuZW52LkNPTkNVUlJFTkNZKSB8fCAxMCB9KTtcbiAgYXdhaXQgcS5hZGRBbGwoaW5wdXRzLm1hcChpbnB1dCA9PiBhc3luYyAoKSA9PiB7XG4gICAgbGV0IGF0dGVtcHRzID0gMTA7XG4gICAgbGV0IHNsZWVwTXMgPSA1MDA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IG91dHB1dCA9IG5ldyBNZW1vcnlTdHJlYW0oKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJsb2NrKGlucHV0LCBvdXRwdXQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHN3aXRjaCAoc3dhbGxvd0Vycm9yPy4oaW5wdXQsIG91dHB1dC50b1N0cmluZygpKSkge1xuICAgICAgICAgIGNhc2UgJ3NraXAnOlxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgY2FzZSAncmV0cnknOlxuICAgICAgICAgICAgaWYgKC0tYXR0ZW1wdHMgPiAwKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHNsZWVwTXMpKTtcbiAgICAgICAgICAgICAgc2xlZXBNcyAqPSAyO1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnZmFpbCc6XG4gICAgICAgICAgY2FzZSB1bmRlZmluZWQ6XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUuZXJyb3Iob3V0cHV0LnRvU3RyaW5nKCkpO1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfSkpO1xuXG4gIGF3YWl0IHEub25FbXB0eSgpO1xufVxuIl19
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYWxsZWwtc2hlbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwYXJhbGxlbC1zaGVsbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLHNDQXlDQztBQWxERCxxQ0FBNkI7QUFDN0IsZ0NBQStCO0FBQy9CLHdDQUEwQztBQUkxQzs7R0FFRztBQUNJLEtBQUssVUFBVSxhQUFhLENBQ2pDLE1BQVcsRUFDWCxLQUE2RCxFQUM3RCxZQUFzRDtJQUV0RCx5RkFBeUY7SUFDekYsTUFBTSxDQUFDLEdBQUcsSUFBSSxpQkFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDN0UsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLElBQUksRUFBRTtRQUM1QyxJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxPQUFPLEdBQUcsR0FBRyxDQUFDO1FBQ2xCLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLE1BQU0sR0FBRyxJQUFJLHNCQUFZLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUMzQixPQUFPO1lBQ1QsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsUUFBUSxZQUFZLGFBQVosWUFBWSx1QkFBWixZQUFZLENBQUcsS0FBSyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ2pELEtBQUssTUFBTTt3QkFDVCxPQUFPO29CQUVULEtBQUssT0FBTzt3QkFDVixJQUFJLEVBQUUsUUFBUSxHQUFHLENBQUMsRUFBRSxDQUFDOzRCQUNuQixNQUFNLElBQUEsV0FBSyxFQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUM7NEJBQ2pELE9BQU8sSUFBSSxDQUFDLENBQUM7NEJBQ2IsU0FBUzt3QkFDWCxDQUFDO3dCQUNELE1BQU07b0JBRVIsS0FBSyxNQUFNLENBQUM7b0JBQ1osS0FBSyxTQUFTO3dCQUNaLE1BQU07Z0JBQ1YsQ0FBQztnQkFFRCxzQ0FBc0M7Z0JBQ3RDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ2pDLE1BQU0sQ0FBQyxDQUFDO1lBQ1YsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRUosTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQUXVldWUgZnJvbSAncC1xdWV1ZSc7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJy4uL2F3cyc7XG5pbXBvcnQgeyBNZW1vcnlTdHJlYW0gfSBmcm9tICcuLi9jb3JraW5nJztcblxuZXhwb3J0IHR5cGUgRXJyb3JSZXNwb25zZSA9ICdmYWlsJyB8ICdza2lwJyB8ICdyZXRyeSc7XG5cbi8qKlxuICogUnVuIGEgZnVuY3Rpb24gaW4gcGFyYWxsZWwgd2l0aCBjYWNoZWQgb3V0cHV0XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYXJhbGxlbFNoZWxsPEE+KFxuICBpbnB1dHM6IEFbXSxcbiAgYmxvY2s6ICh4OiBBLCBvdXRwdXQ6IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkgPT4gUHJvbWlzZTx2b2lkPixcbiAgc3dhbGxvd0Vycm9yPzogKHg6IEEsIG91dHB1dDogc3RyaW5nKSA9PiBFcnJvclJlc3BvbnNlLFxuKSB7XG4gIC8vIExpbWl0IHRvIDEwIGZvciBub3csIHRvbyBtYW55IGluc3RhbmNlcyBvZiBNYXZlbiBleGhhdXN0IHRoZSBDb2RlQnVpbGQgaW5zdGFuY2UgbWVtb3J5XG4gIGNvbnN0IHEgPSBuZXcgUFF1ZXVlKHsgY29uY3VycmVuY3k6IE51bWJlcihwcm9jZXNzLmVudi5DT05DVVJSRU5DWSkgfHwgMTAgfSk7XG4gIGF3YWl0IHEuYWRkQWxsKGlucHV0cy5tYXAoaW5wdXQgPT4gYXN5bmMgKCkgPT4ge1xuICAgIGxldCBhdHRlbXB0cyA9IDEwO1xuICAgIGxldCBzbGVlcE1zID0gNTAwO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCBvdXRwdXQgPSBuZXcgTWVtb3J5U3RyZWFtKCk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBibG9jayhpbnB1dCwgb3V0cHV0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBzd2l0Y2ggKHN3YWxsb3dFcnJvcj8uKGlucHV0LCBvdXRwdXQudG9TdHJpbmcoKSkpIHtcbiAgICAgICAgICBjYXNlICdza2lwJzpcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAgIGNhc2UgJ3JldHJ5JzpcbiAgICAgICAgICAgIGlmICgtLWF0dGVtcHRzID4gMCkge1xuICAgICAgICAgICAgICBhd2FpdCBzbGVlcChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBzbGVlcE1zKSk7XG4gICAgICAgICAgICAgIHNsZWVwTXMgKj0gMjtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ2ZhaWwnOlxuICAgICAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLmVycm9yKG91dHB1dC50b1N0cmluZygpKTtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH0pKTtcblxuICBhd2FpdCBxLm9uRW1wdHkoKTtcbn1cbiJdfQ==
@@ -0,0 +1,51 @@
1
+ import PQueue from 'p-queue';
2
+ import { sleep } from '../aws';
3
+ import { MemoryStream } from '../corking';
4
+
5
+ export type ErrorResponse = 'fail' | 'skip' | 'retry';
6
+
7
+ /**
8
+ * Run a function in parallel with cached output
9
+ */
10
+ export async function parallelShell<A>(
11
+ inputs: A[],
12
+ block: (x: A, output: NodeJS.WritableStream) => Promise<void>,
13
+ swallowError?: (x: A, output: string) => ErrorResponse,
14
+ ) {
15
+ // Limit to 10 for now, too many instances of Maven exhaust the CodeBuild instance memory
16
+ const q = new PQueue({ concurrency: Number(process.env.CONCURRENCY) || 10 });
17
+ await q.addAll(inputs.map(input => async () => {
18
+ let attempts = 10;
19
+ let sleepMs = 500;
20
+ while (true) {
21
+ const output = new MemoryStream();
22
+ try {
23
+ await block(input, output);
24
+ return;
25
+ } catch (e) {
26
+ switch (swallowError?.(input, output.toString())) {
27
+ case 'skip':
28
+ return;
29
+
30
+ case 'retry':
31
+ if (--attempts > 0) {
32
+ await sleep(Math.floor(Math.random() * sleepMs));
33
+ sleepMs *= 2;
34
+ continue;
35
+ }
36
+ break;
37
+
38
+ case 'fail':
39
+ case undefined:
40
+ break;
41
+ }
42
+
43
+ // eslint-disable-next-line no-console
44
+ console.error(output.toString());
45
+ throw e;
46
+ }
47
+ }
48
+ }));
49
+
50
+ await q.onEmpty();
51
+ }
@@ -0,0 +1,50 @@
1
+ /* eslint-disable no-console */
2
+ import * as path from 'path';
3
+ import { LoginInformation } from './codeartifact';
4
+ import { parallelShell } from './parallel-shell';
5
+ import { UsageDir } from './usage-dir';
6
+ import { writeFile } from '../files';
7
+ import { shell } from '../shell';
8
+
9
+ export async function pypiLogin(login: LoginInformation, usageDir: UsageDir) {
10
+ // Write pip config file and set environment var
11
+ await writeFile(path.join(usageDir.directory, 'pip.conf'), [
12
+ '[global]',
13
+ `index-url = https://aws:${login.authToken}@${login.pypiEndpoint.replace(/^https:\/\//, '')}simple/`,
14
+ ].join('\n'));
15
+ await usageDir.addToEnv({
16
+ PIP_CONFIG_FILE: `${usageDir.directory}/pip.conf`,
17
+ });
18
+ }
19
+
20
+ export async function uploadPythonPackages(packages: string[], login: LoginInformation) {
21
+ await shell(['pip', 'install', 'twine'], { show: 'error' });
22
+
23
+ // Even though twine supports uploading all packages in one go, we have to upload them
24
+ // individually since CodeArtifact does not support Twine's `--skip-existing`. Fun beans.
25
+ await parallelShell(packages, async (pkg, output) => {
26
+ console.log(`⏳ ${pkg}`);
27
+
28
+ await shell(['twine', 'upload', '--verbose', pkg], {
29
+ modEnv: {
30
+ TWINE_USERNAME: 'aws',
31
+ TWINE_PASSWORD: login.authToken,
32
+ TWINE_REPOSITORY_URL: login.pypiEndpoint,
33
+ },
34
+ show: 'error',
35
+ outputs: [output],
36
+ });
37
+
38
+ console.log(`✅ ${pkg}`);
39
+ }, (pkg, output) => {
40
+ if (output.toString().includes('This package is configured to block new versions') || output.toString().includes('409 Conflict')) {
41
+ console.log(`❌ ${pkg}: already exists. Skipped.`);
42
+ return 'skip';
43
+ }
44
+ if (output.includes('429 Too Many Requests ')) {
45
+ console.log(`♻️ ${pkg}: 429 Too Many Requests. Retrying.`);
46
+ return 'retry';
47
+ }
48
+ return 'fail';
49
+ });
50
+ }
@@ -0,0 +1,99 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs-extra';
3
+ import { copyDirectoryContents, homeDir, loadLines, updateIniKey, writeLines } from '../files';
4
+
5
+ export const DEFAULT_USAGE_DIR = path.join(homeDir(), '.codeartifact/usage');
6
+
7
+ /**
8
+ * The usage directory is where we write per-session config files to access the CodeArtifact repository.
9
+ *
10
+ * Some config files may be written in a system-global location, but they will not be active unless the
11
+ * contents of this directory have been sourced/copied into the current terminal.
12
+ *
13
+ * CONTRACT
14
+ *
15
+ * There are two special entries:
16
+ *
17
+ * - `env`, a file with `key=value` entries for environment variables to set.
18
+ * - `cwd/`, a directory with files that need to be copied into the current directory before each command.
19
+ *
20
+ * Other than these, code may write tempfiles to this directory if it wants, but there is no meaning
21
+ * implied for other files.
22
+ */
23
+ export class UsageDir {
24
+ public static default() {
25
+ return new UsageDir(DEFAULT_USAGE_DIR);
26
+ }
27
+
28
+ public readonly envFile: string;
29
+ public readonly cwdDir: string;
30
+
31
+ private constructor(public readonly directory: string) {
32
+ this.envFile = path.join(this.directory, 'env');
33
+ this.cwdDir = path.join(this.directory, 'cwd');
34
+ }
35
+
36
+ public async clean() {
37
+ await fs.rm(this.directory, { recursive: true, force: true });
38
+ await fs.mkdirp(path.join(this.directory, 'cwd'));
39
+ await fs.writeFile(path.join(this.directory, 'env'), '', { encoding: 'utf-8' });
40
+
41
+ await this.addToEnv({
42
+ CWD_FILES_DIR: path.join(this.directory, 'cwd'),
43
+ });
44
+
45
+ // Write a bash helper to load these settings
46
+ await fs.writeFile(path.join(this.directory, 'activate.bash'), [
47
+ `while read -u10 line; do [[ -z $line ]] || export "$line"; done 10<${this.directory}/env`,
48
+ 'cp -R $CWD_FILES_DIR/ .', // Copy files from directory even if it is empty
49
+ ].join('\n'), { encoding: 'utf-8' });
50
+ }
51
+
52
+ public async addToEnv(settings: Record<string, string>) {
53
+ const lines = await loadLines(this.envFile);
54
+ for (const [k, v] of Object.entries(settings)) {
55
+ updateIniKey(lines, k, v);
56
+ }
57
+ await writeLines(this.envFile, lines);
58
+ }
59
+
60
+ public async currentEnv(): Promise<Record<string, string>> {
61
+ const lines = await loadLines(this.envFile);
62
+
63
+ const splitter = /^([a-zA-Z0-9_-]+)\s*=\s*(.*)$/;
64
+
65
+ const ret: Record<string, string> = {};
66
+ for (const line of lines) {
67
+ const m = line.match(splitter);
68
+ if (m) {
69
+ ret[m[1]] = m[2];
70
+ }
71
+ }
72
+ return ret;
73
+ }
74
+
75
+ public cwdFile(filename: string) {
76
+ return path.join(this.cwdDir, filename);
77
+ }
78
+
79
+ public async activateInCurrentProcess() {
80
+ for (const [k, v] of Object.entries(await this.currentEnv())) {
81
+ process.env[k] = v;
82
+ }
83
+
84
+ await copyDirectoryContents(this.cwdDir, '.');
85
+ }
86
+
87
+ public async copyCwdFileHere(...filenames: string[]) {
88
+ for (const file of filenames) {
89
+ await fs.copyFile(path.join(this.cwdDir, file), file);
90
+ }
91
+ }
92
+
93
+ public advertise() {
94
+ // eslint-disable-next-line no-console
95
+ console.log('To activate these settings in the current terminal:');
96
+ // eslint-disable-next-line no-console
97
+ console.log(` source ${this.directory}/activate.bash`);
98
+ }
99
+ }
package/lib/with-aws.js CHANGED
@@ -18,12 +18,13 @@ function withAws(block, disableBootstrap = false) {
18
18
  }
19
19
  let _regionPool;
20
20
  function regionPool() {
21
+ var _a, _b;
21
22
  if (_regionPool !== undefined) {
22
23
  return _regionPool;
23
24
  }
24
25
  const REGIONS = process.env.AWS_REGIONS
25
26
  ? process.env.AWS_REGIONS.split(',')
26
- : [process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1'];
27
+ : [(_b = (_a = process.env.AWS_REGION) !== null && _a !== void 0 ? _a : process.env.AWS_DEFAULT_REGION) !== null && _b !== void 0 ? _b : 'us-east-1'];
27
28
  // eslint-disable-next-line no-console
28
29
  console.log(`Using regions: ${REGIONS}\n`);
29
30
  _regionPool = resource_pool_1.ResourcePool.withResources('aws_regions', REGIONS);
@@ -56,4 +57,4 @@ async function sanityCheck(aws) {
56
57
  }
57
58
  }
58
59
  let sanityChecked;
59
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l0aC1hd3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ3aXRoLWF3cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVlBLDBCQVVDO0FBR0QsZ0NBY0M7QUF2Q0QsK0JBQW1DO0FBRW5DLG1EQUErQztBQUsvQzs7OztHQUlHO0FBQ0gsU0FBZ0IsT0FBTyxDQUNyQixLQUEyRSxFQUMzRSxtQkFBNEIsS0FBSztJQUVqQyxPQUFPLENBQUMsT0FBVSxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ3pELE1BQU0sR0FBRyxHQUFHLE1BQU0sZ0JBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvRCxNQUFNLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUV2QixPQUFPLEtBQUssQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDdEQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxXQUFxQyxDQUFDO0FBQzFDLFNBQWdCLFVBQVU7SUFDeEIsSUFBSSxXQUFXLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDOUIsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVztRQUNyQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUNwQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixJQUFJLFdBQVcsQ0FBQyxDQUFDO0lBRTlFLHNDQUFzQztJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixPQUFPLElBQUksQ0FBQyxDQUFDO0lBRTNDLFdBQVcsR0FBRyw0QkFBWSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDakUsT0FBTyxXQUFXLENBQUM7QUFDckIsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxLQUFLLFVBQVUsV0FBVyxDQUFDLEdBQWU7SUFDeEMsSUFBSSxhQUFhLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDcEIsYUFBYSxHQUFHLElBQUksQ0FBQztRQUN2QixDQUFDO1FBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztZQUNoQixhQUFhLEdBQUcsS0FBSyxDQUFDO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3RGLENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsNkRBQTZELENBQUMsQ0FBQztJQUNqRixDQUFDO0FBQ0gsQ0FBQztBQUNELElBQUksYUFBa0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEF3c0NsaWVudHMgfSBmcm9tICcuL2F3cyc7XG5pbXBvcnQgeyBUZXN0Q29udGV4dCB9IGZyb20gJy4vaW50ZWctdGVzdCc7XG5pbXBvcnQgeyBSZXNvdXJjZVBvb2wgfSBmcm9tICcuL3Jlc291cmNlLXBvb2wnO1xuaW1wb3J0IHsgRGlzYWJsZUJvb3RzdHJhcENvbnRleHQgfSBmcm9tICcuL3dpdGgtY2RrLWFwcCc7XG5cbmV4cG9ydCB0eXBlIEF3c0NvbnRleHQgPSB7IHJlYWRvbmx5IGF3czogQXdzQ2xpZW50cyB9O1xuXG4vKipcbiAqIEhpZ2hlciBvcmRlciBmdW5jdGlvbiB0byBleGVjdXRlIGEgYmxvY2sgd2l0aCBhbiBBV1MgY2xpZW50IHNldHVwXG4gKlxuICogQWxsb2NhdGUgdGhlIG5leHQgcmVnaW9uIGZyb20gdGhlIFJFR0lPTiBwb29sIGFuZCBkaXNwb3NlIGl0IGFmdGVyd2FyZHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRoQXdzPEEgZXh0ZW5kcyBUZXN0Q29udGV4dD4oXG4gIGJsb2NrOiAoY29udGV4dDogQSAmIEF3c0NvbnRleHQgJiBEaXNhYmxlQm9vdHN0cmFwQ29udGV4dCkgPT4gUHJvbWlzZTx2b2lkPixcbiAgZGlzYWJsZUJvb3RzdHJhcDogYm9vbGVhbiA9IGZhbHNlLFxuKTogKGNvbnRleHQ6IEEpID0+IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gKGNvbnRleHQ6IEEpID0+IHJlZ2lvblBvb2woKS51c2luZyhhc3luYyAocmVnaW9uKSA9PiB7XG4gICAgY29uc3QgYXdzID0gYXdhaXQgQXdzQ2xpZW50cy5mb3JSZWdpb24ocmVnaW9uLCBjb250ZXh0Lm91dHB1dCk7XG4gICAgYXdhaXQgc2FuaXR5Q2hlY2soYXdzKTtcblxuICAgIHJldHVybiBibG9jayh7IC4uLmNvbnRleHQsIGRpc2FibGVCb290c3RyYXAsIGF3cyB9KTtcbiAgfSk7XG59XG5cbmxldCBfcmVnaW9uUG9vbDogdW5kZWZpbmVkIHwgUmVzb3VyY2VQb29sO1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lvblBvb2woKTogUmVzb3VyY2VQb29sIHtcbiAgaWYgKF9yZWdpb25Qb29sICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gX3JlZ2lvblBvb2w7XG4gIH1cblxuICBjb25zdCBSRUdJT05TID0gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTlNcbiAgICA/IHByb2Nlc3MuZW52LkFXU19SRUdJT05TLnNwbGl0KCcsJylcbiAgICA6IFtwcm9jZXNzLmVudi5BV1NfUkVHSU9OID8/IHByb2Nlc3MuZW52LkFXU19ERUZBVUxUX1JFR0lPTiA/PyAndXMtZWFzdC0xJ107XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coYFVzaW5nIHJlZ2lvbnM6ICR7UkVHSU9OU31cXG5gKTtcblxuICBfcmVnaW9uUG9vbCA9IFJlc291cmNlUG9vbC53aXRoUmVzb3VyY2VzKCdhd3NfcmVnaW9ucycsIFJFR0lPTlMpO1xuICByZXR1cm4gX3JlZ2lvblBvb2w7XG59XG5cbi8qKlxuICogUGVyZm9ybSBhIG9uZS10aW1lIHF1aWNrIHNhbml0eSBjaGVjayB0aGF0IHRoZSBBV1MgY2xpZW50cyBoYXZlIHByb3Blcmx5IGNvbmZpZ3VyZWQgY3JlZGVudGlhbHNcbiAqXG4gKiBJZiB3ZSBkb24ndCBkbyB0aGlzLCBjYWxscyBhcmUgZ29pbmcgdG8gZmFpbCBhbmQgdGhleSdsbCBiZSByZXRyaWVkIGFuZCBldmVyeXRoaW5nIHdpbGwgdGFrZVxuICogZm9yZXZlciBiZWZvcmUgdGhlIHVzZXIgbm90aWNlcyBhIHNpbXBsZSBtaXNjb25maWd1cmF0aW9uLlxuICpcbiAqIFdlIGNhbid0IGNoZWNrIGZvciB0aGUgcHJlc2VuY2Ugb2YgZW52aXJvbm1lbnQgdmFyaWFibGVzIHNpbmNlIGNyZWRlbnRpYWxzIGNvdWxkIGNvbWUgZnJvbVxuICogYW55d2hlcmUsIHNvIGRvIHNpbXBsZSBhY2NvdW50IHJldHJpZXZhbC5cbiAqXG4gKiBPbmx5IGRvIGl0IG9uY2UgcGVyIHByb2Nlc3MuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNhbml0eUNoZWNrKGF3czogQXdzQ2xpZW50cykge1xuICBpZiAoc2FuaXR5Q2hlY2tlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGF3cy5hY2NvdW50KCk7XG4gICAgICBzYW5pdHlDaGVja2VkID0gdHJ1ZTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHNhbml0eUNoZWNrZWQgPSBmYWxzZTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQVdTIGNyZWRlbnRpYWxzIHByb2JhYmx5IG5vdCBjb25maWd1cmVkLCBnb3QgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuICBpZiAoIXNhbml0eUNoZWNrZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0FXUyBjcmVkZW50aWFscyBwcm9iYWJseSBub3QgY29uZmlndXJlZCwgc2VlIHByZXZpb3VzIGVycm9yJyk7XG4gIH1cbn1cbmxldCBzYW5pdHlDaGVja2VkOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuIl19
60
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l0aC1hd3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ3aXRoLWF3cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVlBLDBCQVVDO0FBR0QsZ0NBY0M7QUF2Q0QsK0JBQW1DO0FBRW5DLG1EQUErQztBQUsvQzs7OztHQUlHO0FBQ0gsU0FBZ0IsT0FBTyxDQUNyQixLQUEyRSxFQUMzRSxtQkFBNEIsS0FBSztJQUVqQyxPQUFPLENBQUMsT0FBVSxFQUFFLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ3pELE1BQU0sR0FBRyxHQUFHLE1BQU0sZ0JBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvRCxNQUFNLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUV2QixPQUFPLEtBQUssQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDdEQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxXQUFxQyxDQUFDO0FBQzFDLFNBQWdCLFVBQVU7O0lBQ3hCLElBQUksV0FBVyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVc7UUFDckMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFDcEMsQ0FBQyxDQUFDLENBQUMsTUFBQSxNQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxtQ0FBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixtQ0FBSSxXQUFXLENBQUMsQ0FBQztJQUU5RSxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUUzQyxXQUFXLEdBQUcsNEJBQVksQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2pFLE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsS0FBSyxVQUFVLFdBQVcsQ0FBQyxHQUFlO0lBQ3hDLElBQUksYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDdkIsQ0FBQztRQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7WUFDaEIsYUFBYSxHQUFHLEtBQUssQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUN0RixDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDZEQUE2RCxDQUFDLENBQUM7SUFDakYsQ0FBQztBQUNILENBQUM7QUFDRCxJQUFJLGFBQWtDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBd3NDbGllbnRzIH0gZnJvbSAnLi9hd3MnO1xuaW1wb3J0IHsgVGVzdENvbnRleHQgfSBmcm9tICcuL2ludGVnLXRlc3QnO1xuaW1wb3J0IHsgUmVzb3VyY2VQb29sIH0gZnJvbSAnLi9yZXNvdXJjZS1wb29sJztcbmltcG9ydCB7IERpc2FibGVCb290c3RyYXBDb250ZXh0IH0gZnJvbSAnLi93aXRoLWNkay1hcHAnO1xuXG5leHBvcnQgdHlwZSBBd3NDb250ZXh0ID0geyByZWFkb25seSBhd3M6IEF3c0NsaWVudHMgfTtcblxuLyoqXG4gKiBIaWdoZXIgb3JkZXIgZnVuY3Rpb24gdG8gZXhlY3V0ZSBhIGJsb2NrIHdpdGggYW4gQVdTIGNsaWVudCBzZXR1cFxuICpcbiAqIEFsbG9jYXRlIHRoZSBuZXh0IHJlZ2lvbiBmcm9tIHRoZSBSRUdJT04gcG9vbCBhbmQgZGlzcG9zZSBpdCBhZnRlcndhcmRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2l0aEF3czxBIGV4dGVuZHMgVGVzdENvbnRleHQ+KFxuICBibG9jazogKGNvbnRleHQ6IEEgJiBBd3NDb250ZXh0ICYgRGlzYWJsZUJvb3RzdHJhcENvbnRleHQpID0+IFByb21pc2U8dm9pZD4sXG4gIGRpc2FibGVCb290c3RyYXA6IGJvb2xlYW4gPSBmYWxzZSxcbik6IChjb250ZXh0OiBBKSA9PiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIChjb250ZXh0OiBBKSA9PiByZWdpb25Qb29sKCkudXNpbmcoYXN5bmMgKHJlZ2lvbikgPT4ge1xuICAgIGNvbnN0IGF3cyA9IGF3YWl0IEF3c0NsaWVudHMuZm9yUmVnaW9uKHJlZ2lvbiwgY29udGV4dC5vdXRwdXQpO1xuICAgIGF3YWl0IHNhbml0eUNoZWNrKGF3cyk7XG5cbiAgICByZXR1cm4gYmxvY2soeyAuLi5jb250ZXh0LCBkaXNhYmxlQm9vdHN0cmFwLCBhd3MgfSk7XG4gIH0pO1xufVxuXG5sZXQgX3JlZ2lvblBvb2w6IHVuZGVmaW5lZCB8IFJlc291cmNlUG9vbDtcbmV4cG9ydCBmdW5jdGlvbiByZWdpb25Qb29sKCk6IFJlc291cmNlUG9vbCB7XG4gIGlmIChfcmVnaW9uUG9vbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIF9yZWdpb25Qb29sO1xuICB9XG5cbiAgY29uc3QgUkVHSU9OUyA9IHByb2Nlc3MuZW52LkFXU19SRUdJT05TXG4gICAgPyBwcm9jZXNzLmVudi5BV1NfUkVHSU9OUy5zcGxpdCgnLCcpXG4gICAgOiBbcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiA/PyBwcm9jZXNzLmVudi5BV1NfREVGQVVMVF9SRUdJT04gPz8gJ3VzLWVhc3QtMSddO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gIGNvbnNvbGUubG9nKGBVc2luZyByZWdpb25zOiAke1JFR0lPTlN9XFxuYCk7XG5cbiAgX3JlZ2lvblBvb2wgPSBSZXNvdXJjZVBvb2wud2l0aFJlc291cmNlcygnYXdzX3JlZ2lvbnMnLCBSRUdJT05TKTtcbiAgcmV0dXJuIF9yZWdpb25Qb29sO1xufVxuXG4vKipcbiAqIFBlcmZvcm0gYSBvbmUtdGltZSBxdWljayBzYW5pdHkgY2hlY2sgdGhhdCB0aGUgQVdTIGNsaWVudHMgaGF2ZSBwcm9wZXJseSBjb25maWd1cmVkIGNyZWRlbnRpYWxzXG4gKlxuICogSWYgd2UgZG9uJ3QgZG8gdGhpcywgY2FsbHMgYXJlIGdvaW5nIHRvIGZhaWwgYW5kIHRoZXknbGwgYmUgcmV0cmllZCBhbmQgZXZlcnl0aGluZyB3aWxsIHRha2VcbiAqIGZvcmV2ZXIgYmVmb3JlIHRoZSB1c2VyIG5vdGljZXMgYSBzaW1wbGUgbWlzY29uZmlndXJhdGlvbi5cbiAqXG4gKiBXZSBjYW4ndCBjaGVjayBmb3IgdGhlIHByZXNlbmNlIG9mIGVudmlyb25tZW50IHZhcmlhYmxlcyBzaW5jZSBjcmVkZW50aWFscyBjb3VsZCBjb21lIGZyb21cbiAqIGFueXdoZXJlLCBzbyBkbyBzaW1wbGUgYWNjb3VudCByZXRyaWV2YWwuXG4gKlxuICogT25seSBkbyBpdCBvbmNlIHBlciBwcm9jZXNzLlxuICovXG5hc3luYyBmdW5jdGlvbiBzYW5pdHlDaGVjayhhd3M6IEF3c0NsaWVudHMpIHtcbiAgaWYgKHNhbml0eUNoZWNrZWQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBhd3MuYWNjb3VudCgpO1xuICAgICAgc2FuaXR5Q2hlY2tlZCA9IHRydWU7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBzYW5pdHlDaGVja2VkID0gZmFsc2U7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEFXUyBjcmVkZW50aWFscyBwcm9iYWJseSBub3QgY29uZmlndXJlZCwgZ290IGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFzYW5pdHlDaGVja2VkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBV1MgY3JlZGVudGlhbHMgcHJvYmFibHkgbm90IGNvbmZpZ3VyZWQsIHNlZSBwcmV2aW91cyBlcnJvcicpO1xuICB9XG59XG5sZXQgc2FuaXR5Q2hlY2tlZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiJdfQ==
@@ -0,0 +1,67 @@
1
+ import { AwsClients } from './aws';
2
+ import { TestContext } from './integ-test';
3
+ import { ResourcePool } from './resource-pool';
4
+ import { DisableBootstrapContext } from './with-cdk-app';
5
+
6
+ export type AwsContext = { readonly aws: AwsClients };
7
+
8
+ /**
9
+ * Higher order function to execute a block with an AWS client setup
10
+ *
11
+ * Allocate the next region from the REGION pool and dispose it afterwards.
12
+ */
13
+ export function withAws<A extends TestContext>(
14
+ block: (context: A & AwsContext & DisableBootstrapContext) => Promise<void>,
15
+ disableBootstrap: boolean = false,
16
+ ): (context: A) => Promise<void> {
17
+ return (context: A) => regionPool().using(async (region) => {
18
+ const aws = await AwsClients.forRegion(region, context.output);
19
+ await sanityCheck(aws);
20
+
21
+ return block({ ...context, disableBootstrap, aws });
22
+ });
23
+ }
24
+
25
+ let _regionPool: undefined | ResourcePool;
26
+ export function regionPool(): ResourcePool {
27
+ if (_regionPool !== undefined) {
28
+ return _regionPool;
29
+ }
30
+
31
+ const REGIONS = process.env.AWS_REGIONS
32
+ ? process.env.AWS_REGIONS.split(',')
33
+ : [process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1'];
34
+
35
+ // eslint-disable-next-line no-console
36
+ console.log(`Using regions: ${REGIONS}\n`);
37
+
38
+ _regionPool = ResourcePool.withResources('aws_regions', REGIONS);
39
+ return _regionPool;
40
+ }
41
+
42
+ /**
43
+ * Perform a one-time quick sanity check that the AWS clients have properly configured credentials
44
+ *
45
+ * If we don't do this, calls are going to fail and they'll be retried and everything will take
46
+ * forever before the user notices a simple misconfiguration.
47
+ *
48
+ * We can't check for the presence of environment variables since credentials could come from
49
+ * anywhere, so do simple account retrieval.
50
+ *
51
+ * Only do it once per process.
52
+ */
53
+ async function sanityCheck(aws: AwsClients) {
54
+ if (sanityChecked === undefined) {
55
+ try {
56
+ await aws.account();
57
+ sanityChecked = true;
58
+ } catch (e: any) {
59
+ sanityChecked = false;
60
+ throw new Error(`AWS credentials probably not configured, got error: ${e.message}`);
61
+ }
62
+ }
63
+ if (!sanityChecked) {
64
+ throw new Error('AWS credentials probably not configured, see previous error');
65
+ }
66
+ }
67
+ let sanityChecked: boolean | undefined;