@aws-cdk-testing/cli-integ 0.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 (257) hide show
  1. package/.eslintrc.js +9 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +16 -0
  4. package/README.md +205 -0
  5. package/bin/apply-patches +22 -0
  6. package/bin/download-and-run-old-tests +52 -0
  7. package/bin/query-github +2 -0
  8. package/bin/query-github.d.ts +1 -0
  9. package/bin/query-github.js +54 -0
  10. package/bin/query-github.ts +56 -0
  11. package/bin/run-suite +2 -0
  12. package/bin/run-suite.d.ts +1 -0
  13. package/bin/run-suite.js +131 -0
  14. package/bin/run-suite.ts +140 -0
  15. package/bin/stage-distribution +2 -0
  16. package/bin/stage-distribution.d.ts +1 -0
  17. package/bin/stage-distribution.js +217 -0
  18. package/bin/stage-distribution.ts +267 -0
  19. package/bin/test-root +2 -0
  20. package/bin/test-root.d.ts +1 -0
  21. package/bin/test-root.js +6 -0
  22. package/bin/test-root.ts +3 -0
  23. package/entrypoints/test-cli-regression-against-current-code.sh +11 -0
  24. package/entrypoints/test-cli-regression-against-latest-release.sh +11 -0
  25. package/entrypoints/test-cli-regression.bash +83 -0
  26. package/entrypoints/test.sh +12 -0
  27. package/lib/aws.d.ts +51 -0
  28. package/lib/aws.js +206 -0
  29. package/lib/aws.ts +263 -0
  30. package/lib/corking.d.ts +12 -0
  31. package/lib/corking.js +35 -0
  32. package/lib/corking.ts +33 -0
  33. package/lib/eventually.d.ts +20 -0
  34. package/lib/eventually.js +34 -0
  35. package/lib/eventually.ts +42 -0
  36. package/lib/files.d.ts +15 -0
  37. package/lib/files.js +80 -0
  38. package/lib/files.ts +80 -0
  39. package/lib/github.d.ts +4 -0
  40. package/lib/github.js +43 -0
  41. package/lib/github.ts +43 -0
  42. package/lib/index.d.ts +13 -0
  43. package/lib/index.js +30 -0
  44. package/lib/index.ts +13 -0
  45. package/lib/integ-test.d.ts +10 -0
  46. package/lib/integ-test.js +70 -0
  47. package/lib/integ-test.ts +81 -0
  48. package/lib/lists.d.ts +1 -0
  49. package/lib/lists.js +11 -0
  50. package/lib/lists.ts +9 -0
  51. package/lib/memoize.d.ts +6 -0
  52. package/lib/memoize.js +18 -0
  53. package/lib/memoize.ts +14 -0
  54. package/lib/npm.d.ts +8 -0
  55. package/lib/npm.js +38 -0
  56. package/lib/npm.ts +41 -0
  57. package/lib/package-sources/release-source.d.ts +23 -0
  58. package/lib/package-sources/release-source.js +71 -0
  59. package/lib/package-sources/release-source.ts +81 -0
  60. package/lib/package-sources/repo-source.d.ts +30 -0
  61. package/lib/package-sources/repo-source.js +97 -0
  62. package/lib/package-sources/repo-source.ts +111 -0
  63. package/lib/package-sources/repo-tools/npm +2 -0
  64. package/lib/package-sources/repo-tools/npm.d.ts +1 -0
  65. package/lib/package-sources/repo-tools/npm.js +43 -0
  66. package/lib/package-sources/repo-tools/npm.ts +48 -0
  67. package/lib/package-sources/source.d.ts +28 -0
  68. package/lib/package-sources/source.js +3 -0
  69. package/lib/package-sources/source.ts +35 -0
  70. package/lib/package-sources/subprocess.d.ts +3 -0
  71. package/lib/package-sources/subprocess.js +17 -0
  72. package/lib/package-sources/subprocess.ts +15 -0
  73. package/lib/resource-pool.d.ts +50 -0
  74. package/lib/resource-pool.js +117 -0
  75. package/lib/resource-pool.ts +140 -0
  76. package/lib/resources.d.ts +1 -0
  77. package/lib/resources.js +6 -0
  78. package/lib/resources.ts +4 -0
  79. package/lib/shell.d.ts +56 -0
  80. package/lib/shell.js +123 -0
  81. package/lib/shell.ts +168 -0
  82. package/lib/staging/codeartifact.d.ts +44 -0
  83. package/lib/staging/codeartifact.js +281 -0
  84. package/lib/staging/codeartifact.ts +387 -0
  85. package/lib/staging/maven.d.ts +5 -0
  86. package/lib/staging/maven.js +91 -0
  87. package/lib/staging/maven.ts +95 -0
  88. package/lib/staging/npm.d.ts +4 -0
  89. package/lib/staging/npm.js +55 -0
  90. package/lib/staging/npm.ts +62 -0
  91. package/lib/staging/nuget.d.ts +4 -0
  92. package/lib/staging/nuget.js +69 -0
  93. package/lib/staging/nuget.ts +75 -0
  94. package/lib/staging/parallel-shell.d.ts +5 -0
  95. package/lib/staging/parallel-shell.js +45 -0
  96. package/lib/staging/parallel-shell.ts +51 -0
  97. package/lib/staging/pypi.d.ts +4 -0
  98. package/lib/staging/pypi.js +48 -0
  99. package/lib/staging/pypi.ts +50 -0
  100. package/lib/staging/usage-dir.d.ts +31 -0
  101. package/lib/staging/usage-dir.js +87 -0
  102. package/lib/staging/usage-dir.ts +99 -0
  103. package/lib/with-aws.d.ts +14 -0
  104. package/lib/with-aws.js +60 -0
  105. package/lib/with-aws.ts +67 -0
  106. package/lib/with-cdk-app.d.ts +210 -0
  107. package/lib/with-cdk-app.js +539 -0
  108. package/lib/with-cdk-app.ts +742 -0
  109. package/lib/with-cli-lib.d.ts +17 -0
  110. package/lib/with-cli-lib.js +123 -0
  111. package/lib/with-cli-lib.ts +134 -0
  112. package/lib/with-packages.d.ts +5 -0
  113. package/lib/with-packages.js +13 -0
  114. package/lib/with-packages.ts +15 -0
  115. package/lib/with-sam.d.ts +33 -0
  116. package/lib/with-sam.js +258 -0
  117. package/lib/with-sam.ts +288 -0
  118. package/lib/with-temporary-directory.d.ts +5 -0
  119. package/lib/with-temporary-directory.js +31 -0
  120. package/lib/with-temporary-directory.ts +35 -0
  121. package/lib/with-timeout.d.ts +19 -0
  122. package/lib/with-timeout.js +34 -0
  123. package/lib/with-timeout.ts +33 -0
  124. package/lib/xpmutex.d.ts +43 -0
  125. package/lib/xpmutex.js +207 -0
  126. package/lib/xpmutex.ts +218 -0
  127. package/package.json +111 -0
  128. package/resources/bootstrap-templates/session-tags.all-roles-deny-all.yaml +703 -0
  129. package/resources/bootstrap-templates/session-tags.deploy-role-deny-sqs.yaml +700 -0
  130. package/resources/cdk-apps/app/app.js +926 -0
  131. package/resources/cdk-apps/app/appsync.hotswap.graphql +3 -0
  132. package/resources/cdk-apps/app/cdk.json +7 -0
  133. package/resources/cdk-apps/app/docker/Dockerfile +2 -0
  134. package/resources/cdk-apps/app/docker/Dockerfile.Custom +2 -0
  135. package/resources/cdk-apps/app/lambda/index.js +4 -0
  136. package/resources/cdk-apps/app/lambda/response.json +3 -0
  137. package/resources/cdk-apps/app/nested-stack.js +65 -0
  138. package/resources/cdk-apps/cfn-include-app/cdk.json +4 -0
  139. package/resources/cdk-apps/cfn-include-app/cfn-include-app.js +21 -0
  140. package/resources/cdk-apps/cfn-include-app/example-template.json +13 -0
  141. package/resources/cdk-apps/rollback-test-app/app.js +110 -0
  142. package/resources/cdk-apps/rollback-test-app/cdk.json +7 -0
  143. package/resources/cdk-apps/sam_cdk_integ_app/bin/test-app.js +11 -0
  144. package/resources/cdk-apps/sam_cdk_integ_app/cdk.json +6 -0
  145. package/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js +19 -0
  146. package/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js +134 -0
  147. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/.no-packagejson-validator +0 -0
  148. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/Dockerfile +9 -0
  149. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/app.js +22 -0
  150. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/package.json +18 -0
  151. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/go.mod +5 -0
  152. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/go.sum +17 -0
  153. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/main.go +17 -0
  154. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/.no-packagejson-validator +0 -0
  155. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/app.ts +16 -0
  156. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/package-lock.json +12 -0
  157. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/package.json +5 -0
  158. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Function/app.py +15 -0
  159. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Function/requirements.txt +1 -0
  160. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Layer/layer_version_dependency.py +5 -0
  161. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Layer/requirements.txt +1 -0
  162. package/resources/cdk-apps/sam_cdk_integ_app/src/rest-api-definition.yaml +12 -0
  163. package/resources/cdk-apps/simple-app/app.js +26 -0
  164. package/resources/cdk-apps/simple-app/cdk.json +7 -0
  165. package/resources/cli-regression-patches/v1.119.0/NOTES.md +5 -0
  166. package/resources/cli-regression-patches/v1.119.0/cli.integtest.js +659 -0
  167. package/resources/cli-regression-patches/v1.130.0/NOTES.md +12 -0
  168. package/resources/cli-regression-patches/v1.130.0/app/app.js +378 -0
  169. package/resources/cli-regression-patches/v1.130.0/bootstrapping.integtest.js +220 -0
  170. package/resources/cli-regression-patches/v1.44.0/NOTES.md +18 -0
  171. package/resources/cli-regression-patches/v1.44.0/bootstrapping.integtest.js +126 -0
  172. package/resources/cli-regression-patches/v1.44.0/test.sh +26 -0
  173. package/resources/cli-regression-patches/v1.61.1/NOTES.md +2 -0
  174. package/resources/cli-regression-patches/v1.61.1/skip-tests.txt +16 -0
  175. package/resources/cli-regression-patches/v1.62.0/NOTES.md +2 -0
  176. package/resources/cli-regression-patches/v1.62.0/aws-helpers.js +245 -0
  177. package/resources/cli-regression-patches/v1.63.0/NOTES.md +1 -0
  178. package/resources/cli-regression-patches/v1.63.0/skip-tests.txt +7 -0
  179. package/resources/cli-regression-patches/v1.64.0/NOTES.md +3 -0
  180. package/resources/cli-regression-patches/v1.64.0/cdk-helpers.js +325 -0
  181. package/resources/cli-regression-patches/v1.64.0/cli.integtest.js +599 -0
  182. package/resources/cli-regression-patches/v1.64.1/NOTES.md +3 -0
  183. package/resources/cli-regression-patches/v1.64.1/cdk-helpers.js +324 -0
  184. package/resources/cli-regression-patches/v1.64.1/cli.integtest.js +599 -0
  185. package/resources/cli-regression-patches/v1.67.0/NOTES.md +2 -0
  186. package/resources/cli-regression-patches/v1.67.0/cdk-helpers.js +331 -0
  187. package/resources/cli-regression-patches/v2.130.0/NOTES.md +1 -0
  188. package/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js +19 -0
  189. package/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js +134 -0
  190. package/resources/cli-regression-patches/v2.130.0/skip-tests.txt +5 -0
  191. package/resources/cli-regression-patches/v2.132.0/NOTES.md +1 -0
  192. package/resources/cli-regression-patches/v2.132.0/skip-tests.txt +4 -0
  193. package/resources/cli-regression-patches/v2.142.0/NOTES.md +1 -0
  194. package/resources/cli-regression-patches/v2.142.0/skip-tests.txt +4 -0
  195. package/resources/cli-regression-patches/v2.160.0/skip-tests.txt +2 -0
  196. package/resources/cli-regression-patches/v2.161.0/NOTES.md +1 -0
  197. package/resources/cli-regression-patches/v2.161.0/skip-tests.txt +5 -0
  198. package/resources/cli-regression-patches/v2.166.0/NOTES.md +1 -0
  199. package/resources/cli-regression-patches/v2.166.0/skip-tests.txt +2 -0
  200. package/resources/cloud-assemblies/0.36.0/InitStack.template.json +1 -0
  201. package/resources/cloud-assemblies/0.36.0/cdk.out +1 -0
  202. package/resources/cloud-assemblies/0.36.0/manifest.json +19 -0
  203. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/InitStack.template.json +2 -0
  204. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/cdk.out +1 -0
  205. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/manifest.json.js +37 -0
  206. package/resources/cloud-assemblies/1.10.0-request-azs/InitStack.template.json +2 -0
  207. package/resources/cloud-assemblies/1.10.0-request-azs/cdk.out +1 -0
  208. package/resources/cloud-assemblies/1.10.0-request-azs/manifest.json.js +34 -0
  209. package/resources/integ.jest.config.js +25 -0
  210. package/resources/templates/sqs-template.json +36 -0
  211. package/skip-tests.txt +8 -0
  212. package/tests/cli-integ-tests/README.md +47 -0
  213. package/tests/cli-integ-tests/bootstrapping.integtest.d.ts +1 -0
  214. package/tests/cli-integ-tests/bootstrapping.integtest.js +412 -0
  215. package/tests/cli-integ-tests/bootstrapping.integtest.ts +493 -0
  216. package/tests/cli-integ-tests/cli-lib.integtest.d.ts +1 -0
  217. package/tests/cli-integ-tests/cli-lib.integtest.js +62 -0
  218. package/tests/cli-integ-tests/cli-lib.integtest.ts +90 -0
  219. package/tests/cli-integ-tests/cli.integtest.d.ts +1 -0
  220. package/tests/cli-integ-tests/cli.integtest.js +2104 -0
  221. package/tests/cli-integ-tests/cli.integtest.ts +2874 -0
  222. package/tests/cli-integ-tests/garbage-collection.integtest.d.ts +1 -0
  223. package/tests/cli-integ-tests/garbage-collection.integtest.js +314 -0
  224. package/tests/cli-integ-tests/garbage-collection.integtest.ts +392 -0
  225. package/tests/init-csharp/init-csharp.integtest.d.ts +1 -0
  226. package/tests/init-csharp/init-csharp.integtest.js +14 -0
  227. package/tests/init-csharp/init-csharp.integtest.ts +15 -0
  228. package/tests/init-fsharp/init-fsharp.integtest.d.ts +1 -0
  229. package/tests/init-fsharp/init-fsharp.integtest.js +14 -0
  230. package/tests/init-fsharp/init-fsharp.integtest.ts +15 -0
  231. package/tests/init-go/init-go.integtest.d.ts +1 -0
  232. package/tests/init-go/init-go.integtest.js +21 -0
  233. package/tests/init-go/init-go.integtest.ts +23 -0
  234. package/tests/init-java/init-java.integtest.d.ts +1 -0
  235. package/tests/init-java/init-java.integtest.js +14 -0
  236. package/tests/init-java/init-java.integtest.ts +14 -0
  237. package/tests/init-javascript/init-javascript.integtest.d.ts +1 -0
  238. package/tests/init-javascript/init-javascript.integtest.js +53 -0
  239. package/tests/init-javascript/init-javascript.integtest.ts +59 -0
  240. package/tests/init-python/init-python.integtest.d.ts +1 -0
  241. package/tests/init-python/init-python.integtest.js +19 -0
  242. package/tests/init-python/init-python.integtest.ts +20 -0
  243. package/tests/init-typescript-app/init-typescript-app.integtest.d.ts +1 -0
  244. package/tests/init-typescript-app/init-typescript-app.integtest.js +54 -0
  245. package/tests/init-typescript-app/init-typescript-app.integtest.ts +66 -0
  246. package/tests/init-typescript-lib/init-typescript-lib.integtest.d.ts +1 -0
  247. package/tests/init-typescript-lib/init-typescript-lib.integtest.js +13 -0
  248. package/tests/init-typescript-lib/init-typescript-lib.integtest.ts +13 -0
  249. package/tests/tool-integrations/amplify.integtest.d.ts +1 -0
  250. package/tests/tool-integrations/amplify.integtest.js +39 -0
  251. package/tests/tool-integrations/amplify.integtest.ts +43 -0
  252. package/tests/tool-integrations/with-tool-context.d.ts +9 -0
  253. package/tests/tool-integrations/with-tool-context.js +13 -0
  254. package/tests/tool-integrations/with-tool-context.ts +14 -0
  255. package/tests/uberpackage/uberpackage.integtest.d.ts +1 -0
  256. package/tests/uberpackage/uberpackage.integtest.js +11 -0
  257. package/tests/uberpackage/uberpackage.integtest.ts +11 -0
@@ -0,0 +1,387 @@
1
+ import {
2
+ AssociateExternalConnectionCommand,
3
+ CodeartifactClient,
4
+ CreateDomainCommand,
5
+ CreateRepositoryCommand,
6
+ DeleteRepositoryCommand,
7
+ DescribeDomainCommand,
8
+ DescribeRepositoryCommand,
9
+ GetAuthorizationTokenCommand,
10
+ GetRepositoryEndpointCommand,
11
+ ListPackagesCommand,
12
+ ListPackagesRequest,
13
+ ListRepositoriesCommand,
14
+ ListTagsForResourceCommand,
15
+ PutPackageOriginConfigurationCommand,
16
+ } from '@aws-sdk/client-codeartifact';
17
+ import { sleep } from '../aws';
18
+
19
+ const COLLECT_BY_TAG = 'collect-by';
20
+ const REPO_LIFETIME_MS = 24 * 3600 * 1000; // One day
21
+
22
+ export class TestRepository {
23
+ public static readonly DEFAULT_DOMAIN = 'test-cdk';
24
+
25
+ public static async newRandom() {
26
+ const qualifier = Math.random()
27
+ .toString(36)
28
+ .replace(/[^a-z0-9]+/g, '');
29
+
30
+ const repo = new TestRepository(`test-${qualifier}`);
31
+ await repo.prepare();
32
+ return repo;
33
+ }
34
+
35
+ public static async newWithName(name: string) {
36
+ const repo = new TestRepository(name);
37
+ await repo.prepare();
38
+ return repo;
39
+ }
40
+
41
+ public static existing(repositoryName: string) {
42
+ return new TestRepository(repositoryName);
43
+ }
44
+
45
+ /**
46
+ * Garbage collect repositories
47
+ */
48
+ public static async gc() {
49
+ if (!(await TestRepository.existing('*dummy*').domainExists())) {
50
+ return;
51
+ }
52
+
53
+ const codeArtifact = new CodeartifactClient();
54
+
55
+ let nextToken: string | undefined;
56
+ do {
57
+ const page = await codeArtifact.send(
58
+ new ListRepositoriesCommand({
59
+ nextToken: nextToken,
60
+ }),
61
+ );
62
+
63
+ for (const repo of page.repositories ?? []) {
64
+ const tags = await codeArtifact.send(
65
+ new ListTagsForResourceCommand({
66
+ resourceArn: repo.arn!,
67
+ }),
68
+ );
69
+ const collectable = tags?.tags?.find((t) => t.key === COLLECT_BY_TAG && Number(t.value) < Date.now());
70
+ if (collectable) {
71
+ // eslint-disable-next-line no-console
72
+ console.log('Deleting', repo.name);
73
+ await codeArtifact.send(
74
+ new DeleteRepositoryCommand({
75
+ domain: repo.domainName!,
76
+ repository: repo.name!,
77
+ }),
78
+ );
79
+ }
80
+ }
81
+
82
+ nextToken = page.nextToken;
83
+ } while (nextToken);
84
+ }
85
+
86
+ public readonly npmUpstream = 'npm-upstream';
87
+ public readonly pypiUpstream = 'pypi-upstream';
88
+ public readonly nugetUpstream = 'nuget-upstream';
89
+ public readonly mavenUpstream = 'maven-upstream';
90
+ public readonly domain = TestRepository.DEFAULT_DOMAIN;
91
+
92
+ private readonly codeArtifact = new CodeartifactClient();
93
+
94
+ private _loginInformation: LoginInformation | undefined;
95
+
96
+ private constructor(public readonly repositoryName: string) {}
97
+
98
+ public async prepare() {
99
+ await this.ensureDomain();
100
+ await this.ensureUpstreams();
101
+
102
+ await this.ensureRepository(this.repositoryName, {
103
+ description: 'Testing repository',
104
+ upstreams: [this.npmUpstream, this.pypiUpstream, this.nugetUpstream, this.mavenUpstream],
105
+ tags: {
106
+ [COLLECT_BY_TAG]: `${Date.now() + REPO_LIFETIME_MS}`,
107
+ },
108
+ });
109
+ }
110
+
111
+ public async loginInformation(): Promise<LoginInformation> {
112
+ if (this._loginInformation) {
113
+ return this._loginInformation;
114
+ }
115
+
116
+ this._loginInformation = {
117
+ authToken: (
118
+ await this.codeArtifact.send(
119
+ new GetAuthorizationTokenCommand({
120
+ domain: this.domain,
121
+ durationSeconds: 12 * 3600,
122
+ }),
123
+ )
124
+ ).authorizationToken!,
125
+ repositoryName: this.repositoryName,
126
+
127
+ npmEndpoint: (
128
+ await this.codeArtifact.send(
129
+ new GetRepositoryEndpointCommand({
130
+ domain: this.domain,
131
+ repository: this.repositoryName,
132
+ format: 'npm',
133
+ }),
134
+ )
135
+ ).repositoryEndpoint!,
136
+
137
+ mavenEndpoint: (
138
+ await this.codeArtifact.send(
139
+ new GetRepositoryEndpointCommand({
140
+ domain: this.domain,
141
+ repository: this.repositoryName,
142
+ format: 'maven',
143
+ }),
144
+ )
145
+ ).repositoryEndpoint!,
146
+
147
+ nugetEndpoint: (
148
+ await this.codeArtifact.send(
149
+ new GetRepositoryEndpointCommand({
150
+ domain: this.domain,
151
+ repository: this.repositoryName,
152
+ format: 'nuget',
153
+ }),
154
+ )
155
+ ).repositoryEndpoint!,
156
+
157
+ pypiEndpoint: (
158
+ await this.codeArtifact.send(
159
+ new GetRepositoryEndpointCommand({
160
+ domain: this.domain,
161
+ repository: this.repositoryName,
162
+ format: 'pypi',
163
+ }),
164
+ )
165
+ ).repositoryEndpoint!,
166
+ };
167
+ return this._loginInformation;
168
+ }
169
+
170
+ public async delete() {
171
+ try {
172
+ await this.codeArtifact.send(
173
+ new DeleteRepositoryCommand({
174
+ domain: this.domain,
175
+ repository: this.repositoryName,
176
+ }),
177
+ );
178
+
179
+ // eslint-disable-next-line no-console
180
+ console.log('Deleted', this.repositoryName);
181
+ } catch (e: any) {
182
+ if (e.name !== 'ResourceNotFoundException') {
183
+ throw e;
184
+ }
185
+ // Okay
186
+ }
187
+ }
188
+
189
+ /**
190
+ * List all packages and mark them as "allow upstream versions".
191
+ *
192
+ * If we don't do this and we publish `foo@2.3.4-rc.0`, then we can't
193
+ * download `foo@2.3.0` anymore because by default CodeArtifact will
194
+ * block different versions from the same package.
195
+ */
196
+ public async markAllUpstreamAllow() {
197
+ for await (const pkg of this.listPackages({ upstream: 'BLOCK' })) {
198
+ await retryThrottled(() =>
199
+ this.codeArtifact.send(
200
+ new PutPackageOriginConfigurationCommand({
201
+ domain: this.domain,
202
+ repository: this.repositoryName,
203
+
204
+ format: pkg.format!,
205
+ package: pkg.package!,
206
+ namespace: pkg.namespace!,
207
+ restrictions: {
208
+ publish: 'ALLOW',
209
+ upstream: 'ALLOW',
210
+ },
211
+ }),
212
+ ),
213
+ );
214
+ }
215
+ }
216
+
217
+ private async ensureDomain() {
218
+ if (await this.domainExists()) {
219
+ return;
220
+ }
221
+ await this.codeArtifact.send(
222
+ new CreateDomainCommand({
223
+ domain: this.domain,
224
+ tags: [{ key: 'testing', value: 'true' }],
225
+ }),
226
+ );
227
+ }
228
+
229
+ private async ensureUpstreams() {
230
+ await this.ensureRepository(this.npmUpstream, {
231
+ description: 'The upstream repository for NPM',
232
+ external: 'public:npmjs',
233
+ });
234
+ await this.ensureRepository(this.mavenUpstream, {
235
+ description: 'The upstream repository for Maven',
236
+ external: 'public:maven-central',
237
+ });
238
+ await this.ensureRepository(this.nugetUpstream, {
239
+ description: 'The upstream repository for NuGet',
240
+ external: 'public:nuget-org',
241
+ });
242
+ await this.ensureRepository(this.pypiUpstream, {
243
+ description: 'The upstream repository for PyPI',
244
+ external: 'public:pypi',
245
+ });
246
+ }
247
+
248
+ private async ensureRepository(
249
+ name: string,
250
+ options?: {
251
+ readonly description?: string;
252
+ readonly external?: string;
253
+ readonly upstreams?: string[];
254
+ readonly tags?: Record<string, string>;
255
+ },
256
+ ) {
257
+ if (await this.repositoryExists(name)) {
258
+ return;
259
+ }
260
+
261
+ await this.codeArtifact.send(
262
+ new CreateRepositoryCommand({
263
+ domain: this.domain,
264
+ repository: name,
265
+ description: options?.description,
266
+ upstreams: options?.upstreams?.map((repositoryName) => ({ repositoryName })),
267
+ tags: options?.tags ? Object.entries(options.tags).map(([key, value]) => ({ key, value })) : undefined,
268
+ }),
269
+ );
270
+
271
+ if (options?.external) {
272
+ const externalConnection = options.external;
273
+ await retry(() =>
274
+ this.codeArtifact.send(
275
+ new AssociateExternalConnectionCommand({
276
+ domain: this.domain,
277
+ repository: name,
278
+ externalConnection,
279
+ }),
280
+ ),
281
+ );
282
+ }
283
+ }
284
+
285
+ private async domainExists() {
286
+ try {
287
+ await this.codeArtifact.send(new DescribeDomainCommand({ domain: this.domain }));
288
+ return true;
289
+ } catch (e: any) {
290
+ if (e.name !== 'ResourceNotFoundException') {
291
+ throw e;
292
+ }
293
+ return false;
294
+ }
295
+ }
296
+
297
+ private async repositoryExists(name: string) {
298
+ try {
299
+ await this.codeArtifact.send(new DescribeRepositoryCommand({ domain: this.domain, repository: name }));
300
+ return true;
301
+ } catch (e: any) {
302
+ if (e.name !== 'ResourceNotFoundException') {
303
+ throw e;
304
+ }
305
+ return false;
306
+ }
307
+ }
308
+
309
+ private async *listPackages(filter: Pick<ListPackagesRequest, 'upstream' | 'publish' | 'format'> = {}) {
310
+ let response = await retryThrottled(() =>
311
+ this.codeArtifact.send(
312
+ new ListPackagesCommand({
313
+ domain: this.domain,
314
+ repository: this.repositoryName,
315
+ ...filter,
316
+ }),
317
+ ),
318
+ );
319
+
320
+ while (true) {
321
+ for (const p of response.packages ?? []) {
322
+ yield p;
323
+ }
324
+
325
+ if (!response.nextToken) {
326
+ break;
327
+ }
328
+
329
+ response = await retryThrottled(() =>
330
+ this.codeArtifact.send(
331
+ new ListPackagesCommand({
332
+ domain: this.domain,
333
+ repository: this.repositoryName,
334
+ ...filter,
335
+ nextToken: response.nextToken,
336
+ }),
337
+ ),
338
+ );
339
+ }
340
+ }
341
+ }
342
+
343
+ async function retry<A>(block: () => Promise<A>) {
344
+ let attempts = 3;
345
+ while (true) {
346
+ try {
347
+ return await block();
348
+ } catch (e: any) {
349
+ if (attempts-- === 0) {
350
+ throw e;
351
+ }
352
+ // eslint-disable-next-line no-console
353
+ console.debug(e.message);
354
+ await sleep(500);
355
+ }
356
+ }
357
+ }
358
+
359
+ async function retryThrottled<A>(block: () => Promise<A>) {
360
+ let time = 100;
361
+ let attempts = 15;
362
+ while (true) {
363
+ try {
364
+ return await block();
365
+ } catch (e: any) {
366
+ // eslint-disable-next-line no-console
367
+ console.debug(e.message);
368
+ if (e.name !== 'ThrottlingException') {
369
+ throw e;
370
+ }
371
+ if (attempts-- === 0) {
372
+ throw e;
373
+ }
374
+ await sleep(Math.floor(Math.random() * time));
375
+ time *= 2;
376
+ }
377
+ }
378
+ }
379
+
380
+ export interface LoginInformation {
381
+ readonly authToken: string;
382
+ readonly repositoryName: string;
383
+ readonly npmEndpoint: string;
384
+ readonly mavenEndpoint: string;
385
+ readonly nugetEndpoint: string;
386
+ readonly pypiEndpoint: string;
387
+ }
@@ -0,0 +1,5 @@
1
+ import { LoginInformation } from './codeartifact';
2
+ import { UsageDir } from './usage-dir';
3
+ export declare function mavenLogin(login: LoginInformation, usageDir: UsageDir): Promise<void>;
4
+ export declare function uploadJavaPackages(packages: string[], login: LoginInformation, usageDir: UsageDir): Promise<void>;
5
+ export declare function writeMavenSettingsFile(filename: string, login: LoginInformation): Promise<void>;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mavenLogin = mavenLogin;
4
+ exports.uploadJavaPackages = uploadJavaPackages;
5
+ exports.writeMavenSettingsFile = writeMavenSettingsFile;
6
+ /* eslint-disable no-console */
7
+ const path = require("path");
8
+ const fs_extra_1 = require("fs-extra");
9
+ const parallel_shell_1 = require("./parallel-shell");
10
+ const files_1 = require("../files");
11
+ const shell_1 = require("../shell");
12
+ // Do not try to JIT the Maven binary
13
+ const NO_JIT = '-XX:+TieredCompilation -XX:TieredStopAtLevel=1';
14
+ async function mavenLogin(login, usageDir) {
15
+ var _a;
16
+ await writeMavenSettingsFile(settingsFile(usageDir), login);
17
+ // Write env var
18
+ // Twiddle JVM settings a bit to make Maven survive running on a CodeBuild box.
19
+ await usageDir.addToEnv({
20
+ MAVEN_OPTS: `-Duser.home=${usageDir.directory} ${NO_JIT} ${(_a = process.env.MAVEN_OPTS) !== null && _a !== void 0 ? _a : ''}`.trim(),
21
+ });
22
+ }
23
+ function settingsFile(usageDir) {
24
+ // If we configure usageDir as a fake home directory Maven will find this file.
25
+ // (No other way to configure the settings file as part of the environment).
26
+ return path.join(usageDir.directory, '.m2', 'settings.xml');
27
+ }
28
+ async function uploadJavaPackages(packages, login, usageDir) {
29
+ await (0, parallel_shell_1.parallelShell)(packages, async (pkg, output) => {
30
+ var _a;
31
+ console.log(`⏳ ${pkg}`);
32
+ const sourcesFile = pkg.replace(/.pom$/, '-sources.jar');
33
+ const javadocFile = pkg.replace(/.pom$/, '-javadoc.jar');
34
+ await (0, shell_1.shell)(['mvn',
35
+ `--settings=${settingsFile(usageDir)}`,
36
+ 'org.apache.maven.plugins:maven-deploy-plugin:3.0.0:deploy-file',
37
+ `-Durl=${login.mavenEndpoint}`,
38
+ '-DrepositoryId=codeartifact',
39
+ `-DpomFile=${pkg}`,
40
+ `-Dfile=${pkg.replace(/.pom$/, '.jar')}`,
41
+ ...await (0, fs_extra_1.pathExists)(sourcesFile) ? [`-Dsources=${sourcesFile}`] : [],
42
+ ...await (0, fs_extra_1.pathExists)(javadocFile) ? [`-Djavadoc=${javadocFile}`] : []], {
43
+ outputs: [output],
44
+ modEnv: {
45
+ // Do not try to JIT the Maven binary
46
+ MAVEN_OPTS: `${NO_JIT} ${(_a = process.env.MAVEN_OPTS) !== null && _a !== void 0 ? _a : ''}`.trim(),
47
+ },
48
+ });
49
+ console.log(`✅ ${pkg}`);
50
+ }, (pkg, output) => {
51
+ if (output.toString().includes('409 Conflict')) {
52
+ console.log(`❌ ${pkg}: already exists. Skipped.`);
53
+ return 'skip';
54
+ }
55
+ if (output.toString().includes('Too Many Requests')) {
56
+ console.log(`♻️ ${pkg}: Too many requests. Retrying.`);
57
+ return 'retry';
58
+ }
59
+ return 'fail';
60
+ });
61
+ }
62
+ async function writeMavenSettingsFile(filename, login) {
63
+ await (0, files_1.writeFile)(filename, `<?xml version="1.0" encoding="UTF-8" ?>
64
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
65
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
66
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
67
+ http://maven.apache.org/xsd/settings-1.0.0.xsd">
68
+ <servers>
69
+ <server>
70
+ <id>codeartifact</id>
71
+ <username>aws</username>
72
+ <password>${login.authToken}</password>
73
+ </server>
74
+ </servers>
75
+ <profiles>
76
+ <profile>
77
+ <id>default</id>
78
+ <repositories>
79
+ <repository>
80
+ <id>codeartifact</id>
81
+ <url>${login.mavenEndpoint}</url>
82
+ </repository>
83
+ </repositories>
84
+ </profile>
85
+ </profiles>
86
+ <activeProfiles>
87
+ <activeProfile>default</activeProfile>
88
+ </activeProfiles>
89
+ </settings>`);
90
+ }
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF2ZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtYXZlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVlBLGdDQVFDO0FBUUQsZ0RBb0NDO0FBRUQsd0RBNEJDO0FBOUZELCtCQUErQjtBQUMvQiw2QkFBNkI7QUFDN0IsdUNBQXNDO0FBRXRDLHFEQUFpRDtBQUVqRCxvQ0FBcUM7QUFDckMsb0NBQWlDO0FBRWpDLHFDQUFxQztBQUNyQyxNQUFNLE1BQU0sR0FBRyxnREFBZ0QsQ0FBQztBQUV6RCxLQUFLLFVBQVUsVUFBVSxDQUFDLEtBQXVCLEVBQUUsUUFBa0I7O0lBQzFFLE1BQU0sc0JBQXNCLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRTVELGdCQUFnQjtJQUNoQiwrRUFBK0U7SUFDL0UsTUFBTSxRQUFRLENBQUMsUUFBUSxDQUFDO1FBQ3RCLFVBQVUsRUFBRSxlQUFlLFFBQVEsQ0FBQyxTQUFTLElBQUksTUFBTSxJQUFJLE1BQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLG1DQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRTtLQUNqRyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsUUFBa0I7SUFDdEMsK0VBQStFO0lBQy9FLDRFQUE0RTtJQUM1RSxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDOUQsQ0FBQztBQUVNLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxRQUFrQixFQUFFLEtBQXVCLEVBQUUsUUFBa0I7SUFDdEcsTUFBTSxJQUFBLDhCQUFhLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEVBQUU7O1FBQ2xELE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBRXhCLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBRXpELE1BQU0sSUFBQSxhQUFLLEVBQUMsQ0FBQyxLQUFLO1lBQ2hCLGNBQWMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ3RDLGdFQUFnRTtZQUNoRSxTQUFTLEtBQUssQ0FBQyxhQUFhLEVBQUU7WUFDOUIsNkJBQTZCO1lBQzdCLGFBQWEsR0FBRyxFQUFFO1lBQ2xCLFVBQVUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDeEMsR0FBRyxNQUFNLElBQUEscUJBQVUsRUFBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDcEUsR0FBRyxNQUFNLElBQUEscUJBQVUsRUFBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ3ZFLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUNqQixNQUFNLEVBQUU7Z0JBQ04scUNBQXFDO2dCQUNyQyxVQUFVLEVBQUUsR0FBRyxNQUFNLElBQUksTUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsbUNBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxFQUFFO2FBQy9EO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxFQUNELENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2QsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7WUFDL0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsNEJBQTRCLENBQUMsQ0FBQztZQUNsRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUNwRCxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxnQ0FBZ0MsQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFTSxLQUFLLFVBQVUsc0JBQXNCLENBQUMsUUFBZ0IsRUFBRSxLQUF1QjtJQUNwRixNQUFNLElBQUEsaUJBQVMsRUFBQyxRQUFRLEVBQUU7Ozs7Ozs7OztvQkFTUixLQUFLLENBQUMsU0FBUzs7Ozs7Ozs7O21CQVNoQixLQUFLLENBQUMsYUFBYTs7Ozs7Ozs7Y0FReEIsQ0FBQyxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcGF0aEV4aXN0cyB9IGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IExvZ2luSW5mb3JtYXRpb24gfSBmcm9tICcuL2NvZGVhcnRpZmFjdCc7XG5pbXBvcnQgeyBwYXJhbGxlbFNoZWxsIH0gZnJvbSAnLi9wYXJhbGxlbC1zaGVsbCc7XG5pbXBvcnQgeyBVc2FnZURpciB9IGZyb20gJy4vdXNhZ2UtZGlyJztcbmltcG9ydCB7IHdyaXRlRmlsZSB9IGZyb20gJy4uL2ZpbGVzJztcbmltcG9ydCB7IHNoZWxsIH0gZnJvbSAnLi4vc2hlbGwnO1xuXG4vLyBEbyBub3QgdHJ5IHRvIEpJVCB0aGUgTWF2ZW4gYmluYXJ5XG5jb25zdCBOT19KSVQgPSAnLVhYOitUaWVyZWRDb21waWxhdGlvbiAtWFg6VGllcmVkU3RvcEF0TGV2ZWw9MSc7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBtYXZlbkxvZ2luKGxvZ2luOiBMb2dpbkluZm9ybWF0aW9uLCB1c2FnZURpcjogVXNhZ2VEaXIpIHtcbiAgYXdhaXQgd3JpdGVNYXZlblNldHRpbmdzRmlsZShzZXR0aW5nc0ZpbGUodXNhZ2VEaXIpLCBsb2dpbik7XG5cbiAgLy8gV3JpdGUgZW52IHZhclxuICAvLyBUd2lkZGxlIEpWTSBzZXR0aW5ncyBhIGJpdCB0byBtYWtlIE1hdmVuIHN1cnZpdmUgcnVubmluZyBvbiBhIENvZGVCdWlsZCBib3guXG4gIGF3YWl0IHVzYWdlRGlyLmFkZFRvRW52KHtcbiAgICBNQVZFTl9PUFRTOiBgLUR1c2VyLmhvbWU9JHt1c2FnZURpci5kaXJlY3Rvcnl9ICR7Tk9fSklUfSAke3Byb2Nlc3MuZW52Lk1BVkVOX09QVFMgPz8gJyd9YC50cmltKCksXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzZXR0aW5nc0ZpbGUodXNhZ2VEaXI6IFVzYWdlRGlyKSB7XG4gIC8vIElmIHdlIGNvbmZpZ3VyZSB1c2FnZURpciBhcyBhIGZha2UgaG9tZSBkaXJlY3RvcnkgTWF2ZW4gd2lsbCBmaW5kIHRoaXMgZmlsZS5cbiAgLy8gKE5vIG90aGVyIHdheSB0byBjb25maWd1cmUgdGhlIHNldHRpbmdzIGZpbGUgYXMgcGFydCBvZiB0aGUgZW52aXJvbm1lbnQpLlxuICByZXR1cm4gcGF0aC5qb2luKHVzYWdlRGlyLmRpcmVjdG9yeSwgJy5tMicsICdzZXR0aW5ncy54bWwnKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwbG9hZEphdmFQYWNrYWdlcyhwYWNrYWdlczogc3RyaW5nW10sIGxvZ2luOiBMb2dpbkluZm9ybWF0aW9uLCB1c2FnZURpcjogVXNhZ2VEaXIpIHtcbiAgYXdhaXQgcGFyYWxsZWxTaGVsbChwYWNrYWdlcywgYXN5bmMgKHBrZywgb3V0cHV0KSA9PiB7XG4gICAgY29uc29sZS5sb2coYOKPsyAke3BrZ31gKTtcblxuICAgIGNvbnN0IHNvdXJjZXNGaWxlID0gcGtnLnJlcGxhY2UoLy5wb20kLywgJy1zb3VyY2VzLmphcicpO1xuICAgIGNvbnN0IGphdmFkb2NGaWxlID0gcGtnLnJlcGxhY2UoLy5wb20kLywgJy1qYXZhZG9jLmphcicpO1xuXG4gICAgYXdhaXQgc2hlbGwoWydtdm4nLFxuICAgICAgYC0tc2V0dGluZ3M9JHtzZXR0aW5nc0ZpbGUodXNhZ2VEaXIpfWAsXG4gICAgICAnb3JnLmFwYWNoZS5tYXZlbi5wbHVnaW5zOm1hdmVuLWRlcGxveS1wbHVnaW46My4wLjA6ZGVwbG95LWZpbGUnLFxuICAgICAgYC1EdXJsPSR7bG9naW4ubWF2ZW5FbmRwb2ludH1gLFxuICAgICAgJy1EcmVwb3NpdG9yeUlkPWNvZGVhcnRpZmFjdCcsXG4gICAgICBgLURwb21GaWxlPSR7cGtnfWAsXG4gICAgICBgLURmaWxlPSR7cGtnLnJlcGxhY2UoLy5wb20kLywgJy5qYXInKX1gLFxuICAgICAgLi4uYXdhaXQgcGF0aEV4aXN0cyhzb3VyY2VzRmlsZSkgPyBbYC1Ec291cmNlcz0ke3NvdXJjZXNGaWxlfWBdIDogW10sXG4gICAgICAuLi5hd2FpdCBwYXRoRXhpc3RzKGphdmFkb2NGaWxlKSA/IFtgLURqYXZhZG9jPSR7amF2YWRvY0ZpbGV9YF0gOiBbXV0sIHtcbiAgICAgIG91dHB1dHM6IFtvdXRwdXRdLFxuICAgICAgbW9kRW52OiB7XG4gICAgICAgIC8vIERvIG5vdCB0cnkgdG8gSklUIHRoZSBNYXZlbiBiaW5hcnlcbiAgICAgICAgTUFWRU5fT1BUUzogYCR7Tk9fSklUfSAke3Byb2Nlc3MuZW52Lk1BVkVOX09QVFMgPz8gJyd9YC50cmltKCksXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coYOKchSAke3BrZ31gKTtcbiAgfSxcbiAgKHBrZywgb3V0cHV0KSA9PiB7XG4gICAgaWYgKG91dHB1dC50b1N0cmluZygpLmluY2x1ZGVzKCc0MDkgQ29uZmxpY3QnKSkge1xuICAgICAgY29uc29sZS5sb2coYOKdjCAke3BrZ306IGFscmVhZHkgZXhpc3RzLiBTa2lwcGVkLmApO1xuICAgICAgcmV0dXJuICdza2lwJztcbiAgICB9XG4gICAgaWYgKG91dHB1dC50b1N0cmluZygpLmluY2x1ZGVzKCdUb28gTWFueSBSZXF1ZXN0cycpKSB7XG4gICAgICBjb25zb2xlLmxvZyhg4pm777iPICR7cGtnfTogVG9vIG1hbnkgcmVxdWVzdHMuIFJldHJ5aW5nLmApO1xuICAgICAgcmV0dXJuICdyZXRyeSc7XG4gICAgfVxuICAgIHJldHVybiAnZmFpbCc7XG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVNYXZlblNldHRpbmdzRmlsZShmaWxlbmFtZTogc3RyaW5nLCBsb2dpbjogTG9naW5JbmZvcm1hdGlvbikge1xuICBhd2FpdCB3cml0ZUZpbGUoZmlsZW5hbWUsIGA8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiID8+XG4gIDxzZXR0aW5ncyB4bWxucz1cImh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL1NFVFRJTkdTLzEuMC4wXCJcbiAgICAgICAgICAgIHhtbG5zOnhzaT1cImh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlXCJcbiAgICAgICAgICAgIHhzaTpzY2hlbWFMb2NhdGlvbj1cImh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL1NFVFRJTkdTLzEuMC4wXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0dHA6Ly9tYXZlbi5hcGFjaGUub3JnL3hzZC9zZXR0aW5ncy0xLjAuMC54c2RcIj5cbiAgICA8c2VydmVycz5cbiAgICAgIDxzZXJ2ZXI+XG4gICAgICAgIDxpZD5jb2RlYXJ0aWZhY3Q8L2lkPlxuICAgICAgICA8dXNlcm5hbWU+YXdzPC91c2VybmFtZT5cbiAgICAgICAgPHBhc3N3b3JkPiR7bG9naW4uYXV0aFRva2VufTwvcGFzc3dvcmQ+XG4gICAgICA8L3NlcnZlcj5cbiAgICA8L3NlcnZlcnM+XG4gICAgPHByb2ZpbGVzPlxuICAgICAgPHByb2ZpbGU+XG4gICAgICAgIDxpZD5kZWZhdWx0PC9pZD5cbiAgICAgICAgPHJlcG9zaXRvcmllcz5cbiAgICAgICAgICA8cmVwb3NpdG9yeT5cbiAgICAgICAgICAgIDxpZD5jb2RlYXJ0aWZhY3Q8L2lkPlxuICAgICAgICAgICAgPHVybD4ke2xvZ2luLm1hdmVuRW5kcG9pbnR9PC91cmw+XG4gICAgICAgICAgPC9yZXBvc2l0b3J5PlxuICAgICAgICA8L3JlcG9zaXRvcmllcz5cbiAgICAgIDwvcHJvZmlsZT5cbiAgICA8L3Byb2ZpbGVzPlxuICAgIDxhY3RpdmVQcm9maWxlcz5cbiAgICAgIDxhY3RpdmVQcm9maWxlPmRlZmF1bHQ8L2FjdGl2ZVByb2ZpbGU+XG4gICAgPC9hY3RpdmVQcm9maWxlcz5cbiAgPC9zZXR0aW5ncz5gKTtcbn1cbiJdfQ==
@@ -0,0 +1,95 @@
1
+ /* eslint-disable no-console */
2
+ import * as path from 'path';
3
+ import { pathExists } from 'fs-extra';
4
+ import { LoginInformation } from './codeartifact';
5
+ import { parallelShell } from './parallel-shell';
6
+ import { UsageDir } from './usage-dir';
7
+ import { writeFile } from '../files';
8
+ import { shell } from '../shell';
9
+
10
+ // Do not try to JIT the Maven binary
11
+ const NO_JIT = '-XX:+TieredCompilation -XX:TieredStopAtLevel=1';
12
+
13
+ export async function mavenLogin(login: LoginInformation, usageDir: UsageDir) {
14
+ await writeMavenSettingsFile(settingsFile(usageDir), login);
15
+
16
+ // Write env var
17
+ // Twiddle JVM settings a bit to make Maven survive running on a CodeBuild box.
18
+ await usageDir.addToEnv({
19
+ MAVEN_OPTS: `-Duser.home=${usageDir.directory} ${NO_JIT} ${process.env.MAVEN_OPTS ?? ''}`.trim(),
20
+ });
21
+ }
22
+
23
+ function settingsFile(usageDir: UsageDir) {
24
+ // If we configure usageDir as a fake home directory Maven will find this file.
25
+ // (No other way to configure the settings file as part of the environment).
26
+ return path.join(usageDir.directory, '.m2', 'settings.xml');
27
+ }
28
+
29
+ export async function uploadJavaPackages(packages: string[], login: LoginInformation, usageDir: UsageDir) {
30
+ await parallelShell(packages, async (pkg, output) => {
31
+ console.log(`⏳ ${pkg}`);
32
+
33
+ const sourcesFile = pkg.replace(/.pom$/, '-sources.jar');
34
+ const javadocFile = pkg.replace(/.pom$/, '-javadoc.jar');
35
+
36
+ await shell(['mvn',
37
+ `--settings=${settingsFile(usageDir)}`,
38
+ 'org.apache.maven.plugins:maven-deploy-plugin:3.0.0:deploy-file',
39
+ `-Durl=${login.mavenEndpoint}`,
40
+ '-DrepositoryId=codeartifact',
41
+ `-DpomFile=${pkg}`,
42
+ `-Dfile=${pkg.replace(/.pom$/, '.jar')}`,
43
+ ...await pathExists(sourcesFile) ? [`-Dsources=${sourcesFile}`] : [],
44
+ ...await pathExists(javadocFile) ? [`-Djavadoc=${javadocFile}`] : []], {
45
+ outputs: [output],
46
+ modEnv: {
47
+ // Do not try to JIT the Maven binary
48
+ MAVEN_OPTS: `${NO_JIT} ${process.env.MAVEN_OPTS ?? ''}`.trim(),
49
+ },
50
+ });
51
+
52
+ console.log(`✅ ${pkg}`);
53
+ },
54
+ (pkg, output) => {
55
+ if (output.toString().includes('409 Conflict')) {
56
+ console.log(`❌ ${pkg}: already exists. Skipped.`);
57
+ return 'skip';
58
+ }
59
+ if (output.toString().includes('Too Many Requests')) {
60
+ console.log(`♻️ ${pkg}: Too many requests. Retrying.`);
61
+ return 'retry';
62
+ }
63
+ return 'fail';
64
+ });
65
+ }
66
+
67
+ export async function writeMavenSettingsFile(filename: string, login: LoginInformation) {
68
+ await writeFile(filename, `<?xml version="1.0" encoding="UTF-8" ?>
69
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
70
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
71
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
72
+ http://maven.apache.org/xsd/settings-1.0.0.xsd">
73
+ <servers>
74
+ <server>
75
+ <id>codeartifact</id>
76
+ <username>aws</username>
77
+ <password>${login.authToken}</password>
78
+ </server>
79
+ </servers>
80
+ <profiles>
81
+ <profile>
82
+ <id>default</id>
83
+ <repositories>
84
+ <repository>
85
+ <id>codeartifact</id>
86
+ <url>${login.mavenEndpoint}</url>
87
+ </repository>
88
+ </repositories>
89
+ </profile>
90
+ </profiles>
91
+ <activeProfiles>
92
+ <activeProfile>default</activeProfile>
93
+ </activeProfiles>
94
+ </settings>`);
95
+ }
@@ -0,0 +1,4 @@
1
+ import { LoginInformation } from './codeartifact';
2
+ import { UsageDir } from './usage-dir';
3
+ export declare function npmLogin(login: LoginInformation, usageDir: UsageDir): Promise<void>;
4
+ export declare function uploadNpmPackages(packages: string[], login: LoginInformation, usageDir: UsageDir): Promise<void>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.npmLogin = npmLogin;
4
+ exports.uploadNpmPackages = uploadNpmPackages;
5
+ /* eslint-disable no-console */
6
+ const path = require("path");
7
+ const parallel_shell_1 = require("./parallel-shell");
8
+ const files_1 = require("../files");
9
+ const shell_1 = require("../shell");
10
+ async function npmLogin(login, usageDir) {
11
+ // Creating an ~/.npmrc that references an envvar is what you're supposed to do. (https://docs.npmjs.com/private-modules/ci-server-config)
12
+ await writeNpmLoginToken(usageDir, login.npmEndpoint, '${NPM_TOKEN}');
13
+ // Add variables to env file
14
+ await usageDir.addToEnv(npmEnv(usageDir, login));
15
+ }
16
+ function npmEnv(usageDir, login) {
17
+ return {
18
+ npm_config_userconfig: path.join(usageDir.directory, '.npmrc'),
19
+ npm_config_registry: login.npmEndpoint,
20
+ npm_config_always_auth: 'true', // Necessary for NPM 6, otherwise it will sometimes not pass the token
21
+ NPM_TOKEN: login.authToken,
22
+ };
23
+ }
24
+ async function uploadNpmPackages(packages, login, usageDir) {
25
+ await (0, parallel_shell_1.parallelShell)(packages, async (pkg, output) => {
26
+ console.log(`⏳ ${pkg}`);
27
+ // path.resolve() is required -- if the filename ends up looking like `js/bla.tgz` then NPM thinks it's a short form GitHub name.
28
+ await (0, shell_1.shell)(['node', require.resolve('npm'), 'publish', path.resolve(pkg)], {
29
+ modEnv: npmEnv(usageDir, login),
30
+ show: 'error',
31
+ outputs: [output],
32
+ });
33
+ console.log(`✅ ${pkg}`);
34
+ }, (pkg, output) => {
35
+ if (output.toString().includes('code EPUBLISHCONFLICT')) {
36
+ console.log(`❌ ${pkg}: already exists. Skipped.`);
37
+ return 'skip';
38
+ }
39
+ if (output.toString().includes('code EPRIVATE')) {
40
+ console.log(`❌ ${pkg}: is private. Skipped.`);
41
+ return 'skip';
42
+ }
43
+ return 'fail';
44
+ });
45
+ }
46
+ async function writeNpmLoginToken(usageDir, endpoint, token) {
47
+ const rcFile = path.join(usageDir.directory, '.npmrc');
48
+ const lines = await (0, files_1.loadLines)(rcFile);
49
+ const key = `${endpoint.replace(/^https:/, '')}:_authToken`;
50
+ (0, files_1.updateIniKey)(lines, key, token);
51
+ await (0, files_1.writeLines)(rcFile, lines);
52
+ return rcFile;
53
+ }
54
+ // Environment variable, .npmrc in same directory as package.json or in home dir
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnBtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibnBtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBUUEsNEJBTUM7QUFXRCw4Q0F1QkM7QUFoREQsK0JBQStCO0FBQy9CLDZCQUE2QjtBQUU3QixxREFBaUQ7QUFFakQsb0NBQStEO0FBQy9ELG9DQUFpQztBQUUxQixLQUFLLFVBQVUsUUFBUSxDQUFDLEtBQXVCLEVBQUUsUUFBa0I7SUFDeEUsMElBQTBJO0lBQzFJLE1BQU0sa0JBQWtCLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFFdEUsNEJBQTRCO0lBQzVCLE1BQU0sUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQUVELFNBQVMsTUFBTSxDQUFDLFFBQWtCLEVBQUUsS0FBdUI7SUFDekQsT0FBTztRQUNMLHFCQUFxQixFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUM7UUFDOUQsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLFdBQVc7UUFDdEMsc0JBQXNCLEVBQUUsTUFBTSxFQUFFLHNFQUFzRTtRQUN0RyxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7S0FDM0IsQ0FBQztBQUNKLENBQUM7QUFFTSxLQUFLLFVBQVUsaUJBQWlCLENBQUMsUUFBa0IsRUFBRSxLQUF1QixFQUFFLFFBQWtCO0lBQ3JHLE1BQU0sSUFBQSw4QkFBYSxFQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2xELE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBRXhCLGlJQUFpSTtRQUNqSSxNQUFNLElBQUEsYUFBSyxFQUFDLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRTtZQUMxRSxNQUFNLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUM7WUFDL0IsSUFBSSxFQUFFLE9BQU87WUFDYixPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUM7U0FDbEIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2pCLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLENBQUM7WUFDeEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsNEJBQTRCLENBQUMsQ0FBQztZQUNsRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7WUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsd0JBQXdCLENBQUMsQ0FBQztZQUM5QyxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGtCQUFrQixDQUFDLFFBQWtCLEVBQUUsUUFBZ0IsRUFBRSxLQUFhO0lBQ25GLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2RCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUEsaUJBQVMsRUFBQyxNQUFNLENBQUMsQ0FBQztJQUV0QyxNQUFNLEdBQUcsR0FBRyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxhQUFhLENBQUM7SUFDNUQsSUFBQSxvQkFBWSxFQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFaEMsTUFBTSxJQUFBLGtCQUFVLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxnRkFBZ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgTG9naW5JbmZvcm1hdGlvbiB9IGZyb20gJy4vY29kZWFydGlmYWN0JztcbmltcG9ydCB7IHBhcmFsbGVsU2hlbGwgfSBmcm9tICcuL3BhcmFsbGVsLXNoZWxsJztcbmltcG9ydCB7IFVzYWdlRGlyIH0gZnJvbSAnLi91c2FnZS1kaXInO1xuaW1wb3J0IHsgdXBkYXRlSW5pS2V5LCBsb2FkTGluZXMsIHdyaXRlTGluZXMgfSBmcm9tICcuLi9maWxlcyc7XG5pbXBvcnQgeyBzaGVsbCB9IGZyb20gJy4uL3NoZWxsJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG5wbUxvZ2luKGxvZ2luOiBMb2dpbkluZm9ybWF0aW9uLCB1c2FnZURpcjogVXNhZ2VEaXIpIHtcbiAgLy8gQ3JlYXRpbmcgYW4gfi8ubnBtcmMgdGhhdCByZWZlcmVuY2VzIGFuIGVudnZhciBpcyB3aGF0IHlvdSdyZSBzdXBwb3NlZCB0byBkby4gKGh0dHBzOi8vZG9jcy5ucG1qcy5jb20vcHJpdmF0ZS1tb2R1bGVzL2NpLXNlcnZlci1jb25maWcpXG4gIGF3YWl0IHdyaXRlTnBtTG9naW5Ub2tlbih1c2FnZURpciwgbG9naW4ubnBtRW5kcG9pbnQsICcke05QTV9UT0tFTn0nKTtcblxuICAvLyBBZGQgdmFyaWFibGVzIHRvIGVudiBmaWxlXG4gIGF3YWl0IHVzYWdlRGlyLmFkZFRvRW52KG5wbUVudih1c2FnZURpciwgbG9naW4pKTtcbn1cblxuZnVuY3Rpb24gbnBtRW52KHVzYWdlRGlyOiBVc2FnZURpciwgbG9naW46IExvZ2luSW5mb3JtYXRpb24pIHtcbiAgcmV0dXJuIHtcbiAgICBucG1fY29uZmlnX3VzZXJjb25maWc6IHBhdGguam9pbih1c2FnZURpci5kaXJlY3RvcnksICcubnBtcmMnKSxcbiAgICBucG1fY29uZmlnX3JlZ2lzdHJ5OiBsb2dpbi5ucG1FbmRwb2ludCxcbiAgICBucG1fY29uZmlnX2Fsd2F5c19hdXRoOiAndHJ1ZScsIC8vIE5lY2Vzc2FyeSBmb3IgTlBNIDYsIG90aGVyd2lzZSBpdCB3aWxsIHNvbWV0aW1lcyBub3QgcGFzcyB0aGUgdG9rZW5cbiAgICBOUE1fVE9LRU46IGxvZ2luLmF1dGhUb2tlbixcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwbG9hZE5wbVBhY2thZ2VzKHBhY2thZ2VzOiBzdHJpbmdbXSwgbG9naW46IExvZ2luSW5mb3JtYXRpb24sIHVzYWdlRGlyOiBVc2FnZURpcikge1xuICBhd2FpdCBwYXJhbGxlbFNoZWxsKHBhY2thZ2VzLCBhc3luYyAocGtnLCBvdXRwdXQpID0+IHtcbiAgICBjb25zb2xlLmxvZyhg4o+zICR7cGtnfWApO1xuXG4gICAgLy8gcGF0aC5yZXNvbHZlKCkgaXMgcmVxdWlyZWQgLS0gaWYgdGhlIGZpbGVuYW1lIGVuZHMgdXAgbG9va2luZyBsaWtlIGBqcy9ibGEudGd6YCB0aGVuIE5QTSB0aGlua3MgaXQncyBhIHNob3J0IGZvcm0gR2l0SHViIG5hbWUuXG4gICAgYXdhaXQgc2hlbGwoWydub2RlJywgcmVxdWlyZS5yZXNvbHZlKCducG0nKSwgJ3B1Ymxpc2gnLCBwYXRoLnJlc29sdmUocGtnKV0sIHtcbiAgICAgIG1vZEVudjogbnBtRW52KHVzYWdlRGlyLCBsb2dpbiksXG4gICAgICBzaG93OiAnZXJyb3InLFxuICAgICAgb3V0cHV0czogW291dHB1dF0sXG4gICAgfSk7XG5cbiAgICBjb25zb2xlLmxvZyhg4pyFICR7cGtnfWApO1xuICB9LCAocGtnLCBvdXRwdXQpID0+IHtcbiAgICBpZiAob3V0cHV0LnRvU3RyaW5nKCkuaW5jbHVkZXMoJ2NvZGUgRVBVQkxJU0hDT05GTElDVCcpKSB7XG4gICAgICBjb25zb2xlLmxvZyhg4p2MICR7cGtnfTogYWxyZWFkeSBleGlzdHMuIFNraXBwZWQuYCk7XG4gICAgICByZXR1cm4gJ3NraXAnO1xuICAgIH1cbiAgICBpZiAob3V0cHV0LnRvU3RyaW5nKCkuaW5jbHVkZXMoJ2NvZGUgRVBSSVZBVEUnKSkge1xuICAgICAgY29uc29sZS5sb2coYOKdjCAke3BrZ306IGlzIHByaXZhdGUuIFNraXBwZWQuYCk7XG4gICAgICByZXR1cm4gJ3NraXAnO1xuICAgIH1cbiAgICByZXR1cm4gJ2ZhaWwnO1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVOcG1Mb2dpblRva2VuKHVzYWdlRGlyOiBVc2FnZURpciwgZW5kcG9pbnQ6IHN0cmluZywgdG9rZW46IHN0cmluZykge1xuICBjb25zdCByY0ZpbGUgPSBwYXRoLmpvaW4odXNhZ2VEaXIuZGlyZWN0b3J5LCAnLm5wbXJjJyk7XG4gIGNvbnN0IGxpbmVzID0gYXdhaXQgbG9hZExpbmVzKHJjRmlsZSk7XG5cbiAgY29uc3Qga2V5ID0gYCR7ZW5kcG9pbnQucmVwbGFjZSgvXmh0dHBzOi8sICcnKX06X2F1dGhUb2tlbmA7XG4gIHVwZGF0ZUluaUtleShsaW5lcywga2V5LCB0b2tlbik7XG5cbiAgYXdhaXQgd3JpdGVMaW5lcyhyY0ZpbGUsIGxpbmVzKTtcbiAgcmV0dXJuIHJjRmlsZTtcbn1cblxuLy8gRW52aXJvbm1lbnQgdmFyaWFibGUsIC5ucG1yYyBpbiBzYW1lIGRpcmVjdG9yeSBhcyBwYWNrYWdlLmpzb24gb3IgaW4gaG9tZSBkaXJcbiJdfQ==