@jjrawlins/cdk-deploy-pr-github-action 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.
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CdkDeployPipeline = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const github_1 = require("projen/lib/github");
7
+ const workflows_model_1 = require("projen/lib/github/workflows-model");
8
+ const CdkDeployDispatchWorkflow_1 = require("./CdkDeployDispatchWorkflow");
9
+ const utils_1 = require("./utils");
10
+ const CHECKOUT_VERSION = 'v5';
11
+ const SETUP_NODE_VERSION = 'v5';
12
+ const AWS_CREDENTIALS_VERSION = 'v5';
13
+ const UPLOAD_ARTIFACT_VERSION = 'v4';
14
+ const DOWNLOAD_ARTIFACT_VERSION = 'v5';
15
+ /**
16
+ * Generates GitHub Actions workflows for CDK deployments.
17
+ *
18
+ * Creates a `deploy.yml` workflow with:
19
+ * - Synth job to compile and synthesize the CDK app
20
+ * - Asset publish job to upload Lambda/container assets to AWS
21
+ * - Per-stage deploy jobs with GitHub Environments, parallel execution, and concurrency groups
22
+ *
23
+ * Optionally creates a `deploy-dispatch.yml` workflow for manual deployments and rollbacks.
24
+ */
25
+ class CdkDeployPipeline {
26
+ constructor(project, options) {
27
+ const { pkgNamespace, stackPrefix, iamRoleArn, iamRoleRegion = 'us-east-1', nodeVersion = '24.x', cdkCommand = 'npx cdk', installCommand = 'yarn install --check-files --frozen-lockfile', stages, manualDeployment = true, useGithubPackagesForAssembly = true, branchName = 'main', } = options;
28
+ // Validate inputs
29
+ if (stages.length === 0) {
30
+ throw new Error('At least one deployment stage must be defined');
31
+ }
32
+ const stageNames = new Set(stages.map((s) => s.name));
33
+ for (const stage of stages) {
34
+ if (stage.dependsOn) {
35
+ for (const dep of stage.dependsOn) {
36
+ if (!stageNames.has(dep)) {
37
+ throw new Error(`Stage '${stage.name}' depends on '${dep}', which is not a defined stage. Available: ${[...stageNames].join(', ')}`);
38
+ }
39
+ if (dep === stage.name) {
40
+ throw new Error(`Stage '${stage.name}' cannot depend on itself`);
41
+ }
42
+ }
43
+ }
44
+ }
45
+ (0, utils_1.validateNoCycles)(stages);
46
+ if (useGithubPackagesForAssembly && !pkgNamespace) {
47
+ throw new Error('pkgNamespace is required when useGithubPackagesForAssembly is enabled');
48
+ }
49
+ // Create the deploy workflow
50
+ const gh = project.github ?? new github_1.GitHub(project);
51
+ const workflow = new github_1.GithubWorkflow(gh, 'deploy', {
52
+ fileName: 'deploy.yml',
53
+ });
54
+ workflow.on({
55
+ push: { branches: [branchName] },
56
+ workflowDispatch: {},
57
+ });
58
+ const appName = project.name ?? stackPrefix.toLowerCase();
59
+ // Build jobs object
60
+ const jobs = {};
61
+ // --- Synth Job ---
62
+ jobs.synth = {
63
+ name: 'Synthesize CDK application',
64
+ runsOn: ['ubuntu-latest'],
65
+ permissions: {
66
+ contents: workflows_model_1.JobPermission.READ,
67
+ packages: workflows_model_1.JobPermission.READ,
68
+ },
69
+ env: { CI: 'true' },
70
+ steps: [
71
+ {
72
+ name: 'Checkout',
73
+ uses: `actions/checkout@${CHECKOUT_VERSION}`,
74
+ with: { 'fetch-depth': 0 },
75
+ },
76
+ {
77
+ name: 'Setup Node.js',
78
+ uses: `actions/setup-node@${SETUP_NODE_VERSION}`,
79
+ with: {
80
+ 'node-version': nodeVersion,
81
+ 'registry-url': 'https://npm.pkg.github.com',
82
+ },
83
+ },
84
+ {
85
+ name: 'Install dependencies',
86
+ run: installCommand,
87
+ env: { NODE_AUTH_TOKEN: '${{ secrets.GITHUB_TOKEN }}', GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
88
+ },
89
+ {
90
+ name: 'Synth',
91
+ run: `${cdkCommand} synth`,
92
+ },
93
+ {
94
+ name: 'Upload cloud assembly',
95
+ uses: `actions/upload-artifact@${UPLOAD_ARTIFACT_VERSION}`,
96
+ with: {
97
+ name: 'cloud-assembly',
98
+ path: 'cdk.out/',
99
+ },
100
+ },
101
+ ],
102
+ };
103
+ // --- Publish Assets Job ---
104
+ const publishSteps = [
105
+ {
106
+ name: 'Checkout',
107
+ uses: `actions/checkout@${CHECKOUT_VERSION}`,
108
+ with: { 'fetch-depth': 0 },
109
+ },
110
+ {
111
+ name: 'Setup Node.js',
112
+ uses: `actions/setup-node@${SETUP_NODE_VERSION}`,
113
+ with: {
114
+ 'node-version': nodeVersion,
115
+ 'registry-url': 'https://npm.pkg.github.com',
116
+ },
117
+ },
118
+ {
119
+ name: 'Install dependencies',
120
+ run: installCommand,
121
+ env: { NODE_AUTH_TOKEN: '${{ secrets.GITHUB_TOKEN }}', GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
122
+ },
123
+ {
124
+ name: 'Download cloud assembly',
125
+ uses: `actions/download-artifact@${DOWNLOAD_ARTIFACT_VERSION}`,
126
+ with: { name: 'cloud-assembly', path: 'cdk.out/' },
127
+ },
128
+ {
129
+ name: 'AWS Credentials',
130
+ uses: `aws-actions/configure-aws-credentials@${AWS_CREDENTIALS_VERSION}`,
131
+ with: {
132
+ 'role-to-assume': iamRoleArn,
133
+ 'role-session-name': 'GitHubAction',
134
+ 'aws-region': iamRoleRegion,
135
+ },
136
+ },
137
+ {
138
+ name: 'Publish assets',
139
+ run: 'npx cdk-assets publish -p cdk.out/**/*-assets.json',
140
+ },
141
+ ];
142
+ if (useGithubPackagesForAssembly) {
143
+ publishSteps.push({
144
+ name: 'Configure git identity',
145
+ run: [
146
+ 'git config user.name "github-actions[bot]"',
147
+ 'git config user.email "41898282+github-actions[bot]@users.noreply.github.com"',
148
+ ].join('\n'),
149
+ }, {
150
+ name: 'Create assembly package',
151
+ run: [
152
+ `echo '${JSON.stringify({ name: `${pkgNamespace}/${appName}`, version: '0.0.0' })}' > cdk.out/package.json`,
153
+ 'cd cdk.out && npm version --no-git-tag-version from-git || npm version --no-git-tag-version patch',
154
+ ].join('\n'),
155
+ env: { NODE_AUTH_TOKEN: '${{ secrets.GITHUB_TOKEN }}', GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
156
+ }, {
157
+ name: 'Publish assembly to GitHub Packages',
158
+ run: 'cd cdk.out && npm publish',
159
+ env: { NODE_AUTH_TOKEN: '${{ secrets.GITHUB_TOKEN }}', GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
160
+ });
161
+ }
162
+ jobs['publish-assets'] = {
163
+ name: 'Publish assets to AWS',
164
+ needs: ['synth'],
165
+ runsOn: ['ubuntu-latest'],
166
+ permissions: {
167
+ contents: workflows_model_1.JobPermission.WRITE,
168
+ packages: workflows_model_1.JobPermission.WRITE,
169
+ idToken: workflows_model_1.JobPermission.WRITE,
170
+ },
171
+ env: { CI: 'true' },
172
+ steps: publishSteps,
173
+ };
174
+ // --- Per-Stage Deploy Jobs ---
175
+ for (const stage of stages) {
176
+ const jobId = `deploy-${(0, utils_1.toKebabCase)(stage.name)}`;
177
+ const stacks = stage.stacks ?? [`${stackPrefix}-${stage.name}`];
178
+ const githubEnv = stage.environment ?? stage.name;
179
+ const roleArn = stage.iamRoleArn ?? iamRoleArn;
180
+ const roleRegion = stage.iamRoleRegion ?? iamRoleRegion ?? stage.env.region;
181
+ // Compute needs
182
+ let needs;
183
+ if (stage.dependsOn && stage.dependsOn.length > 0) {
184
+ needs = stage.dependsOn.map((dep) => `deploy-${(0, utils_1.toKebabCase)(dep)}`);
185
+ }
186
+ else {
187
+ needs = ['publish-assets'];
188
+ }
189
+ const deployCommand = stacks
190
+ .map((s) => `${cdkCommand} deploy ${s} --require-approval never --app cdk.out`)
191
+ .join(' && ');
192
+ jobs[jobId] = {
193
+ name: `Deploy ${stage.name}`,
194
+ needs: needs,
195
+ runsOn: ['ubuntu-latest'],
196
+ environment: githubEnv,
197
+ concurrency: {
198
+ 'group': `deploy-${(0, utils_1.toKebabCase)(stage.name)}`,
199
+ 'cancel-in-progress': false,
200
+ },
201
+ permissions: {
202
+ contents: workflows_model_1.JobPermission.READ,
203
+ packages: workflows_model_1.JobPermission.READ,
204
+ idToken: workflows_model_1.JobPermission.WRITE,
205
+ },
206
+ env: { CI: 'true' },
207
+ steps: [
208
+ {
209
+ name: 'Checkout',
210
+ uses: `actions/checkout@${CHECKOUT_VERSION}`,
211
+ },
212
+ {
213
+ name: 'Setup Node.js',
214
+ uses: `actions/setup-node@${SETUP_NODE_VERSION}`,
215
+ with: {
216
+ 'node-version': nodeVersion,
217
+ 'registry-url': 'https://npm.pkg.github.com',
218
+ },
219
+ },
220
+ {
221
+ name: 'Install dependencies',
222
+ run: installCommand,
223
+ env: { NODE_AUTH_TOKEN: '${{ secrets.GITHUB_TOKEN }}', GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' },
224
+ },
225
+ {
226
+ name: 'Download cloud assembly',
227
+ uses: `actions/download-artifact@${DOWNLOAD_ARTIFACT_VERSION}`,
228
+ with: { name: 'cloud-assembly', path: 'cdk.out/' },
229
+ },
230
+ {
231
+ name: 'AWS Credentials',
232
+ uses: `aws-actions/configure-aws-credentials@${AWS_CREDENTIALS_VERSION}`,
233
+ with: {
234
+ 'role-to-assume': roleArn,
235
+ 'role-session-name': 'GitHubAction',
236
+ 'aws-region': roleRegion,
237
+ },
238
+ },
239
+ {
240
+ name: `Deploy ${stage.name}`,
241
+ run: deployCommand,
242
+ },
243
+ ],
244
+ };
245
+ // Create projen task for local usage
246
+ project.addTask(`deploy:${stage.name}`, {
247
+ description: `Deploy to ${stage.name}`,
248
+ exec: stacks
249
+ .map((s) => `${cdkCommand} deploy ${s} --require-approval never`)
250
+ .join(' && '),
251
+ });
252
+ }
253
+ // Add all jobs to the workflow
254
+ workflow.addJobs(jobs);
255
+ // --- Dispatch Workflow ---
256
+ if (manualDeployment && useGithubPackagesForAssembly) {
257
+ new CdkDeployDispatchWorkflow_1.CdkDeployDispatchWorkflow(project, {
258
+ stages,
259
+ pkgNamespace,
260
+ appName,
261
+ stackPrefix,
262
+ iamRoleArn,
263
+ iamRoleRegion,
264
+ nodeVersion,
265
+ cdkCommand,
266
+ installCommand,
267
+ });
268
+ }
269
+ }
270
+ }
271
+ exports.CdkDeployPipeline = CdkDeployPipeline;
272
+ _a = JSII_RTTI_SYMBOL_1;
273
+ CdkDeployPipeline[_a] = { fqn: "@jjrawlins/cdk-deploy-pr-github-action.CdkDeployPipeline", version: "0.0.0" };
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2RrRGVwbG95UGlwZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvQ2RrRGVwbG95UGlwZWxpbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4Q0FBMkQ7QUFDM0QsdUVBQWtFO0FBQ2xFLDJFQUF3RTtBQUV4RSxtQ0FBd0Q7QUFFeEQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUFDOUIsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUM7QUFDaEMsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLENBQUM7QUFDckMsTUFBTSx1QkFBdUIsR0FBRyxJQUFJLENBQUM7QUFDckMsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUM7QUFFdkM7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBYSxpQkFBaUI7SUFDNUIsWUFBWSxPQUFZLEVBQUUsT0FBaUM7UUFDekQsTUFBTSxFQUNKLFlBQVksRUFDWixXQUFXLEVBQ1gsVUFBVSxFQUNWLGFBQWEsR0FBRyxXQUFXLEVBQzNCLFdBQVcsR0FBRyxNQUFNLEVBQ3BCLFVBQVUsR0FBRyxTQUFTLEVBQ3RCLGNBQWMsR0FBRyw4Q0FBOEMsRUFDL0QsTUFBTSxFQUNOLGdCQUFnQixHQUFHLElBQUksRUFDdkIsNEJBQTRCLEdBQUcsSUFBSSxFQUNuQyxVQUFVLEdBQUcsTUFBTSxHQUNwQixHQUFHLE9BQU8sQ0FBQztRQUVaLGtCQUFrQjtRQUNsQixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0RCxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzNC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NUIsR0FBRyxFQUFFLGFBQWE7cUJBQ25CO2lCQUNGO2FBQ0YsQ0FBQztZQUVGLHFDQUFxQztZQUNyQyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUN0QyxXQUFXLEVBQUUsYUFBYSxLQUFLLENBQUMsSUFBSSxFQUFFO2dCQUN0QyxJQUFJLEVBQUUsTUFBTTtxQkFDVCxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsVUFBVSxXQUFXLENBQUMsMkJBQTJCLENBQUM7cUJBQ2hFLElBQUksQ0FBQyxNQUFNLENBQUM7YUFDaEIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELCtCQUErQjtRQUMvQixRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXZCLDRCQUE0QjtRQUM1QixJQUFJLGdCQUFnQixJQUFJLDRCQUE0QixFQUFFLENBQUM7WUFDckQsSUFBSSxxREFBeUIsQ0FBQyxPQUFPLEVBQUU7Z0JBQ3JDLE1BQU07Z0JBQ04sWUFBWTtnQkFDWixPQUFPO2dCQUNQLFdBQVc7Z0JBQ1gsVUFBVTtnQkFDVixhQUFhO2dCQUNiLFdBQVc7Z0JBQ1gsVUFBVTtnQkFDVixjQUFjO2FBQ2YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7O0FBN1JILDhDQThSQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEdpdEh1YiwgR2l0aHViV29ya2Zsb3cgfSBmcm9tICdwcm9qZW4vbGliL2dpdGh1Yic7XG5pbXBvcnQgeyBKb2JQZXJtaXNzaW9uIH0gZnJvbSAncHJvamVuL2xpYi9naXRodWIvd29ya2Zsb3dzLW1vZGVsJztcbmltcG9ydCB7IENka0RlcGxveURpc3BhdGNoV29ya2Zsb3cgfSBmcm9tICcuL0Nka0RlcGxveURpc3BhdGNoV29ya2Zsb3cnO1xuaW1wb3J0IHsgQ2RrRGVwbG95UGlwZWxpbmVPcHRpb25zLCBEZXBsb3lTdGFnZU9wdGlvbnMgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IHRvS2ViYWJDYXNlLCB2YWxpZGF0ZU5vQ3ljbGVzIH0gZnJvbSAnLi91dGlscyc7XG5cbmNvbnN0IENIRUNLT1VUX1ZFUlNJT04gPSAndjUnO1xuY29uc3QgU0VUVVBfTk9ERV9WRVJTSU9OID0gJ3Y1JztcbmNvbnN0IEFXU19DUkVERU5USUFMU19WRVJTSU9OID0gJ3Y1JztcbmNvbnN0IFVQTE9BRF9BUlRJRkFDVF9WRVJTSU9OID0gJ3Y0JztcbmNvbnN0IERPV05MT0FEX0FSVElGQUNUX1ZFUlNJT04gPSAndjUnO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBHaXRIdWIgQWN0aW9ucyB3b3JrZmxvd3MgZm9yIENESyBkZXBsb3ltZW50cy5cbiAqXG4gKiBDcmVhdGVzIGEgYGRlcGxveS55bWxgIHdvcmtmbG93IHdpdGg6XG4gKiAtIFN5bnRoIGpvYiB0byBjb21waWxlIGFuZCBzeW50aGVzaXplIHRoZSBDREsgYXBwXG4gKiAtIEFzc2V0IHB1Ymxpc2ggam9iIHRvIHVwbG9hZCBMYW1iZGEvY29udGFpbmVyIGFzc2V0cyB0byBBV1NcbiAqIC0gUGVyLXN0YWdlIGRlcGxveSBqb2JzIHdpdGggR2l0SHViIEVudmlyb25tZW50cywgcGFyYWxsZWwgZXhlY3V0aW9uLCBhbmQgY29uY3VycmVuY3kgZ3JvdXBzXG4gKlxuICogT3B0aW9uYWxseSBjcmVhdGVzIGEgYGRlcGxveS1kaXNwYXRjaC55bWxgIHdvcmtmbG93IGZvciBtYW51YWwgZGVwbG95bWVudHMgYW5kIHJvbGxiYWNrcy5cbiAqL1xuZXhwb3J0IGNsYXNzIENka0RlcGxveVBpcGVsaW5lIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogYW55LCBvcHRpb25zOiBDZGtEZXBsb3lQaXBlbGluZU9wdGlvbnMpIHtcbiAgICBjb25zdCB7XG4gICAgICBwa2dOYW1lc3BhY2UsXG4gICAgICBzdGFja1ByZWZpeCxcbiAgICAgIGlhbVJvbGVBcm4sXG4gICAgICBpYW1Sb2xlUmVnaW9uID0gJ3VzLWVhc3QtMScsXG4gICAgICBub2RlVmVyc2lvbiA9ICcyNC54JyxcbiAgICAgIGNka0NvbW1hbmQgPSAnbnB4IGNkaycsXG4gICAgICBpbnN0YWxsQ29tbWFuZCA9ICd5YXJuIGluc3RhbGwgLS1jaGVjay1maWxlcyAtLWZyb3plbi1sb2NrZmlsZScsXG4gICAgICBzdGFnZXMsXG4gICAgICBtYW51YWxEZXBsb3ltZW50ID0gdHJ1ZSxcbiAgICAgIHVzZUdpdGh1YlBhY2thZ2VzRm9yQXNzZW1ibHkgPSB0cnVlLFxuICAgICAgYnJhbmNoTmFtZSA9ICdtYWluJyxcbiAgICB9ID0gb3B0aW9ucztcblxuICAgIC8vIFZhbGlkYXRlIGlucHV0c1xuICAgIGlmIChzdGFnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F0IGxlYXN0IG9uZSBkZXBsb3ltZW50IHN0YWdlIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YWdlTmFtZXMgPSBuZXcgU2V0KHN0YWdlcy5tYXAoKHMpID0+IHMubmFtZSkpO1xuICAgIGZvciAoY29uc3Qgc3RhZ2Ugb2Ygc3RhZ2VzKSB7XG4gICAgICBpZiAoc3RhZ2UuZGVwZW5kc09uKSB7XG4gICAgICAgIGZvciAoY29uc3QgZGVwIG9mIHN0YWdlLmRlcGVuZHNPbikge1xuICAgICAgICAgIGlmICghc3RhZ2VOYW1lcy5oYXMoZGVwKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgU3RhZ2UgJyR7c3RhZ2UubmFtZX0nIGRlcGVuZHMgb24gJyR7ZGVwfScsIHdoaWNoIGlzIG5vdCBhIGRlZmluZWQgc3RhZ2UuIEF2YWlsYWJsZTogJHtbLi4uc3RhZ2VOYW1lc10uam9pbignLCAnKX1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGRlcCA9PT0gc3RhZ2UubmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdGFnZSAnJHtzdGFnZS5uYW1lfScgY2Fubm90IGRlcGVuZCBvbiBpdHNlbGZgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdmFsaWRhdGVOb0N5Y2xlcyhzdGFnZXMpO1xuXG4gICAgaWYgKHVzZUdpdGh1YlBhY2thZ2VzRm9yQXNzZW1ibHkgJiYgIXBrZ05hbWVzcGFjZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAncGtnTmFtZXNwYWNlIGlzIHJlcXVpcmVkIHdoZW4gdXNlR2l0aHViUGFja2FnZXNGb3JBc3NlbWJseSBpcyBlbmFibGVkJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIHRoZSBkZXBsb3kgd29ya2Zsb3dcbiAgICBjb25zdCBnaCA9IHByb2plY3QuZ2l0aHViID8/IG5ldyBHaXRIdWIocHJvamVjdCk7XG4gICAgY29uc3Qgd29ya2Zsb3cgPSBuZXcgR2l0aHViV29ya2Zsb3coZ2gsICdkZXBsb3knLCB7XG4gICAgICBmaWxlTmFtZTogJ2RlcGxveS55bWwnLFxuICAgIH0pO1xuXG4gICAgd29ya2Zsb3cub24oe1xuICAgICAgcHVzaDogeyBicmFuY2hlczogW2JyYW5jaE5hbWVdIH0sXG4gICAgICB3b3JrZmxvd0Rpc3BhdGNoOiB7fSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFwcE5hbWUgPSBwcm9qZWN0Lm5hbWUgPz8gc3RhY2tQcmVmaXgudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIEJ1aWxkIGpvYnMgb2JqZWN0XG4gICAgY29uc3Qgam9iczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgLy8gLS0tIFN5bnRoIEpvYiAtLS1cbiAgICBqb2JzLnN5bnRoID0ge1xuICAgICAgbmFtZTogJ1N5bnRoZXNpemUgQ0RLIGFwcGxpY2F0aW9uJyxcbiAgICAgIHJ1bnNPbjogWyd1YnVudHUtbGF0ZXN0J10sXG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgICBwYWNrYWdlczogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgfSxcbiAgICAgIGVudjogeyBDSTogJ3RydWUnIH0sXG4gICAgICBzdGVwczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ0NoZWNrb3V0JyxcbiAgICAgICAgICB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke0NIRUNLT1VUX1ZFUlNJT059YCxcbiAgICAgICAgICB3aXRoOiB7ICdmZXRjaC1kZXB0aCc6IDAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICB1c2VzOiBgYWN0aW9ucy9zZXR1cC1ub2RlQCR7U0VUVVBfTk9ERV9WRVJTSU9OfWAsXG4gICAgICAgICAgd2l0aDoge1xuICAgICAgICAgICAgJ25vZGUtdmVyc2lvbic6IG5vZGVWZXJzaW9uLFxuICAgICAgICAgICAgJ3JlZ2lzdHJ5LXVybCc6ICdodHRwczovL25wbS5wa2cuZ2l0aHViLmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdJbnN0YWxsIGRlcGVuZGVuY2llcycsXG4gICAgICAgICAgcnVuOiBpbnN0YWxsQ29tbWFuZCxcbiAgICAgICAgICBlbnY6IHsgTk9ERV9BVVRIX1RPS0VOOiAnJHt7IHNlY3JldHMuR0lUSFVCX1RPS0VOIH19JywgR0lUSFVCX1RPS0VOOiAnJHt7IHNlY3JldHMuR0lUSFVCX1RPS0VOIH19JyB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ1N5bnRoJyxcbiAgICAgICAgICBydW46IGAke2Nka0NvbW1hbmR9IHN5bnRoYCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdVcGxvYWQgY2xvdWQgYXNzZW1ibHknLFxuICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3VwbG9hZC1hcnRpZmFjdEAke1VQTE9BRF9BUlRJRkFDVF9WRVJTSU9OfWAsXG4gICAgICAgICAgd2l0aDoge1xuICAgICAgICAgICAgbmFtZTogJ2Nsb3VkLWFzc2VtYmx5JyxcbiAgICAgICAgICAgIHBhdGg6ICdjZGsub3V0LycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIC8vIC0tLSBQdWJsaXNoIEFzc2V0cyBKb2IgLS0tXG4gICAgY29uc3QgcHVibGlzaFN0ZXBzOiBhbnlbXSA9IFtcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ0NoZWNrb3V0JyxcbiAgICAgICAgdXNlczogYGFjdGlvbnMvY2hlY2tvdXRAJHtDSEVDS09VVF9WRVJTSU9OfWAsXG4gICAgICAgIHdpdGg6IHsgJ2ZldGNoLWRlcHRoJzogMCB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ1NldHVwIE5vZGUuanMnLFxuICAgICAgICB1c2VzOiBgYWN0aW9ucy9zZXR1cC1ub2RlQCR7U0VUVVBfTk9ERV9WRVJTSU9OfWAsXG4gICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAnbm9kZS12ZXJzaW9uJzogbm9kZVZlcnNpb24sXG4gICAgICAgICAgJ3JlZ2lzdHJ5LXVybCc6ICdodHRwczovL25wbS5wa2cuZ2l0aHViLmNvbScsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnSW5zdGFsbCBkZXBlbmRlbmNpZXMnLFxuICAgICAgICBydW46IGluc3RhbGxDb21tYW5kLFxuICAgICAgICBlbnY6IHsgTk9ERV9BVVRIX1RPS0VOOiAnJHt7IHNlY3JldHMuR0lUSFVCX1RPS0VOIH19JywgR0lUSFVCX1RPS0VOOiAnJHt7IHNlY3JldHMuR0lUSFVCX1RPS0VOIH19JyB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ0Rvd25sb2FkIGNsb3VkIGFzc2VtYmx5JyxcbiAgICAgICAgdXNlczogYGFjdGlvbnMvZG93bmxvYWQtYXJ0aWZhY3RAJHtET1dOTE9BRF9BUlRJRkFDVF9WRVJTSU9OfWAsXG4gICAgICAgIHdpdGg6IHsgbmFtZTogJ2Nsb3VkLWFzc2VtYmx5JywgcGF0aDogJ2Nkay5vdXQvJyB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ0FXUyBDcmVkZW50aWFscycsXG4gICAgICAgIHVzZXM6IGBhd3MtYWN0aW9ucy9jb25maWd1cmUtYXdzLWNyZWRlbnRpYWxzQCR7QVdTX0NSRURFTlRJQUxTX1ZFUlNJT059YCxcbiAgICAgICAgd2l0aDoge1xuICAgICAgICAgICdyb2xlLXRvLWFzc3VtZSc6IGlhbVJvbGVBcm4sXG4gICAgICAgICAgJ3JvbGUtc2Vzc2lvbi1uYW1lJzogJ0dpdEh1YkFjdGlvbicsXG4gICAgICAgICAgJ2F3cy1yZWdpb24nOiBpYW1Sb2xlUmVnaW9uLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ1B1Ymxpc2ggYXNzZXRzJyxcbiAgICAgICAgcnVuOiAnbnB4IGNkay1hc3NldHMgcHVibGlzaCAtcCBjZGsub3V0LyoqLyotYXNzZXRzLmpzb24nLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgaWYgKHVzZUdpdGh1YlBhY2thZ2VzRm9yQXNzZW1ibHkpIHtcbiAgICAgIHB1Ymxpc2hTdGVwcy5wdXNoKFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ0NvbmZpZ3VyZSBnaXQgaWRlbnRpdHknLFxuICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgJ2dpdCBjb25maWcgdXNlci5uYW1lIFwiZ2l0aHViLWFjdGlvbnNbYm90XVwiJyxcbiAgICAgICAgICAgICdnaXQgY29uZmlnIHVzZXIuZW1haWwgXCI0MTg5ODI4MitnaXRodWItYWN0aW9uc1tib3RdQHVzZXJzLm5vcmVwbHkuZ2l0aHViLmNvbVwiJyxcbiAgICAgICAgICBdLmpvaW4oJ1xcbicpLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ0NyZWF0ZSBhc3NlbWJseSBwYWNrYWdlJyxcbiAgICAgICAgICBydW46IFtcbiAgICAgICAgICAgIGBlY2hvICcke0pTT04uc3RyaW5naWZ5KHsgbmFtZTogYCR7cGtnTmFtZXNwYWNlfS8ke2FwcE5hbWV9YCwgdmVyc2lvbjogJzAuMC4wJyB9KX0nID4gY2RrLm91dC9wYWNrYWdlLmpzb25gLFxuICAgICAgICAgICAgJ2NkIGNkay5vdXQgJiYgbnBtIHZlcnNpb24gLS1uby1naXQtdGFnLXZlcnNpb24gZnJvbS1naXQgfHwgbnBtIHZlcnNpb24gLS1uby1naXQtdGFnLXZlcnNpb24gcGF0Y2gnLFxuICAgICAgICAgIF0uam9pbignXFxuJyksXG4gICAgICAgICAgZW52OiB7IE5PREVfQVVUSF9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScsIEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdQdWJsaXNoIGFzc2VtYmx5IHRvIEdpdEh1YiBQYWNrYWdlcycsXG4gICAgICAgICAgcnVuOiAnY2QgY2RrLm91dCAmJiBucG0gcHVibGlzaCcsXG4gICAgICAgICAgZW52OiB7IE5PREVfQVVUSF9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScsIEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSxcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgam9ic1sncHVibGlzaC1hc3NldHMnXSA9IHtcbiAgICAgIG5hbWU6ICdQdWJsaXNoIGFzc2V0cyB0byBBV1MnLFxuICAgICAgbmVlZHM6IFsnc3ludGgnXSxcbiAgICAgIHJ1bnNPbjogWyd1YnVudHUtbGF0ZXN0J10sXG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgICAgcGFja2FnZXM6IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgIGlkVG9rZW46IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICB9LFxuICAgICAgZW52OiB7IENJOiAndHJ1ZScgfSxcbiAgICAgIHN0ZXBzOiBwdWJsaXNoU3RlcHMsXG4gICAgfTtcblxuICAgIC8vIC0tLSBQZXItU3RhZ2UgRGVwbG95IEpvYnMgLS0tXG4gICAgZm9yIChjb25zdCBzdGFnZSBvZiBzdGFnZXMpIHtcbiAgICAgIGNvbnN0IGpvYklkID0gYGRlcGxveS0ke3RvS2ViYWJDYXNlKHN0YWdlLm5hbWUpfWA7XG4gICAgICBjb25zdCBzdGFja3MgPVxuICAgICAgICBzdGFnZS5zdGFja3MgPz8gW2Ake3N0YWNrUHJlZml4fS0ke3N0YWdlLm5hbWV9YF07XG4gICAgICBjb25zdCBnaXRodWJFbnYgPSBzdGFnZS5lbnZpcm9ubWVudCA/PyBzdGFnZS5uYW1lO1xuICAgICAgY29uc3Qgcm9sZUFybiA9IHN0YWdlLmlhbVJvbGVBcm4gPz8gaWFtUm9sZUFybjtcbiAgICAgIGNvbnN0IHJvbGVSZWdpb24gPVxuICAgICAgICBzdGFnZS5pYW1Sb2xlUmVnaW9uID8/IGlhbVJvbGVSZWdpb24gPz8gc3RhZ2UuZW52LnJlZ2lvbjtcblxuICAgICAgLy8gQ29tcHV0ZSBuZWVkc1xuICAgICAgbGV0IG5lZWRzOiBzdHJpbmdbXTtcbiAgICAgIGlmIChzdGFnZS5kZXBlbmRzT24gJiYgc3RhZ2UuZGVwZW5kc09uLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbmVlZHMgPSBzdGFnZS5kZXBlbmRzT24ubWFwKFxuICAgICAgICAgIChkZXApID0+IGBkZXBsb3ktJHt0b0tlYmFiQ2FzZShkZXApfWAsXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZWVkcyA9IFsncHVibGlzaC1hc3NldHMnXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVwbG95Q29tbWFuZCA9IHN0YWNrc1xuICAgICAgICAubWFwKChzKSA9PiBgJHtjZGtDb21tYW5kfSBkZXBsb3kgJHtzfSAtLXJlcXVpcmUtYXBwcm92YWwgbmV2ZXIgLS1hcHAgY2RrLm91dGApXG4gICAgICAgIC5qb2luKCcgJiYgJyk7XG5cbiAgICAgIGpvYnNbam9iSWRdID0ge1xuICAgICAgICBuYW1lOiBgRGVwbG95ICR7c3RhZ2UubmFtZX1gLFxuICAgICAgICBuZWVkczogbmVlZHMsXG4gICAgICAgIHJ1bnNPbjogWyd1YnVudHUtbGF0ZXN0J10sXG4gICAgICAgIGVudmlyb25tZW50OiBnaXRodWJFbnYsXG4gICAgICAgIGNvbmN1cnJlbmN5OiB7XG4gICAgICAgICAgJ2dyb3VwJzogYGRlcGxveS0ke3RvS2ViYWJDYXNlKHN0YWdlLm5hbWUpfWAsXG4gICAgICAgICAgJ2NhbmNlbC1pbi1wcm9ncmVzcyc6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICAgIGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLlJFQUQsXG4gICAgICAgICAgcGFja2FnZXM6IEpvYlBlcm1pc3Npb24uUkVBRCxcbiAgICAgICAgICBpZFRva2VuOiBKb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgICB9LFxuICAgICAgICBlbnY6IHsgQ0k6ICd0cnVlJyB9LFxuICAgICAgICBzdGVwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdDaGVja291dCcsXG4gICAgICAgICAgICB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke0NIRUNLT1VUX1ZFUlNJT059YCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3NldHVwLW5vZGVAJHtTRVRVUF9OT0RFX1ZFUlNJT059YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ25vZGUtdmVyc2lvbic6IG5vZGVWZXJzaW9uLFxuICAgICAgICAgICAgICAncmVnaXN0cnktdXJsJzogJ2h0dHBzOi8vbnBtLnBrZy5naXRodWIuY29tJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnSW5zdGFsbCBkZXBlbmRlbmNpZXMnLFxuICAgICAgICAgICAgcnVuOiBpbnN0YWxsQ29tbWFuZCxcbiAgICAgICAgICAgIGVudjogeyBOT0RFX0FVVEhfVE9LRU46ICcke3sgc2VjcmV0cy5HSVRIVUJfVE9LRU4gfX0nLCBHSVRIVUJfVE9LRU46ICcke3sgc2VjcmV0cy5HSVRIVUJfVE9LRU4gfX0nIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnRG93bmxvYWQgY2xvdWQgYXNzZW1ibHknLFxuICAgICAgICAgICAgdXNlczogYGFjdGlvbnMvZG93bmxvYWQtYXJ0aWZhY3RAJHtET1dOTE9BRF9BUlRJRkFDVF9WRVJTSU9OfWAsXG4gICAgICAgICAgICB3aXRoOiB7IG5hbWU6ICdjbG91ZC1hc3NlbWJseScsIHBhdGg6ICdjZGsub3V0LycgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdBV1MgQ3JlZGVudGlhbHMnLFxuICAgICAgICAgICAgdXNlczogYGF3cy1hY3Rpb25zL2NvbmZpZ3VyZS1hd3MtY3JlZGVudGlhbHNAJHtBV1NfQ1JFREVOVElBTFNfVkVSU0lPTn1gLFxuICAgICAgICAgICAgd2l0aDoge1xuICAgICAgICAgICAgICAncm9sZS10by1hc3N1bWUnOiByb2xlQXJuLFxuICAgICAgICAgICAgICAncm9sZS1zZXNzaW9uLW5hbWUnOiAnR2l0SHViQWN0aW9uJyxcbiAgICAgICAgICAgICAgJ2F3cy1yZWdpb24nOiByb2xlUmVnaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IGBEZXBsb3kgJHtzdGFnZS5uYW1lfWAsXG4gICAgICAgICAgICBydW46IGRlcGxveUNvbW1hbmQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIC8vIENyZWF0ZSBwcm9qZW4gdGFzayBmb3IgbG9jYWwgdXNhZ2VcbiAgICAgIHByb2plY3QuYWRkVGFzayhgZGVwbG95OiR7c3RhZ2UubmFtZX1gLCB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBgRGVwbG95IHRvICR7c3RhZ2UubmFtZX1gLFxuICAgICAgICBleGVjOiBzdGFja3NcbiAgICAgICAgICAubWFwKChzKSA9PiBgJHtjZGtDb21tYW5kfSBkZXBsb3kgJHtzfSAtLXJlcXVpcmUtYXBwcm92YWwgbmV2ZXJgKVxuICAgICAgICAgIC5qb2luKCcgJiYgJyksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgYWxsIGpvYnMgdG8gdGhlIHdvcmtmbG93XG4gICAgd29ya2Zsb3cuYWRkSm9icyhqb2JzKTtcblxuICAgIC8vIC0tLSBEaXNwYXRjaCBXb3JrZmxvdyAtLS1cbiAgICBpZiAobWFudWFsRGVwbG95bWVudCAmJiB1c2VHaXRodWJQYWNrYWdlc0ZvckFzc2VtYmx5KSB7XG4gICAgICBuZXcgQ2RrRGVwbG95RGlzcGF0Y2hXb3JrZmxvdyhwcm9qZWN0LCB7XG4gICAgICAgIHN0YWdlcyxcbiAgICAgICAgcGtnTmFtZXNwYWNlLFxuICAgICAgICBhcHBOYW1lLFxuICAgICAgICBzdGFja1ByZWZpeCxcbiAgICAgICAgaWFtUm9sZUFybixcbiAgICAgICAgaWFtUm9sZVJlZ2lvbixcbiAgICAgICAgbm9kZVZlcnNpb24sXG4gICAgICAgIGNka0NvbW1hbmQsXG4gICAgICAgIGluc3RhbGxDb21tYW5kLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogSW50ZXJuYWwgaGVscGVyIHRvIGJ1aWxkIGRlcGxveSBkaXNwYXRjaCB3b3JrZmxvdyBvcHRpb25zIGZyb20gcGlwZWxpbmUgb3B0aW9ucy5cbiAqIEV4cG9ydGVkIGZvciB1c2UgYnkgQ2RrRGVwbG95RGlzcGF0Y2hXb3JrZmxvdy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBsb3lEaXNwYXRjaEludGVybmFsT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHN0YWdlczogRGVwbG95U3RhZ2VPcHRpb25zW107XG4gIHJlYWRvbmx5IHBrZ05hbWVzcGFjZTogc3RyaW5nO1xuICByZWFkb25seSBhcHBOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YWNrUHJlZml4OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGlhbVJvbGVBcm46IHN0cmluZztcbiAgcmVhZG9ubHkgaWFtUm9sZVJlZ2lvbjogc3RyaW5nO1xuICByZWFkb25seSBub2RlVmVyc2lvbjogc3RyaW5nO1xuICByZWFkb25seSBjZGtDb21tYW5kOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGluc3RhbGxDb21tYW5kOiBzdHJpbmc7XG59XG4iXX0=
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './types';
2
+ export * from './CdkDeployPipeline';
3
+ export * from './CdkDeployDispatchWorkflow';
4
+ export * from './utils';
package/lib/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./CdkDeployPipeline"), exports);
19
+ __exportStar(require("./CdkDeployDispatchWorkflow"), exports);
20
+ __exportStar(require("./utils"), exports);
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDBDQUF3QjtBQUN4QixzREFBb0M7QUFDcEMsOERBQTRDO0FBQzVDLDBDQUF3QiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vdHlwZXMnO1xuZXhwb3J0ICogZnJvbSAnLi9DZGtEZXBsb3lQaXBlbGluZSc7XG5leHBvcnQgKiBmcm9tICcuL0Nka0RlcGxveURpc3BhdGNoV29ya2Zsb3cnO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscyc7XG4iXX0=
package/lib/types.d.ts ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * AWS environment target for a deployment stage.
3
+ */
4
+ export interface AwsEnvironment {
5
+ /** AWS account ID */
6
+ readonly account: string;
7
+ /** AWS region */
8
+ readonly region: string;
9
+ }
10
+ /**
11
+ * Configuration for a single deployment stage.
12
+ */
13
+ export interface DeployStageOptions {
14
+ /** Stage name (used as suffix in job IDs and stack names, e.g., 'Sandbox', 'Production') */
15
+ readonly name: string;
16
+ /** AWS target environment (account + region) */
17
+ readonly env: AwsEnvironment;
18
+ /**
19
+ * GitHub Environment name for protection rules, secrets scoping, and deployment approvals.
20
+ * @default - uses the stage name
21
+ */
22
+ readonly environment?: string;
23
+ /**
24
+ * Override the default OIDC role ARN for this stage.
25
+ * Useful for cross-account deployments where each account has its own role.
26
+ */
27
+ readonly iamRoleArn?: string;
28
+ /**
29
+ * Override the default AWS region for OIDC credential assumption.
30
+ * @default - uses the pipeline-level iamRoleRegion or the stage env.region
31
+ */
32
+ readonly iamRoleRegion?: string;
33
+ /**
34
+ * Stage names that must complete successfully before this stage runs.
35
+ * Stages with no dependsOn run in parallel after the publish-assets job.
36
+ *
37
+ * @example ['Sandbox', 'Dev'] // waits for both before deploying
38
+ * @default - depends only on publish-assets (runs as soon as assets are ready)
39
+ */
40
+ readonly dependsOn?: string[];
41
+ /**
42
+ * Specific CDK stack names to deploy in this stage.
43
+ * @default - ['{stackPrefix}-{stageName}']
44
+ */
45
+ readonly stacks?: string[];
46
+ }
47
+ /**
48
+ * Configuration for the CDK deploy pipeline.
49
+ */
50
+ export interface CdkDeployPipelineOptions {
51
+ /** npm scope for versioned cloud assembly packages (e.g., '@defiance-digital') */
52
+ readonly pkgNamespace: string;
53
+ /** Stack name prefix. Stage names are appended with a dash (e.g., 'MyApp' -> 'MyApp-Production') */
54
+ readonly stackPrefix: string;
55
+ /** Default OIDC role ARN for AWS credential assumption */
56
+ readonly iamRoleArn: string;
57
+ /**
58
+ * Default AWS region for OIDC credential assumption.
59
+ * @default 'us-east-1'
60
+ */
61
+ readonly iamRoleRegion?: string;
62
+ /**
63
+ * Node.js version for workflow runners.
64
+ * @default '24.x'
65
+ */
66
+ readonly nodeVersion?: string;
67
+ /**
68
+ * CDK CLI command prefix.
69
+ * @default 'npx cdk'
70
+ */
71
+ readonly cdkCommand?: string;
72
+ /**
73
+ * Package install command.
74
+ * @default 'yarn install --check-files --frozen-lockfile'
75
+ */
76
+ readonly installCommand?: string;
77
+ /** Deployment stages in declaration order */
78
+ readonly stages: DeployStageOptions[];
79
+ /**
80
+ * Generate a workflow_dispatch workflow for manual deployments and rollbacks.
81
+ * @default true
82
+ */
83
+ readonly manualDeployment?: boolean;
84
+ /**
85
+ * Version and publish cloud assembly to GitHub Packages for rollback support.
86
+ * @default true
87
+ */
88
+ readonly useGithubPackagesForAssembly?: boolean;
89
+ /**
90
+ * Branch that triggers deployments on push.
91
+ * @default 'main'
92
+ */
93
+ readonly branchName?: string;
94
+ }
package/lib/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQVdTIGVudmlyb25tZW50IHRhcmdldCBmb3IgYSBkZXBsb3ltZW50IHN0YWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF3c0Vudmlyb25tZW50IHtcbiAgLyoqIEFXUyBhY2NvdW50IElEICovXG4gIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZztcbiAgLyoqIEFXUyByZWdpb24gKi9cbiAgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgYSBzaW5nbGUgZGVwbG95bWVudCBzdGFnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBsb3lTdGFnZU9wdGlvbnMge1xuICAvKiogU3RhZ2UgbmFtZSAodXNlZCBhcyBzdWZmaXggaW4gam9iIElEcyBhbmQgc3RhY2sgbmFtZXMsIGUuZy4sICdTYW5kYm94JywgJ1Byb2R1Y3Rpb24nKSAqL1xuICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqIEFXUyB0YXJnZXQgZW52aXJvbm1lbnQgKGFjY291bnQgKyByZWdpb24pICovXG4gIHJlYWRvbmx5IGVudjogQXdzRW52aXJvbm1lbnQ7XG5cbiAgLyoqXG4gICAqIEdpdEh1YiBFbnZpcm9ubWVudCBuYW1lIGZvciBwcm90ZWN0aW9uIHJ1bGVzLCBzZWNyZXRzIHNjb3BpbmcsIGFuZCBkZXBsb3ltZW50IGFwcHJvdmFscy5cbiAgICogQGRlZmF1bHQgLSB1c2VzIHRoZSBzdGFnZSBuYW1lXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IHN0cmluZztcblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIGRlZmF1bHQgT0lEQyByb2xlIEFSTiBmb3IgdGhpcyBzdGFnZS5cbiAgICogVXNlZnVsIGZvciBjcm9zcy1hY2NvdW50IGRlcGxveW1lbnRzIHdoZXJlIGVhY2ggYWNjb3VudCBoYXMgaXRzIG93biByb2xlLlxuICAgKi9cbiAgcmVhZG9ubHkgaWFtUm9sZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIGRlZmF1bHQgQVdTIHJlZ2lvbiBmb3IgT0lEQyBjcmVkZW50aWFsIGFzc3VtcHRpb24uXG4gICAqIEBkZWZhdWx0IC0gdXNlcyB0aGUgcGlwZWxpbmUtbGV2ZWwgaWFtUm9sZVJlZ2lvbiBvciB0aGUgc3RhZ2UgZW52LnJlZ2lvblxuICAgKi9cbiAgcmVhZG9ubHkgaWFtUm9sZVJlZ2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogU3RhZ2UgbmFtZXMgdGhhdCBtdXN0IGNvbXBsZXRlIHN1Y2Nlc3NmdWxseSBiZWZvcmUgdGhpcyBzdGFnZSBydW5zLlxuICAgKiBTdGFnZXMgd2l0aCBubyBkZXBlbmRzT24gcnVuIGluIHBhcmFsbGVsIGFmdGVyIHRoZSBwdWJsaXNoLWFzc2V0cyBqb2IuXG4gICAqXG4gICAqIEBleGFtcGxlIFsnU2FuZGJveCcsICdEZXYnXSAvLyB3YWl0cyBmb3IgYm90aCBiZWZvcmUgZGVwbG95aW5nXG4gICAqIEBkZWZhdWx0IC0gZGVwZW5kcyBvbmx5IG9uIHB1Ymxpc2gtYXNzZXRzIChydW5zIGFzIHNvb24gYXMgYXNzZXRzIGFyZSByZWFkeSlcbiAgICovXG4gIHJlYWRvbmx5IGRlcGVuZHNPbj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpYyBDREsgc3RhY2sgbmFtZXMgdG8gZGVwbG95IGluIHRoaXMgc3RhZ2UuXG4gICAqIEBkZWZhdWx0IC0gWyd7c3RhY2tQcmVmaXh9LXtzdGFnZU5hbWV9J11cbiAgICovXG4gIHJlYWRvbmx5IHN0YWNrcz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBDREsgZGVwbG95IHBpcGVsaW5lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENka0RlcGxveVBpcGVsaW5lT3B0aW9ucyB7XG4gIC8qKiBucG0gc2NvcGUgZm9yIHZlcnNpb25lZCBjbG91ZCBhc3NlbWJseSBwYWNrYWdlcyAoZS5nLiwgJ0BkZWZpYW5jZS1kaWdpdGFsJykgKi9cbiAgcmVhZG9ubHkgcGtnTmFtZXNwYWNlOiBzdHJpbmc7XG5cbiAgLyoqIFN0YWNrIG5hbWUgcHJlZml4LiBTdGFnZSBuYW1lcyBhcmUgYXBwZW5kZWQgd2l0aCBhIGRhc2ggKGUuZy4sICdNeUFwcCcgLT4gJ015QXBwLVByb2R1Y3Rpb24nKSAqL1xuICByZWFkb25seSBzdGFja1ByZWZpeDogc3RyaW5nO1xuXG4gIC8qKiBEZWZhdWx0IE9JREMgcm9sZSBBUk4gZm9yIEFXUyBjcmVkZW50aWFsIGFzc3VtcHRpb24gKi9cbiAgcmVhZG9ubHkgaWFtUm9sZUFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IEFXUyByZWdpb24gZm9yIE9JREMgY3JlZGVudGlhbCBhc3N1bXB0aW9uLlxuICAgKiBAZGVmYXVsdCAndXMtZWFzdC0xJ1xuICAgKi9cbiAgcmVhZG9ubHkgaWFtUm9sZVJlZ2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogTm9kZS5qcyB2ZXJzaW9uIGZvciB3b3JrZmxvdyBydW5uZXJzLlxuICAgKiBAZGVmYXVsdCAnMjQueCdcbiAgICovXG4gIHJlYWRvbmx5IG5vZGVWZXJzaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDREsgQ0xJIGNvbW1hbmQgcHJlZml4LlxuICAgKiBAZGVmYXVsdCAnbnB4IGNkaydcbiAgICovXG4gIHJlYWRvbmx5IGNka0NvbW1hbmQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFBhY2thZ2UgaW5zdGFsbCBjb21tYW5kLlxuICAgKiBAZGVmYXVsdCAneWFybiBpbnN0YWxsIC0tY2hlY2stZmlsZXMgLS1mcm96ZW4tbG9ja2ZpbGUnXG4gICAqL1xuICByZWFkb25seSBpbnN0YWxsQ29tbWFuZD86IHN0cmluZztcblxuICAvKiogRGVwbG95bWVudCBzdGFnZXMgaW4gZGVjbGFyYXRpb24gb3JkZXIgKi9cbiAgcmVhZG9ubHkgc3RhZ2VzOiBEZXBsb3lTdGFnZU9wdGlvbnNbXTtcblxuICAvKipcbiAgICogR2VuZXJhdGUgYSB3b3JrZmxvd19kaXNwYXRjaCB3b3JrZmxvdyBmb3IgbWFudWFsIGRlcGxveW1lbnRzIGFuZCByb2xsYmFja3MuXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IG1hbnVhbERlcGxveW1lbnQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBWZXJzaW9uIGFuZCBwdWJsaXNoIGNsb3VkIGFzc2VtYmx5IHRvIEdpdEh1YiBQYWNrYWdlcyBmb3Igcm9sbGJhY2sgc3VwcG9ydC5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgdXNlR2l0aHViUGFja2FnZXNGb3JBc3NlbWJseT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEJyYW5jaCB0aGF0IHRyaWdnZXJzIGRlcGxveW1lbnRzIG9uIHB1c2guXG4gICAqIEBkZWZhdWx0ICdtYWluJ1xuICAgKi9cbiAgcmVhZG9ubHkgYnJhbmNoTmFtZT86IHN0cmluZztcbn1cbiJdfQ==
package/lib/utils.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Convert a string to kebab-case for use in file names and job IDs.
3
+ */
4
+ export declare function toKebabCase(s: string): string;
5
+ /**
6
+ * Convert a string to a valid GitHub Actions job ID.
7
+ * Job IDs must start with a letter or underscore and contain only alphanumerics, hyphens, and underscores.
8
+ */
9
+ export declare function toGithubJobId(s: string): string;
10
+ /**
11
+ * Validate that there are no circular dependencies in the stage graph.
12
+ * @throws Error if a cycle is detected
13
+ */
14
+ export declare function validateNoCycles(stages: {
15
+ name: string;
16
+ dependsOn?: string[];
17
+ }[]): void;
package/lib/utils.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toKebabCase = toKebabCase;
4
+ exports.toGithubJobId = toGithubJobId;
5
+ exports.validateNoCycles = validateNoCycles;
6
+ /**
7
+ * Convert a string to kebab-case for use in file names and job IDs.
8
+ */
9
+ function toKebabCase(s) {
10
+ return s
11
+ .replace(/[^a-zA-Z0-9]+/g, '-')
12
+ .replace(/^-+|-+$/g, '')
13
+ .toLowerCase();
14
+ }
15
+ /**
16
+ * Convert a string to a valid GitHub Actions job ID.
17
+ * Job IDs must start with a letter or underscore and contain only alphanumerics, hyphens, and underscores.
18
+ */
19
+ function toGithubJobId(s) {
20
+ let out = s.replace(/[^A-Za-z0-9_-]+/g, '-');
21
+ out = out.replace(/-+/g, '-');
22
+ out = out.replace(/^-+|-+$/g, '');
23
+ out = out.toLowerCase();
24
+ if (!out || !/^[a-z_]/i.test(out)) {
25
+ out = `s-${out}`;
26
+ }
27
+ return out;
28
+ }
29
+ /**
30
+ * Validate that there are no circular dependencies in the stage graph.
31
+ * @throws Error if a cycle is detected
32
+ */
33
+ function validateNoCycles(stages) {
34
+ const visited = new Set();
35
+ const inStack = new Set();
36
+ const stageMap = new Map(stages.map((s) => [s.name, s]));
37
+ function visit(name, path) {
38
+ if (inStack.has(name)) {
39
+ throw new Error(`Circular dependency detected: ${[...path, name].join(' -> ')}`);
40
+ }
41
+ if (visited.has(name)) {
42
+ return;
43
+ }
44
+ inStack.add(name);
45
+ const stage = stageMap.get(name);
46
+ if (stage?.dependsOn) {
47
+ for (const dep of stage.dependsOn) {
48
+ visit(dep, [...path, name]);
49
+ }
50
+ }
51
+ inStack.delete(name);
52
+ visited.add(name);
53
+ }
54
+ for (const stage of stages) {
55
+ visit(stage.name, []);
56
+ }
57
+ }
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSxrQ0FLQztBQU1ELHNDQVNDO0FBTUQsNENBOEJDO0FBM0REOztHQUVHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLENBQVM7SUFDbkMsT0FBTyxDQUFDO1NBQ0wsT0FBTyxDQUFDLGdCQUFnQixFQUFFLEdBQUcsQ0FBQztTQUM5QixPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztTQUN2QixXQUFXLEVBQUUsQ0FBQztBQUNuQixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0IsYUFBYSxDQUFDLENBQVM7SUFDckMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM3QyxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUIsR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLEdBQUcsR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDeEIsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxHQUFHLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0IsZ0JBQWdCLENBQzlCLE1BQWdEO0lBRWhELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXpELFNBQVMsS0FBSyxDQUFDLElBQVksRUFBRSxJQUFjO1FBQ3pDLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQ2IsaUNBQWlDLENBQUMsR0FBRyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ2hFLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdEIsT0FBTztRQUNULENBQUM7UUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xCLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakMsSUFBSSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUM7WUFDckIsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2xDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzlCLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQzNCLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3hCLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGtlYmFiLWNhc2UgZm9yIHVzZSBpbiBmaWxlIG5hbWVzIGFuZCBqb2IgSURzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9LZWJhYkNhc2Uoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNcbiAgICAucmVwbGFjZSgvW15hLXpBLVowLTldKy9nLCAnLScpXG4gICAgLnJlcGxhY2UoL14tK3wtKyQvZywgJycpXG4gICAgLnRvTG93ZXJDYXNlKCk7XG59XG5cbi8qKlxuICogQ29udmVydCBhIHN0cmluZyB0byBhIHZhbGlkIEdpdEh1YiBBY3Rpb25zIGpvYiBJRC5cbiAqIEpvYiBJRHMgbXVzdCBzdGFydCB3aXRoIGEgbGV0dGVyIG9yIHVuZGVyc2NvcmUgYW5kIGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWNzLCBoeXBoZW5zLCBhbmQgdW5kZXJzY29yZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0dpdGh1YkpvYklkKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCBvdXQgPSBzLnJlcGxhY2UoL1teQS1aYS16MC05Xy1dKy9nLCAnLScpO1xuICBvdXQgPSBvdXQucmVwbGFjZSgvLSsvZywgJy0nKTtcbiAgb3V0ID0gb3V0LnJlcGxhY2UoL14tK3wtKyQvZywgJycpO1xuICBvdXQgPSBvdXQudG9Mb3dlckNhc2UoKTtcbiAgaWYgKCFvdXQgfHwgIS9eW2Etel9dL2kudGVzdChvdXQpKSB7XG4gICAgb3V0ID0gYHMtJHtvdXR9YDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIHRoYXQgdGhlcmUgYXJlIG5vIGNpcmN1bGFyIGRlcGVuZGVuY2llcyBpbiB0aGUgc3RhZ2UgZ3JhcGguXG4gKiBAdGhyb3dzIEVycm9yIGlmIGEgY3ljbGUgaXMgZGV0ZWN0ZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTm9DeWNsZXMoXG4gIHN0YWdlczogeyBuYW1lOiBzdHJpbmc7IGRlcGVuZHNPbj86IHN0cmluZ1tdIH1bXSxcbik6IHZvaWQge1xuICBjb25zdCB2aXNpdGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGNvbnN0IGluU3RhY2sgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3Qgc3RhZ2VNYXAgPSBuZXcgTWFwKHN0YWdlcy5tYXAoKHMpID0+IFtzLm5hbWUsIHNdKSk7XG5cbiAgZnVuY3Rpb24gdmlzaXQobmFtZTogc3RyaW5nLCBwYXRoOiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGlmIChpblN0YWNrLmhhcyhuYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ2lyY3VsYXIgZGVwZW5kZW5jeSBkZXRlY3RlZDogJHtbLi4ucGF0aCwgbmFtZV0uam9pbignIC0+ICcpfWAsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodmlzaXRlZC5oYXMobmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaW5TdGFjay5hZGQobmFtZSk7XG4gICAgY29uc3Qgc3RhZ2UgPSBzdGFnZU1hcC5nZXQobmFtZSk7XG4gICAgaWYgKHN0YWdlPy5kZXBlbmRzT24pIHtcbiAgICAgIGZvciAoY29uc3QgZGVwIG9mIHN0YWdlLmRlcGVuZHNPbikge1xuICAgICAgICB2aXNpdChkZXAsIFsuLi5wYXRoLCBuYW1lXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGluU3RhY2suZGVsZXRlKG5hbWUpO1xuICAgIHZpc2l0ZWQuYWRkKG5hbWUpO1xuICB9XG5cbiAgZm9yIChjb25zdCBzdGFnZSBvZiBzdGFnZXMpIHtcbiAgICB2aXNpdChzdGFnZS5uYW1lLCBbXSk7XG4gIH1cbn1cbiJdfQ==