@taimos/projen 0.1.78 → 0.1.80
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.
- package/.jsii +541 -10
- package/API.md +662 -0
- package/lib/components/amplify-deploy.d.ts +187 -0
- package/lib/components/amplify-deploy.js +248 -0
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +2 -1
- package/lib/components/production-release.js +1 -1
- package/lib/projects/cdk-app.js +1 -1
- package/lib/projects/cdk-construct.js +1 -1
- package/lib/projects/monorepo.d.ts +15 -1
- package/lib/projects/monorepo.js +7 -2
- package/lib/projects/private-cdk-app.js +1 -1
- package/lib/projects/private-ts-lib.js +1 -1
- package/lib/projects/prod-cdk-app.js +1 -1
- package/lib/projects/ts-lib.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { Component, github } from 'projen';
|
|
2
|
+
import { GitHubProject } from 'projen/lib/github';
|
|
3
|
+
/**
|
|
4
|
+
* One deploy stage: a git branch, the logical stage it serves, and the AWS
|
|
5
|
+
* account its Amplify apps live in.
|
|
6
|
+
*
|
|
7
|
+
* Both shapes seen in practice are expressible: separate accounts per stage
|
|
8
|
+
* (each entry has its own `account`), or a single account serving several
|
|
9
|
+
* branches (every entry repeats the same `account`, and the branch alone
|
|
10
|
+
* selects which Amplify branch is built).
|
|
11
|
+
*/
|
|
12
|
+
export interface AmplifyDeployStage {
|
|
13
|
+
/** The git branch the Amplify apps build from, e.g. `main` or `production`. */
|
|
14
|
+
readonly branch: string;
|
|
15
|
+
/**
|
|
16
|
+
* The logical stage this branch serves, e.g. `dev` or `prod`. Used as the
|
|
17
|
+
* GitHub environment so protection rules apply per stage.
|
|
18
|
+
*/
|
|
19
|
+
readonly stageName: string;
|
|
20
|
+
/** The AWS account hosting this stage's Amplify apps. */
|
|
21
|
+
readonly account: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One Amplify Hosting application whose builds CI drives.
|
|
25
|
+
*
|
|
26
|
+
* Mirrors a `MonorepoAmplifyApp` entry in the generated `amplify.yml`; the
|
|
27
|
+
* `appRoot` should match so a build is triggered by exactly the directory it is
|
|
28
|
+
* built from.
|
|
29
|
+
*/
|
|
30
|
+
export interface AmplifyDeployApp {
|
|
31
|
+
/**
|
|
32
|
+
* Short key identifying the app. Used in the app-id SSM parameter path and,
|
|
33
|
+
* by default, in the workflow name.
|
|
34
|
+
*
|
|
35
|
+
* Must match the key the CDK side registers the app under.
|
|
36
|
+
*/
|
|
37
|
+
readonly key: string;
|
|
38
|
+
/**
|
|
39
|
+
* The package path that is the Amplify app root, e.g. `packages/frontend`.
|
|
40
|
+
* `<appRoot>/**` becomes a push trigger path.
|
|
41
|
+
*/
|
|
42
|
+
readonly appRoot: string;
|
|
43
|
+
/**
|
|
44
|
+
* Extra path globs that affect this app's build output.
|
|
45
|
+
*
|
|
46
|
+
* Set this for workspace packages the app consumes via `workspace:*` and that
|
|
47
|
+
* the build spec pre-builds — a shared API package, say. Without them a change
|
|
48
|
+
* to shared types would not rebuild the app and it would ship stale.
|
|
49
|
+
*
|
|
50
|
+
* @default []
|
|
51
|
+
*/
|
|
52
|
+
readonly dependencyPaths?: string[];
|
|
53
|
+
/**
|
|
54
|
+
* Human-readable name used in step names and log lines.
|
|
55
|
+
*
|
|
56
|
+
* @default - the `key`
|
|
57
|
+
*/
|
|
58
|
+
readonly label?: string;
|
|
59
|
+
/**
|
|
60
|
+
* The generated workflow name, which is also its `.yml` file name.
|
|
61
|
+
*
|
|
62
|
+
* @default - `<key>-deploy`
|
|
63
|
+
*/
|
|
64
|
+
readonly workflowName?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface GitHubAmplifyDeployOptions {
|
|
67
|
+
/** The Amplify apps to generate deploy workflows for. At least one. */
|
|
68
|
+
readonly apps: AmplifyDeployApp[];
|
|
69
|
+
/** The branches that deploy, and the account each one deploys into. At least one. */
|
|
70
|
+
readonly stages: AmplifyDeployStage[];
|
|
71
|
+
/**
|
|
72
|
+
* The GitHub OIDC deployment role every workflow assumes first, typically in
|
|
73
|
+
* a management account. The per-stage build-trigger role is reached from it
|
|
74
|
+
* by role chaining, so it must be allowed to `sts:AssumeRole` on that role —
|
|
75
|
+
* an IAM grant that lives outside the generated code.
|
|
76
|
+
*/
|
|
77
|
+
readonly deploymentRoleArn: string;
|
|
78
|
+
/**
|
|
79
|
+
* Name of the per-account IAM role CI chains into to start builds.
|
|
80
|
+
*
|
|
81
|
+
* The same name is expected in every stage account, so the workflow can build
|
|
82
|
+
* the ARN from the account id alone. The CDK side must create a role with
|
|
83
|
+
* exactly this name.
|
|
84
|
+
*
|
|
85
|
+
* @default - `<project name>-amplify-build-trigger`
|
|
86
|
+
*/
|
|
87
|
+
readonly buildTriggerRoleName?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Prefix of the SSM parameter path holding each app's Amplify app id. The
|
|
90
|
+
* full path is `<prefix>/<app key>/app-id`.
|
|
91
|
+
*
|
|
92
|
+
* Reading the app id at run time means CI never hardcodes an id that changes
|
|
93
|
+
* whenever an app is replaced.
|
|
94
|
+
*
|
|
95
|
+
* @default - `/<project name>/amplify`
|
|
96
|
+
*/
|
|
97
|
+
readonly parameterPrefix?: string;
|
|
98
|
+
/**
|
|
99
|
+
* The AWS region the Amplify apps live in.
|
|
100
|
+
*
|
|
101
|
+
* @default 'eu-central-1'
|
|
102
|
+
*/
|
|
103
|
+
readonly region?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Paths that change what *every* Amplify build produces, added to each app's
|
|
106
|
+
* own paths.
|
|
107
|
+
*
|
|
108
|
+
* @default - the Amplify build spec, the lockfile and the workspace file
|
|
109
|
+
*/
|
|
110
|
+
readonly sharedBuildPaths?: string[];
|
|
111
|
+
/**
|
|
112
|
+
* The runner tags used to select the runner.
|
|
113
|
+
*
|
|
114
|
+
* @default ['ubuntu-latest']
|
|
115
|
+
*/
|
|
116
|
+
readonly runnerTags?: string[];
|
|
117
|
+
/**
|
|
118
|
+
* Timeout for a deploy job, bounding a hung Amplify build.
|
|
119
|
+
*
|
|
120
|
+
* @default 45
|
|
121
|
+
*/
|
|
122
|
+
readonly timeoutMinutes?: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Adds one path-scoped deploy workflow per Amplify Hosting app.
|
|
126
|
+
*
|
|
127
|
+
* Amplify's own auto-build fires on every push to a tracked branch. In a
|
|
128
|
+
* monorepo that means every frontend rebuilds whenever anything changes — the
|
|
129
|
+
* marketing site rebuilding for a backend-only commit and vice versa, once per
|
|
130
|
+
* tracked branch. Amplify bills build minutes, so most of those are waste.
|
|
131
|
+
*
|
|
132
|
+
* Amplify's native answer, `AMPLIFY_DIFF_DEPLOY`, diffs exactly one directory
|
|
133
|
+
* (`AMPLIFY_MONOREPO_APP_ROOT`, overridable via `AMPLIFY_DIFF_DEPLOY_ROOT` —
|
|
134
|
+
* still a single path). That is enough for a self-contained app but not for one
|
|
135
|
+
* that also depends on a shared workspace package: a one-directory diff would
|
|
136
|
+
* ship a stale frontend whenever the shared types changed. GitHub's `paths:`
|
|
137
|
+
* filters accept multiple globs, so builds move to CI.
|
|
138
|
+
*
|
|
139
|
+
* Each generated workflow resolves the pushed branch to its stage and account,
|
|
140
|
+
* chains OIDC -> deployment role -> build-trigger role, reads the app id from
|
|
141
|
+
* SSM, starts a `RELEASE` job and polls until it reaches a terminal state — so
|
|
142
|
+
* a failed Amplify build fails the workflow instead of passing silently.
|
|
143
|
+
*
|
|
144
|
+
* This component generates the CI half only. The infrastructure half belongs in
|
|
145
|
+
* the project's own CDK app, which must:
|
|
146
|
+
*
|
|
147
|
+
* 1. set `autoBuild: false` on every branch these workflows build,
|
|
148
|
+
* 2. publish each app's id to `<parameterPrefix>/<key>/app-id`, and
|
|
149
|
+
* 3. create a role named `buildTriggerRoleName` in each stage account,
|
|
150
|
+
* trusted by `deploymentRoleArn` and granting `amplify:StartJob` +
|
|
151
|
+
* `amplify:GetJob` on the tracked branch ARNs only.
|
|
152
|
+
*
|
|
153
|
+
* Use `buildTriggerRoleName` and `appIdParameterName()` from the projenrc to
|
|
154
|
+
* keep those names in step; a mismatch fails the workflow loudly at the
|
|
155
|
+
* assume-role or parameter-read step rather than skipping a deploy.
|
|
156
|
+
*/
|
|
157
|
+
export declare class GitHubAmplifyDeploy extends Component {
|
|
158
|
+
/** The generated deploy workflows, one per app. */
|
|
159
|
+
readonly workflows: github.GithubWorkflow[];
|
|
160
|
+
/** Name of the IAM role CI chains into, in every stage account. */
|
|
161
|
+
readonly buildTriggerRoleName: string;
|
|
162
|
+
/** Prefix of the SSM parameter path holding each app's Amplify app id. */
|
|
163
|
+
readonly parameterPrefix: string;
|
|
164
|
+
private readonly region;
|
|
165
|
+
constructor(scope: GitHubProject, options: GitHubAmplifyDeployOptions);
|
|
166
|
+
/**
|
|
167
|
+
* The SSM parameter path holding an app's Amplify app id. The CDK side must
|
|
168
|
+
* publish the id under exactly this name.
|
|
169
|
+
*/
|
|
170
|
+
appIdParameterName(key: string): string;
|
|
171
|
+
/**
|
|
172
|
+
* The job-level `environment:` expression mapping branch to stage, so each
|
|
173
|
+
* stage keeps whatever GitHub environment protection rules it has. The first
|
|
174
|
+
* stage is the fallback; every later stage gets an explicit branch test.
|
|
175
|
+
*/
|
|
176
|
+
private environmentExpression;
|
|
177
|
+
/**
|
|
178
|
+
* Bash mapping the pushed branch to its stage and build-trigger role ARN, so
|
|
179
|
+
* account ids live only in the projenrc. A branch that is not a deploy branch
|
|
180
|
+
* is an error rather than a silent no-op.
|
|
181
|
+
*/
|
|
182
|
+
private resolveStageScript;
|
|
183
|
+
/** Reads the app id from SSM and starts a RELEASE build. */
|
|
184
|
+
private startBuildScript;
|
|
185
|
+
/** Polls the job until it reaches a terminal state, failing on a bad one. */
|
|
186
|
+
private waitForBuildScript;
|
|
187
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitHubAmplifyDeploy = void 0;
|
|
4
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
+
const projen_1 = require("projen");
|
|
6
|
+
/** Paths that invalidate every app's build output. */
|
|
7
|
+
const DEFAULT_SHARED_BUILD_PATHS = [
|
|
8
|
+
'amplify.yml',
|
|
9
|
+
'pnpm-lock.yaml',
|
|
10
|
+
'pnpm-workspace.yaml',
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Adds one path-scoped deploy workflow per Amplify Hosting app.
|
|
14
|
+
*
|
|
15
|
+
* Amplify's own auto-build fires on every push to a tracked branch. In a
|
|
16
|
+
* monorepo that means every frontend rebuilds whenever anything changes — the
|
|
17
|
+
* marketing site rebuilding for a backend-only commit and vice versa, once per
|
|
18
|
+
* tracked branch. Amplify bills build minutes, so most of those are waste.
|
|
19
|
+
*
|
|
20
|
+
* Amplify's native answer, `AMPLIFY_DIFF_DEPLOY`, diffs exactly one directory
|
|
21
|
+
* (`AMPLIFY_MONOREPO_APP_ROOT`, overridable via `AMPLIFY_DIFF_DEPLOY_ROOT` —
|
|
22
|
+
* still a single path). That is enough for a self-contained app but not for one
|
|
23
|
+
* that also depends on a shared workspace package: a one-directory diff would
|
|
24
|
+
* ship a stale frontend whenever the shared types changed. GitHub's `paths:`
|
|
25
|
+
* filters accept multiple globs, so builds move to CI.
|
|
26
|
+
*
|
|
27
|
+
* Each generated workflow resolves the pushed branch to its stage and account,
|
|
28
|
+
* chains OIDC -> deployment role -> build-trigger role, reads the app id from
|
|
29
|
+
* SSM, starts a `RELEASE` job and polls until it reaches a terminal state — so
|
|
30
|
+
* a failed Amplify build fails the workflow instead of passing silently.
|
|
31
|
+
*
|
|
32
|
+
* This component generates the CI half only. The infrastructure half belongs in
|
|
33
|
+
* the project's own CDK app, which must:
|
|
34
|
+
*
|
|
35
|
+
* 1. set `autoBuild: false` on every branch these workflows build,
|
|
36
|
+
* 2. publish each app's id to `<parameterPrefix>/<key>/app-id`, and
|
|
37
|
+
* 3. create a role named `buildTriggerRoleName` in each stage account,
|
|
38
|
+
* trusted by `deploymentRoleArn` and granting `amplify:StartJob` +
|
|
39
|
+
* `amplify:GetJob` on the tracked branch ARNs only.
|
|
40
|
+
*
|
|
41
|
+
* Use `buildTriggerRoleName` and `appIdParameterName()` from the projenrc to
|
|
42
|
+
* keep those names in step; a mismatch fails the workflow loudly at the
|
|
43
|
+
* assume-role or parameter-read step rather than skipping a deploy.
|
|
44
|
+
*/
|
|
45
|
+
class GitHubAmplifyDeploy extends projen_1.Component {
|
|
46
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.GitHubAmplifyDeploy", version: "0.1.80" };
|
|
47
|
+
/** The generated deploy workflows, one per app. */
|
|
48
|
+
workflows = [];
|
|
49
|
+
/** Name of the IAM role CI chains into, in every stage account. */
|
|
50
|
+
buildTriggerRoleName;
|
|
51
|
+
/** Prefix of the SSM parameter path holding each app's Amplify app id. */
|
|
52
|
+
parameterPrefix;
|
|
53
|
+
region;
|
|
54
|
+
constructor(scope, options) {
|
|
55
|
+
super(scope);
|
|
56
|
+
if (!scope.github) {
|
|
57
|
+
throw new Error('GitHubAmplifyDeploy requires a project with GitHub enabled');
|
|
58
|
+
}
|
|
59
|
+
if (options.apps.length === 0) {
|
|
60
|
+
throw new Error('GitHubAmplifyDeploy requires at least one app');
|
|
61
|
+
}
|
|
62
|
+
if (options.stages.length === 0) {
|
|
63
|
+
throw new Error('GitHubAmplifyDeploy requires at least one stage');
|
|
64
|
+
}
|
|
65
|
+
const keys = options.apps.map((app) => app.key);
|
|
66
|
+
const duplicateKey = keys.find((key, index) => keys.indexOf(key) !== index);
|
|
67
|
+
if (duplicateKey) {
|
|
68
|
+
throw new Error(`GitHubAmplifyDeploy app keys must be unique, got '${duplicateKey}' twice`);
|
|
69
|
+
}
|
|
70
|
+
const branches = options.stages.map((stage) => stage.branch);
|
|
71
|
+
const duplicateBranch = branches.find((branch, index) => branches.indexOf(branch) !== index);
|
|
72
|
+
if (duplicateBranch) {
|
|
73
|
+
throw new Error(`GitHubAmplifyDeploy stage branches must be unique, got '${duplicateBranch}' twice`);
|
|
74
|
+
}
|
|
75
|
+
this.buildTriggerRoleName = options.buildTriggerRoleName ?? `${scope.name}-amplify-build-trigger`;
|
|
76
|
+
this.parameterPrefix = options.parameterPrefix ?? `/${scope.name}/amplify`;
|
|
77
|
+
this.region = options.region ?? 'eu-central-1';
|
|
78
|
+
const sharedBuildPaths = options.sharedBuildPaths ?? DEFAULT_SHARED_BUILD_PATHS;
|
|
79
|
+
const runnerTags = options.runnerTags ?? ['ubuntu-latest'];
|
|
80
|
+
const timeoutMinutes = options.timeoutMinutes ?? 45;
|
|
81
|
+
for (const app of options.apps) {
|
|
82
|
+
const label = app.label ?? app.key;
|
|
83
|
+
const workflowName = app.workflowName ?? `${app.key}-deploy`;
|
|
84
|
+
const workflow = new projen_1.github.GithubWorkflow(scope.github, workflowName);
|
|
85
|
+
workflow.on({
|
|
86
|
+
push: {
|
|
87
|
+
branches: options.stages.map((stage) => stage.branch),
|
|
88
|
+
paths: [
|
|
89
|
+
`${app.appRoot}/**`,
|
|
90
|
+
...(app.dependencyPaths ?? []),
|
|
91
|
+
...sharedBuildPaths,
|
|
92
|
+
// Changing the workflow itself should prove it still works.
|
|
93
|
+
`.github/workflows/${workflowName}.yml`,
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
// Manual redeploy, e.g. after a build-only failure.
|
|
97
|
+
workflowDispatch: {},
|
|
98
|
+
});
|
|
99
|
+
workflow.addJob('deploy', {
|
|
100
|
+
name: `Build and deploy the ${label} on Amplify`,
|
|
101
|
+
runsOn: runnerTags,
|
|
102
|
+
permissions: {
|
|
103
|
+
contents: projen_1.github.workflows.JobPermission.READ,
|
|
104
|
+
idToken: projen_1.github.workflows.JobPermission.WRITE,
|
|
105
|
+
},
|
|
106
|
+
environment: this.environmentExpression(options.stages),
|
|
107
|
+
concurrency: {
|
|
108
|
+
'group': `${workflowName}-\${{ github.ref_name }}`,
|
|
109
|
+
// Cancelling the workflow would not cancel the Amplify job it started,
|
|
110
|
+
// so let runs queue instead of orphaning builds.
|
|
111
|
+
'cancel-in-progress': false,
|
|
112
|
+
},
|
|
113
|
+
timeoutMinutes,
|
|
114
|
+
steps: [
|
|
115
|
+
{
|
|
116
|
+
name: 'Resolve stage',
|
|
117
|
+
id: 'stage',
|
|
118
|
+
run: this.resolveStageScript(options.stages),
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'AWS credentials — deployment role',
|
|
122
|
+
id: 'aws_credentials_deployment_role',
|
|
123
|
+
uses: 'aws-actions/configure-aws-credentials@v5',
|
|
124
|
+
with: {
|
|
125
|
+
'role-to-assume': options.deploymentRoleArn,
|
|
126
|
+
'role-session-name': 'GitHubAction',
|
|
127
|
+
'aws-region': this.region,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'AWS credentials — Amplify build trigger',
|
|
132
|
+
id: 'aws_credentials_amplify_build_trigger',
|
|
133
|
+
uses: 'aws-actions/configure-aws-credentials@v5',
|
|
134
|
+
with: {
|
|
135
|
+
'role-to-assume': '${{ steps.stage.outputs.role_arn }}',
|
|
136
|
+
'role-session-name': 'AmplifyBuildTrigger',
|
|
137
|
+
'aws-region': this.region,
|
|
138
|
+
// Chain from the deployment role rather than re-using the OIDC
|
|
139
|
+
// token, so no identity provider is needed in the stage account.
|
|
140
|
+
'role-chaining': true,
|
|
141
|
+
// The action tags sessions by default, which turns the chained
|
|
142
|
+
// call into AssumeRole + TagSession. The trust policy grants
|
|
143
|
+
// AssumeRole only, so tagging fails the step; the session is
|
|
144
|
+
// already tagged by the first assume anyway.
|
|
145
|
+
'role-skip-session-tagging': true,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: `Start ${label} build`,
|
|
150
|
+
id: 'start',
|
|
151
|
+
run: this.startBuildScript(app, label),
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'Wait for build to finish',
|
|
155
|
+
id: 'wait_for_build_to_finish',
|
|
156
|
+
run: this.waitForBuildScript(label),
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
this.workflows.push(workflow);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The SSM parameter path holding an app's Amplify app id. The CDK side must
|
|
165
|
+
* publish the id under exactly this name.
|
|
166
|
+
*/
|
|
167
|
+
appIdParameterName(key) {
|
|
168
|
+
return `${this.parameterPrefix}/${key}/app-id`;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The job-level `environment:` expression mapping branch to stage, so each
|
|
172
|
+
* stage keeps whatever GitHub environment protection rules it has. The first
|
|
173
|
+
* stage is the fallback; every later stage gets an explicit branch test.
|
|
174
|
+
*/
|
|
175
|
+
environmentExpression(stages) {
|
|
176
|
+
const [fallback, ...rest] = stages;
|
|
177
|
+
const tests = rest.map((s) => `github.ref_name == '${s.branch}' && '${s.stageName}' || `).join('');
|
|
178
|
+
return `\${{ ${tests}'${fallback.stageName}' }}`;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Bash mapping the pushed branch to its stage and build-trigger role ARN, so
|
|
182
|
+
* account ids live only in the projenrc. A branch that is not a deploy branch
|
|
183
|
+
* is an error rather than a silent no-op.
|
|
184
|
+
*/
|
|
185
|
+
resolveStageScript(stages) {
|
|
186
|
+
const cases = stages.map((s) => ` ${s.branch}) stage='${s.stageName}'; account='${s.account}' ;;`);
|
|
187
|
+
return [
|
|
188
|
+
'set -euo pipefail',
|
|
189
|
+
'case "$GITHUB_REF_NAME" in',
|
|
190
|
+
...cases,
|
|
191
|
+
' *)',
|
|
192
|
+
' echo "::error::$GITHUB_REF_NAME is not a deploy branch"',
|
|
193
|
+
' exit 1',
|
|
194
|
+
' ;;',
|
|
195
|
+
'esac',
|
|
196
|
+
`role="arn:aws:iam::$account:role/${this.buildTriggerRoleName}"`,
|
|
197
|
+
'echo "stage=$stage" >> "$GITHUB_OUTPUT"',
|
|
198
|
+
'echo "role_arn=$role" >> "$GITHUB_OUTPUT"',
|
|
199
|
+
'echo "Deploying $GITHUB_REF_NAME to stage $stage ($account)" >> "$GITHUB_STEP_SUMMARY"',
|
|
200
|
+
].join('\n');
|
|
201
|
+
}
|
|
202
|
+
/** Reads the app id from SSM and starts a RELEASE build. */
|
|
203
|
+
startBuildScript(app, label) {
|
|
204
|
+
return [
|
|
205
|
+
'set -euo pipefail',
|
|
206
|
+
`app_id="$(aws ssm get-parameter --name '${this.appIdParameterName(app.key)}' --query Parameter.Value --output text)"`,
|
|
207
|
+
'# RELEASE builds the current tip of the branch. That is normally $GITHUB_SHA;',
|
|
208
|
+
'# if two pushes race, the tip wins and the earlier run is redundant rather',
|
|
209
|
+
'# than wrong. The job concurrency group keeps that rare.',
|
|
210
|
+
'job_id="$(aws amplify start-job \\',
|
|
211
|
+
' --app-id "$app_id" \\',
|
|
212
|
+
' --branch-name "$GITHUB_REF_NAME" \\',
|
|
213
|
+
' --job-type RELEASE \\',
|
|
214
|
+
' --job-reason "GitHub Actions $GITHUB_WORKFLOW run $GITHUB_RUN_ID for $GITHUB_SHA" \\',
|
|
215
|
+
' --query jobSummary.jobId --output text)"',
|
|
216
|
+
'echo "app_id=$app_id" >> "$GITHUB_OUTPUT"',
|
|
217
|
+
'echo "job_id=$job_id" >> "$GITHUB_OUTPUT"',
|
|
218
|
+
`echo "Started ${label} Amplify job \$job_id on app \$app_id" >> "\$GITHUB_STEP_SUMMARY"`,
|
|
219
|
+
].join('\n');
|
|
220
|
+
}
|
|
221
|
+
/** Polls the job until it reaches a terminal state, failing on a bad one. */
|
|
222
|
+
waitForBuildScript(label) {
|
|
223
|
+
return [
|
|
224
|
+
'set -euo pipefail',
|
|
225
|
+
'while true; do',
|
|
226
|
+
' status="$(aws amplify get-job \\',
|
|
227
|
+
' --app-id "${{ steps.start.outputs.app_id }}" \\',
|
|
228
|
+
' --branch-name "$GITHUB_REF_NAME" \\',
|
|
229
|
+
' --job-id "${{ steps.start.outputs.job_id }}" \\',
|
|
230
|
+
' --query job.summary.status --output text)"',
|
|
231
|
+
' case "$status" in',
|
|
232
|
+
' SUCCEED)',
|
|
233
|
+
` echo "${label} build succeeded" >> "\$GITHUB_STEP_SUMMARY"`,
|
|
234
|
+
' exit 0',
|
|
235
|
+
' ;;',
|
|
236
|
+
' FAILED|CANCELLED)',
|
|
237
|
+
` echo "::error::${label} Amplify job \${{ steps.start.outputs.job_id }} ended as \$status"`,
|
|
238
|
+
' exit 1',
|
|
239
|
+
' ;;',
|
|
240
|
+
' esac',
|
|
241
|
+
' echo "status: $status"',
|
|
242
|
+
' sleep 15',
|
|
243
|
+
'done',
|
|
244
|
+
].join('\n');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.GitHubAmplifyDeploy = GitHubAmplifyDeploy;
|
|
248
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1wbGlmeS1kZXBsb3kuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9hbXBsaWZ5LWRlcGxveS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsbUNBQTJDO0FBNkkzQyxzREFBc0Q7QUFDdEQsTUFBTSwwQkFBMEIsR0FBRztJQUNqQyxhQUFhO0lBQ2IsZ0JBQWdCO0lBQ2hCLHFCQUFxQjtDQUN0QixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0NHO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxrQkFBUzs7SUFDaEQsbURBQW1EO0lBQ25DLFNBQVMsR0FBNEIsRUFBRSxDQUFDO0lBRXhELG1FQUFtRTtJQUNuRCxvQkFBb0IsQ0FBUztJQUU3QywwRUFBMEU7SUFDMUQsZUFBZSxDQUFTO0lBRXZCLE1BQU0sQ0FBUztJQUVoQyxZQUFZLEtBQW9CLEVBQUUsT0FBbUM7UUFDbkUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWIsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNsQixNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7UUFDaEYsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQztRQUM1RSxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELFlBQVksU0FBUyxDQUFDLENBQUM7UUFDOUYsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0QsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUM7UUFDN0YsSUFBSSxlQUFlLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxlQUFlLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZHLENBQUM7UUFFRCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksd0JBQXdCLENBQUM7UUFDbEcsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUMsZUFBZSxJQUFJLElBQUksS0FBSyxDQUFDLElBQUksVUFBVSxDQUFDO1FBQzNFLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxjQUFjLENBQUM7UUFFL0MsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLElBQUksMEJBQTBCLENBQUM7UUFDaEYsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzNELE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDO1FBRXBELEtBQUssTUFBTSxHQUFHLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQy9CLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQztZQUNuQyxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxJQUFJLEdBQUcsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDO1lBRTdELE1BQU0sUUFBUSxHQUFHLElBQUksZUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ3ZFLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQ1YsSUFBSSxFQUFFO29CQUNKLFFBQVEsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztvQkFDckQsS0FBSyxFQUFFO3dCQUNMLEdBQUcsR0FBRyxDQUFDLE9BQU8sS0FBSzt3QkFDbkIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksRUFBRSxDQUFDO3dCQUM5QixHQUFHLGdCQUFnQjt3QkFDbkIsNERBQTREO3dCQUM1RCxxQkFBcUIsWUFBWSxNQUFNO3FCQUN4QztpQkFDRjtnQkFDRCxvREFBb0Q7Z0JBQ3BELGdCQUFnQixFQUFFLEVBQUU7YUFDckIsQ0FBQyxDQUFDO1lBRUgsUUFBUSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7Z0JBQ3hCLElBQUksRUFBRSx3QkFBd0IsS0FBSyxhQUFhO2dCQUNoRCxNQUFNLEVBQUUsVUFBVTtnQkFDbEIsV0FBVyxFQUFFO29CQUNYLFFBQVEsRUFBRSxlQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxJQUFJO29CQUM3QyxPQUFPLEVBQUUsZUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSztpQkFDOUM7Z0JBQ0QsV0FBVyxFQUFFLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO2dCQUN2RCxXQUFXLEVBQUU7b0JBQ1gsT0FBTyxFQUFFLEdBQUcsWUFBWSwwQkFBMEI7b0JBQ2xELHVFQUF1RTtvQkFDdkUsaURBQWlEO29CQUNqRCxvQkFBb0IsRUFBRSxLQUFLO2lCQUM1QjtnQkFDRCxjQUFjO2dCQUNkLEtBQUssRUFBRTtvQkFDTDt3QkFDRSxJQUFJLEVBQUUsZUFBZTt3QkFDckIsRUFBRSxFQUFFLE9BQU87d0JBQ1gsR0FBRyxFQUFFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO3FCQUM3QztvQkFDRDt3QkFDRSxJQUFJLEVBQUUsbUNBQW1DO3dCQUN6QyxFQUFFLEVBQUUsaUNBQWlDO3dCQUNyQyxJQUFJLEVBQUUsMENBQTBDO3dCQUNoRCxJQUFJLEVBQUU7NEJBQ0osZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGlCQUFpQjs0QkFDM0MsbUJBQW1CLEVBQUUsY0FBYzs0QkFDbkMsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFNO3lCQUMxQjtxQkFDRjtvQkFDRDt3QkFDRSxJQUFJLEVBQUUseUNBQXlDO3dCQUMvQyxFQUFFLEVBQUUsdUNBQXVDO3dCQUMzQyxJQUFJLEVBQUUsMENBQTBDO3dCQUNoRCxJQUFJLEVBQUU7NEJBQ0osZ0JBQWdCLEVBQUUscUNBQXFDOzRCQUN2RCxtQkFBbUIsRUFBRSxxQkFBcUI7NEJBQzFDLFlBQVksRUFBRSxJQUFJLENBQUMsTUFBTTs0QkFDekIsK0RBQStEOzRCQUMvRCxpRUFBaUU7NEJBQ2pFLGVBQWUsRUFBRSxJQUFJOzRCQUNyQiwrREFBK0Q7NEJBQy9ELDZEQUE2RDs0QkFDN0QsNkRBQTZEOzRCQUM3RCw2Q0FBNkM7NEJBQzdDLDJCQUEyQixFQUFFLElBQUk7eUJBQ2xDO3FCQUNGO29CQUNEO3dCQUNFLElBQUksRUFBRSxTQUFTLEtBQUssUUFBUTt3QkFDNUIsRUFBRSxFQUFFLE9BQU87d0JBQ1gsR0FBRyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO3FCQUN2QztvQkFDRDt3QkFDRSxJQUFJLEVBQUUsMEJBQTBCO3dCQUNoQyxFQUFFLEVBQUUsMEJBQTBCO3dCQUM5QixHQUFHLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQztxQkFDcEM7aUJBQ0Y7YUFDRixDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNoQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLGtCQUFrQixDQUFDLEdBQVc7UUFDbkMsT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLElBQUksR0FBRyxTQUFTLENBQUM7SUFDakQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxxQkFBcUIsQ0FBQyxNQUE0QjtRQUN4RCxNQUFNLENBQUMsUUFBUSxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQ25DLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLHVCQUF1QixDQUFDLENBQUMsTUFBTSxTQUFTLENBQUMsQ0FBQyxTQUFTLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNuRyxPQUFPLFFBQVEsS0FBSyxJQUFJLFFBQVEsQ0FBQyxTQUFTLE1BQU0sQ0FBQztJQUNuRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGtCQUFrQixDQUFDLE1BQTRCO1FBQ3JELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sWUFBWSxDQUFDLENBQUMsU0FBUyxlQUFlLENBQUMsQ0FBQyxPQUFPLE1BQU0sQ0FBQyxDQUFDO1FBQ3BHLE9BQU87WUFDTCxtQkFBbUI7WUFDbkIsNEJBQTRCO1lBQzVCLEdBQUcsS0FBSztZQUNSLE1BQU07WUFDTiw2REFBNkQ7WUFDN0QsWUFBWTtZQUNaLFFBQVE7WUFDUixNQUFNO1lBQ04sb0NBQW9DLElBQUksQ0FBQyxvQkFBb0IsR0FBRztZQUNoRSx5Q0FBeUM7WUFDekMsMkNBQTJDO1lBQzNDLHdGQUF3RjtTQUN6RixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNmLENBQUM7SUFFRCw0REFBNEQ7SUFDcEQsZ0JBQWdCLENBQUMsR0FBcUIsRUFBRSxLQUFhO1FBQzNELE9BQU87WUFDTCxtQkFBbUI7WUFDbkIsMkNBQTJDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLDJDQUEyQztZQUN0SCwrRUFBK0U7WUFDL0UsNEVBQTRFO1lBQzVFLDBEQUEwRDtZQUMxRCxvQ0FBb0M7WUFDcEMseUJBQXlCO1lBQ3pCLHVDQUF1QztZQUN2Qyx5QkFBeUI7WUFDekIsd0ZBQXdGO1lBQ3hGLDRDQUE0QztZQUM1QywyQ0FBMkM7WUFDM0MsMkNBQTJDO1lBQzNDLGlCQUFpQixLQUFLLG1FQUFtRTtTQUMxRixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNmLENBQUM7SUFFRCw2RUFBNkU7SUFDckUsa0JBQWtCLENBQUMsS0FBYTtRQUN0QyxPQUFPO1lBQ0wsbUJBQW1CO1lBQ25CLGdCQUFnQjtZQUNoQixvQ0FBb0M7WUFDcEMscURBQXFEO1lBQ3JELHlDQUF5QztZQUN6QyxxREFBcUQ7WUFDckQsZ0RBQWdEO1lBQ2hELHFCQUFxQjtZQUNyQixjQUFjO1lBQ2QsZUFBZSxLQUFLLDhDQUE4QztZQUNsRSxjQUFjO1lBQ2QsVUFBVTtZQUNWLHVCQUF1QjtZQUN2Qix3QkFBd0IsS0FBSyxvRUFBb0U7WUFDakcsY0FBYztZQUNkLFVBQVU7WUFDVixRQUFRO1lBQ1IsMEJBQTBCO1lBQzFCLFlBQVk7WUFDWixNQUFNO1NBQ1AsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDZixDQUFDOztBQXpOSCxrREEwTkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIGdpdGh1YiB9IGZyb20gJ3Byb2plbic7XG5pbXBvcnQgeyBHaXRIdWJQcm9qZWN0IH0gZnJvbSAncHJvamVuL2xpYi9naXRodWInO1xuXG4vKipcbiAqIE9uZSBkZXBsb3kgc3RhZ2U6IGEgZ2l0IGJyYW5jaCwgdGhlIGxvZ2ljYWwgc3RhZ2UgaXQgc2VydmVzLCBhbmQgdGhlIEFXU1xuICogYWNjb3VudCBpdHMgQW1wbGlmeSBhcHBzIGxpdmUgaW4uXG4gKlxuICogQm90aCBzaGFwZXMgc2VlbiBpbiBwcmFjdGljZSBhcmUgZXhwcmVzc2libGU6IHNlcGFyYXRlIGFjY291bnRzIHBlciBzdGFnZVxuICogKGVhY2ggZW50cnkgaGFzIGl0cyBvd24gYGFjY291bnRgKSwgb3IgYSBzaW5nbGUgYWNjb3VudCBzZXJ2aW5nIHNldmVyYWxcbiAqIGJyYW5jaGVzIChldmVyeSBlbnRyeSByZXBlYXRzIHRoZSBzYW1lIGBhY2NvdW50YCwgYW5kIHRoZSBicmFuY2ggYWxvbmVcbiAqIHNlbGVjdHMgd2hpY2ggQW1wbGlmeSBicmFuY2ggaXMgYnVpbHQpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFtcGxpZnlEZXBsb3lTdGFnZSB7XG4gIC8qKiBUaGUgZ2l0IGJyYW5jaCB0aGUgQW1wbGlmeSBhcHBzIGJ1aWxkIGZyb20sIGUuZy4gYG1haW5gIG9yIGBwcm9kdWN0aW9uYC4gKi9cbiAgcmVhZG9ubHkgYnJhbmNoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBsb2dpY2FsIHN0YWdlIHRoaXMgYnJhbmNoIHNlcnZlcywgZS5nLiBgZGV2YCBvciBgcHJvZGAuIFVzZWQgYXMgdGhlXG4gICAqIEdpdEh1YiBlbnZpcm9ubWVudCBzbyBwcm90ZWN0aW9uIHJ1bGVzIGFwcGx5IHBlciBzdGFnZS5cbiAgICovXG4gIHJlYWRvbmx5IHN0YWdlTmFtZTogc3RyaW5nO1xuXG4gIC8qKiBUaGUgQVdTIGFjY291bnQgaG9zdGluZyB0aGlzIHN0YWdlJ3MgQW1wbGlmeSBhcHBzLiAqL1xuICByZWFkb25seSBhY2NvdW50OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT25lIEFtcGxpZnkgSG9zdGluZyBhcHBsaWNhdGlvbiB3aG9zZSBidWlsZHMgQ0kgZHJpdmVzLlxuICpcbiAqIE1pcnJvcnMgYSBgTW9ub3JlcG9BbXBsaWZ5QXBwYCBlbnRyeSBpbiB0aGUgZ2VuZXJhdGVkIGBhbXBsaWZ5LnltbGA7IHRoZVxuICogYGFwcFJvb3RgIHNob3VsZCBtYXRjaCBzbyBhIGJ1aWxkIGlzIHRyaWdnZXJlZCBieSBleGFjdGx5IHRoZSBkaXJlY3RvcnkgaXQgaXNcbiAqIGJ1aWx0IGZyb20uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQW1wbGlmeURlcGxveUFwcCB7XG4gIC8qKlxuICAgKiBTaG9ydCBrZXkgaWRlbnRpZnlpbmcgdGhlIGFwcC4gVXNlZCBpbiB0aGUgYXBwLWlkIFNTTSBwYXJhbWV0ZXIgcGF0aCBhbmQsXG4gICAqIGJ5IGRlZmF1bHQsIGluIHRoZSB3b3JrZmxvdyBuYW1lLlxuICAgKlxuICAgKiBNdXN0IG1hdGNoIHRoZSBrZXkgdGhlIENESyBzaWRlIHJlZ2lzdGVycyB0aGUgYXBwIHVuZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkga2V5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwYWNrYWdlIHBhdGggdGhhdCBpcyB0aGUgQW1wbGlmeSBhcHAgcm9vdCwgZS5nLiBgcGFja2FnZXMvZnJvbnRlbmRgLlxuICAgKiBgPGFwcFJvb3Q+LyoqYCBiZWNvbWVzIGEgcHVzaCB0cmlnZ2VyIHBhdGguXG4gICAqL1xuICByZWFkb25seSBhcHBSb290OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEV4dHJhIHBhdGggZ2xvYnMgdGhhdCBhZmZlY3QgdGhpcyBhcHAncyBidWlsZCBvdXRwdXQuXG4gICAqXG4gICAqIFNldCB0aGlzIGZvciB3b3Jrc3BhY2UgcGFja2FnZXMgdGhlIGFwcCBjb25zdW1lcyB2aWEgYHdvcmtzcGFjZToqYCBhbmQgdGhhdFxuICAgKiB0aGUgYnVpbGQgc3BlYyBwcmUtYnVpbGRzIOKAlCBhIHNoYXJlZCBBUEkgcGFja2FnZSwgc2F5LiBXaXRob3V0IHRoZW0gYSBjaGFuZ2VcbiAgICogdG8gc2hhcmVkIHR5cGVzIHdvdWxkIG5vdCByZWJ1aWxkIHRoZSBhcHAgYW5kIGl0IHdvdWxkIHNoaXAgc3RhbGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRlbmN5UGF0aHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogSHVtYW4tcmVhZGFibGUgbmFtZSB1c2VkIGluIHN0ZXAgbmFtZXMgYW5kIGxvZyBsaW5lcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgYGtleWBcbiAgICovXG4gIHJlYWRvbmx5IGxhYmVsPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZ2VuZXJhdGVkIHdvcmtmbG93IG5hbWUsIHdoaWNoIGlzIGFsc28gaXRzIGAueW1sYCBmaWxlIG5hbWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYDxrZXk+LWRlcGxveWBcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93TmFtZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHaXRIdWJBbXBsaWZ5RGVwbG95T3B0aW9ucyB7XG4gIC8qKiBUaGUgQW1wbGlmeSBhcHBzIHRvIGdlbmVyYXRlIGRlcGxveSB3b3JrZmxvd3MgZm9yLiBBdCBsZWFzdCBvbmUuICovXG4gIHJlYWRvbmx5IGFwcHM6IEFtcGxpZnlEZXBsb3lBcHBbXTtcblxuICAvKiogVGhlIGJyYW5jaGVzIHRoYXQgZGVwbG95LCBhbmQgdGhlIGFjY291bnQgZWFjaCBvbmUgZGVwbG95cyBpbnRvLiBBdCBsZWFzdCBvbmUuICovXG4gIHJlYWRvbmx5IHN0YWdlczogQW1wbGlmeURlcGxveVN0YWdlW107XG5cbiAgLyoqXG4gICAqIFRoZSBHaXRIdWIgT0lEQyBkZXBsb3ltZW50IHJvbGUgZXZlcnkgd29ya2Zsb3cgYXNzdW1lcyBmaXJzdCwgdHlwaWNhbGx5IGluXG4gICAqIGEgbWFuYWdlbWVudCBhY2NvdW50LiBUaGUgcGVyLXN0YWdlIGJ1aWxkLXRyaWdnZXIgcm9sZSBpcyByZWFjaGVkIGZyb20gaXRcbiAgICogYnkgcm9sZSBjaGFpbmluZywgc28gaXQgbXVzdCBiZSBhbGxvd2VkIHRvIGBzdHM6QXNzdW1lUm9sZWAgb24gdGhhdCByb2xlIOKAlFxuICAgKiBhbiBJQU0gZ3JhbnQgdGhhdCBsaXZlcyBvdXRzaWRlIHRoZSBnZW5lcmF0ZWQgY29kZS5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveW1lbnRSb2xlQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHBlci1hY2NvdW50IElBTSByb2xlIENJIGNoYWlucyBpbnRvIHRvIHN0YXJ0IGJ1aWxkcy5cbiAgICpcbiAgICogVGhlIHNhbWUgbmFtZSBpcyBleHBlY3RlZCBpbiBldmVyeSBzdGFnZSBhY2NvdW50LCBzbyB0aGUgd29ya2Zsb3cgY2FuIGJ1aWxkXG4gICAqIHRoZSBBUk4gZnJvbSB0aGUgYWNjb3VudCBpZCBhbG9uZS4gVGhlIENESyBzaWRlIG11c3QgY3JlYXRlIGEgcm9sZSB3aXRoXG4gICAqIGV4YWN0bHkgdGhpcyBuYW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGA8cHJvamVjdCBuYW1lPi1hbXBsaWZ5LWJ1aWxkLXRyaWdnZXJgXG4gICAqL1xuICByZWFkb25seSBidWlsZFRyaWdnZXJSb2xlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogUHJlZml4IG9mIHRoZSBTU00gcGFyYW1ldGVyIHBhdGggaG9sZGluZyBlYWNoIGFwcCdzIEFtcGxpZnkgYXBwIGlkLiBUaGVcbiAgICogZnVsbCBwYXRoIGlzIGA8cHJlZml4Pi88YXBwIGtleT4vYXBwLWlkYC5cbiAgICpcbiAgICogUmVhZGluZyB0aGUgYXBwIGlkIGF0IHJ1biB0aW1lIG1lYW5zIENJIG5ldmVyIGhhcmRjb2RlcyBhbiBpZCB0aGF0IGNoYW5nZXNcbiAgICogd2hlbmV2ZXIgYW4gYXBwIGlzIHJlcGxhY2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGAvPHByb2plY3QgbmFtZT4vYW1wbGlmeWBcbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlclByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFXUyByZWdpb24gdGhlIEFtcGxpZnkgYXBwcyBsaXZlIGluLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnZXUtY2VudHJhbC0xJ1xuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBQYXRocyB0aGF0IGNoYW5nZSB3aGF0ICpldmVyeSogQW1wbGlmeSBidWlsZCBwcm9kdWNlcywgYWRkZWQgdG8gZWFjaCBhcHAnc1xuICAgKiBvd24gcGF0aHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIEFtcGxpZnkgYnVpbGQgc3BlYywgdGhlIGxvY2tmaWxlIGFuZCB0aGUgd29ya3NwYWNlIGZpbGVcbiAgICovXG4gIHJlYWRvbmx5IHNoYXJlZEJ1aWxkUGF0aHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIHJ1bm5lciB0YWdzIHVzZWQgdG8gc2VsZWN0IHRoZSBydW5uZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IFsndWJ1bnR1LWxhdGVzdCddXG4gICAqL1xuICByZWFkb25seSBydW5uZXJUYWdzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgZm9yIGEgZGVwbG95IGpvYiwgYm91bmRpbmcgYSBodW5nIEFtcGxpZnkgYnVpbGQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDQ1XG4gICAqL1xuICByZWFkb25seSB0aW1lb3V0TWludXRlcz86IG51bWJlcjtcbn1cblxuLyoqIFBhdGhzIHRoYXQgaW52YWxpZGF0ZSBldmVyeSBhcHAncyBidWlsZCBvdXRwdXQuICovXG5jb25zdCBERUZBVUxUX1NIQVJFRF9CVUlMRF9QQVRIUyA9IFtcbiAgJ2FtcGxpZnkueW1sJyxcbiAgJ3BucG0tbG9jay55YW1sJyxcbiAgJ3BucG0td29ya3NwYWNlLnlhbWwnLFxuXTtcblxuLyoqXG4gKiBBZGRzIG9uZSBwYXRoLXNjb3BlZCBkZXBsb3kgd29ya2Zsb3cgcGVyIEFtcGxpZnkgSG9zdGluZyBhcHAuXG4gKlxuICogQW1wbGlmeSdzIG93biBhdXRvLWJ1aWxkIGZpcmVzIG9uIGV2ZXJ5IHB1c2ggdG8gYSB0cmFja2VkIGJyYW5jaC4gSW4gYVxuICogbW9ub3JlcG8gdGhhdCBtZWFucyBldmVyeSBmcm9udGVuZCByZWJ1aWxkcyB3aGVuZXZlciBhbnl0aGluZyBjaGFuZ2VzIOKAlCB0aGVcbiAqIG1hcmtldGluZyBzaXRlIHJlYnVpbGRpbmcgZm9yIGEgYmFja2VuZC1vbmx5IGNvbW1pdCBhbmQgdmljZSB2ZXJzYSwgb25jZSBwZXJcbiAqIHRyYWNrZWQgYnJhbmNoLiBBbXBsaWZ5IGJpbGxzIGJ1aWxkIG1pbnV0ZXMsIHNvIG1vc3Qgb2YgdGhvc2UgYXJlIHdhc3RlLlxuICpcbiAqIEFtcGxpZnkncyBuYXRpdmUgYW5zd2VyLCBgQU1QTElGWV9ESUZGX0RFUExPWWAsIGRpZmZzIGV4YWN0bHkgb25lIGRpcmVjdG9yeVxuICogKGBBTVBMSUZZX01PTk9SRVBPX0FQUF9ST09UYCwgb3ZlcnJpZGFibGUgdmlhIGBBTVBMSUZZX0RJRkZfREVQTE9ZX1JPT1RgIOKAlFxuICogc3RpbGwgYSBzaW5nbGUgcGF0aCkuIFRoYXQgaXMgZW5vdWdoIGZvciBhIHNlbGYtY29udGFpbmVkIGFwcCBidXQgbm90IGZvciBvbmVcbiAqIHRoYXQgYWxzbyBkZXBlbmRzIG9uIGEgc2hhcmVkIHdvcmtzcGFjZSBwYWNrYWdlOiBhIG9uZS1kaXJlY3RvcnkgZGlmZiB3b3VsZFxuICogc2hpcCBhIHN0YWxlIGZyb250ZW5kIHdoZW5ldmVyIHRoZSBzaGFyZWQgdHlwZXMgY2hhbmdlZC4gR2l0SHViJ3MgYHBhdGhzOmBcbiAqIGZpbHRlcnMgYWNjZXB0IG11bHRpcGxlIGdsb2JzLCBzbyBidWlsZHMgbW92ZSB0byBDSS5cbiAqXG4gKiBFYWNoIGdlbmVyYXRlZCB3b3JrZmxvdyByZXNvbHZlcyB0aGUgcHVzaGVkIGJyYW5jaCB0byBpdHMgc3RhZ2UgYW5kIGFjY291bnQsXG4gKiBjaGFpbnMgT0lEQyAtPiBkZXBsb3ltZW50IHJvbGUgLT4gYnVpbGQtdHJpZ2dlciByb2xlLCByZWFkcyB0aGUgYXBwIGlkIGZyb21cbiAqIFNTTSwgc3RhcnRzIGEgYFJFTEVBU0VgIGpvYiBhbmQgcG9sbHMgdW50aWwgaXQgcmVhY2hlcyBhIHRlcm1pbmFsIHN0YXRlIOKAlCBzb1xuICogYSBmYWlsZWQgQW1wbGlmeSBidWlsZCBmYWlscyB0aGUgd29ya2Zsb3cgaW5zdGVhZCBvZiBwYXNzaW5nIHNpbGVudGx5LlxuICpcbiAqIFRoaXMgY29tcG9uZW50IGdlbmVyYXRlcyB0aGUgQ0kgaGFsZiBvbmx5LiBUaGUgaW5mcmFzdHJ1Y3R1cmUgaGFsZiBiZWxvbmdzIGluXG4gKiB0aGUgcHJvamVjdCdzIG93biBDREsgYXBwLCB3aGljaCBtdXN0OlxuICpcbiAqICAgMS4gc2V0IGBhdXRvQnVpbGQ6IGZhbHNlYCBvbiBldmVyeSBicmFuY2ggdGhlc2Ugd29ya2Zsb3dzIGJ1aWxkLFxuICogICAyLiBwdWJsaXNoIGVhY2ggYXBwJ3MgaWQgdG8gYDxwYXJhbWV0ZXJQcmVmaXg+LzxrZXk+L2FwcC1pZGAsIGFuZFxuICogICAzLiBjcmVhdGUgYSByb2xlIG5hbWVkIGBidWlsZFRyaWdnZXJSb2xlTmFtZWAgaW4gZWFjaCBzdGFnZSBhY2NvdW50LFxuICogICAgICB0cnVzdGVkIGJ5IGBkZXBsb3ltZW50Um9sZUFybmAgYW5kIGdyYW50aW5nIGBhbXBsaWZ5OlN0YXJ0Sm9iYCArXG4gKiAgICAgIGBhbXBsaWZ5OkdldEpvYmAgb24gdGhlIHRyYWNrZWQgYnJhbmNoIEFSTnMgb25seS5cbiAqXG4gKiBVc2UgYGJ1aWxkVHJpZ2dlclJvbGVOYW1lYCBhbmQgYGFwcElkUGFyYW1ldGVyTmFtZSgpYCBmcm9tIHRoZSBwcm9qZW5yYyB0b1xuICoga2VlcCB0aG9zZSBuYW1lcyBpbiBzdGVwOyBhIG1pc21hdGNoIGZhaWxzIHRoZSB3b3JrZmxvdyBsb3VkbHkgYXQgdGhlXG4gKiBhc3N1bWUtcm9sZSBvciBwYXJhbWV0ZXItcmVhZCBzdGVwIHJhdGhlciB0aGFuIHNraXBwaW5nIGEgZGVwbG95LlxuICovXG5leHBvcnQgY2xhc3MgR2l0SHViQW1wbGlmeURlcGxveSBleHRlbmRzIENvbXBvbmVudCB7XG4gIC8qKiBUaGUgZ2VuZXJhdGVkIGRlcGxveSB3b3JrZmxvd3MsIG9uZSBwZXIgYXBwLiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3dzOiBnaXRodWIuR2l0aHViV29ya2Zsb3dbXSA9IFtdO1xuXG4gIC8qKiBOYW1lIG9mIHRoZSBJQU0gcm9sZSBDSSBjaGFpbnMgaW50bywgaW4gZXZlcnkgc3RhZ2UgYWNjb3VudC4gKi9cbiAgcHVibGljIHJlYWRvbmx5IGJ1aWxkVHJpZ2dlclJvbGVOYW1lOiBzdHJpbmc7XG5cbiAgLyoqIFByZWZpeCBvZiB0aGUgU1NNIHBhcmFtZXRlciBwYXRoIGhvbGRpbmcgZWFjaCBhcHAncyBBbXBsaWZ5IGFwcCBpZC4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHBhcmFtZXRlclByZWZpeDogc3RyaW5nO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IEdpdEh1YlByb2plY3QsIG9wdGlvbnM6IEdpdEh1YkFtcGxpZnlEZXBsb3lPcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUpO1xuXG4gICAgaWYgKCFzY29wZS5naXRodWIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignR2l0SHViQW1wbGlmeURlcGxveSByZXF1aXJlcyBhIHByb2plY3Qgd2l0aCBHaXRIdWIgZW5hYmxlZCcpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5hcHBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdHaXRIdWJBbXBsaWZ5RGVwbG95IHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBhcHAnKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuc3RhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdHaXRIdWJBbXBsaWZ5RGVwbG95IHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBzdGFnZScpO1xuICAgIH1cblxuICAgIGNvbnN0IGtleXMgPSBvcHRpb25zLmFwcHMubWFwKChhcHApID0+IGFwcC5rZXkpO1xuICAgIGNvbnN0IGR1cGxpY2F0ZUtleSA9IGtleXMuZmluZCgoa2V5LCBpbmRleCkgPT4ga2V5cy5pbmRleE9mKGtleSkgIT09IGluZGV4KTtcbiAgICBpZiAoZHVwbGljYXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEdpdEh1YkFtcGxpZnlEZXBsb3kgYXBwIGtleXMgbXVzdCBiZSB1bmlxdWUsIGdvdCAnJHtkdXBsaWNhdGVLZXl9JyB0d2ljZWApO1xuICAgIH1cblxuICAgIGNvbnN0IGJyYW5jaGVzID0gb3B0aW9ucy5zdGFnZXMubWFwKChzdGFnZSkgPT4gc3RhZ2UuYnJhbmNoKTtcbiAgICBjb25zdCBkdXBsaWNhdGVCcmFuY2ggPSBicmFuY2hlcy5maW5kKChicmFuY2gsIGluZGV4KSA9PiBicmFuY2hlcy5pbmRleE9mKGJyYW5jaCkgIT09IGluZGV4KTtcbiAgICBpZiAoZHVwbGljYXRlQnJhbmNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEdpdEh1YkFtcGxpZnlEZXBsb3kgc3RhZ2UgYnJhbmNoZXMgbXVzdCBiZSB1bmlxdWUsIGdvdCAnJHtkdXBsaWNhdGVCcmFuY2h9JyB0d2ljZWApO1xuICAgIH1cblxuICAgIHRoaXMuYnVpbGRUcmlnZ2VyUm9sZU5hbWUgPSBvcHRpb25zLmJ1aWxkVHJpZ2dlclJvbGVOYW1lID8/IGAke3Njb3BlLm5hbWV9LWFtcGxpZnktYnVpbGQtdHJpZ2dlcmA7XG4gICAgdGhpcy5wYXJhbWV0ZXJQcmVmaXggPSBvcHRpb25zLnBhcmFtZXRlclByZWZpeCA/PyBgLyR7c2NvcGUubmFtZX0vYW1wbGlmeWA7XG4gICAgdGhpcy5yZWdpb24gPSBvcHRpb25zLnJlZ2lvbiA/PyAnZXUtY2VudHJhbC0xJztcblxuICAgIGNvbnN0IHNoYXJlZEJ1aWxkUGF0aHMgPSBvcHRpb25zLnNoYXJlZEJ1aWxkUGF0aHMgPz8gREVGQVVMVF9TSEFSRURfQlVJTERfUEFUSFM7XG4gICAgY29uc3QgcnVubmVyVGFncyA9IG9wdGlvbnMucnVubmVyVGFncyA/PyBbJ3VidW50dS1sYXRlc3QnXTtcbiAgICBjb25zdCB0aW1lb3V0TWludXRlcyA9IG9wdGlvbnMudGltZW91dE1pbnV0ZXMgPz8gNDU7XG5cbiAgICBmb3IgKGNvbnN0IGFwcCBvZiBvcHRpb25zLmFwcHMpIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gYXBwLmxhYmVsID8/IGFwcC5rZXk7XG4gICAgICBjb25zdCB3b3JrZmxvd05hbWUgPSBhcHAud29ya2Zsb3dOYW1lID8/IGAke2FwcC5rZXl9LWRlcGxveWA7XG5cbiAgICAgIGNvbnN0IHdvcmtmbG93ID0gbmV3IGdpdGh1Yi5HaXRodWJXb3JrZmxvdyhzY29wZS5naXRodWIsIHdvcmtmbG93TmFtZSk7XG4gICAgICB3b3JrZmxvdy5vbih7XG4gICAgICAgIHB1c2g6IHtcbiAgICAgICAgICBicmFuY2hlczogb3B0aW9ucy5zdGFnZXMubWFwKChzdGFnZSkgPT4gc3RhZ2UuYnJhbmNoKSxcbiAgICAgICAgICBwYXRoczogW1xuICAgICAgICAgICAgYCR7YXBwLmFwcFJvb3R9LyoqYCxcbiAgICAgICAgICAgIC4uLihhcHAuZGVwZW5kZW5jeVBhdGhzID8/IFtdKSxcbiAgICAgICAgICAgIC4uLnNoYXJlZEJ1aWxkUGF0aHMsXG4gICAgICAgICAgICAvLyBDaGFuZ2luZyB0aGUgd29ya2Zsb3cgaXRzZWxmIHNob3VsZCBwcm92ZSBpdCBzdGlsbCB3b3Jrcy5cbiAgICAgICAgICAgIGAuZ2l0aHViL3dvcmtmbG93cy8ke3dvcmtmbG93TmFtZX0ueW1sYCxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICAvLyBNYW51YWwgcmVkZXBsb3ksIGUuZy4gYWZ0ZXIgYSBidWlsZC1vbmx5IGZhaWx1cmUuXG4gICAgICAgIHdvcmtmbG93RGlzcGF0Y2g6IHt9LFxuICAgICAgfSk7XG5cbiAgICAgIHdvcmtmbG93LmFkZEpvYignZGVwbG95Jywge1xuICAgICAgICBuYW1lOiBgQnVpbGQgYW5kIGRlcGxveSB0aGUgJHtsYWJlbH0gb24gQW1wbGlmeWAsXG4gICAgICAgIHJ1bnNPbjogcnVubmVyVGFncyxcbiAgICAgICAgcGVybWlzc2lvbnM6IHtcbiAgICAgICAgICBjb250ZW50czogZ2l0aHViLndvcmtmbG93cy5Kb2JQZXJtaXNzaW9uLlJFQUQsXG4gICAgICAgICAgaWRUb2tlbjogZ2l0aHViLndvcmtmbG93cy5Kb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgICB9LFxuICAgICAgICBlbnZpcm9ubWVudDogdGhpcy5lbnZpcm9ubWVudEV4cHJlc3Npb24ob3B0aW9ucy5zdGFnZXMpLFxuICAgICAgICBjb25jdXJyZW5jeToge1xuICAgICAgICAgICdncm91cCc6IGAke3dvcmtmbG93TmFtZX0tXFwke3sgZ2l0aHViLnJlZl9uYW1lIH19YCxcbiAgICAgICAgICAvLyBDYW5jZWxsaW5nIHRoZSB3b3JrZmxvdyB3b3VsZCBub3QgY2FuY2VsIHRoZSBBbXBsaWZ5IGpvYiBpdCBzdGFydGVkLFxuICAgICAgICAgIC8vIHNvIGxldCBydW5zIHF1ZXVlIGluc3RlYWQgb2Ygb3JwaGFuaW5nIGJ1aWxkcy5cbiAgICAgICAgICAnY2FuY2VsLWluLXByb2dyZXNzJzogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIHRpbWVvdXRNaW51dGVzLFxuICAgICAgICBzdGVwczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdSZXNvbHZlIHN0YWdlJyxcbiAgICAgICAgICAgIGlkOiAnc3RhZ2UnLFxuICAgICAgICAgICAgcnVuOiB0aGlzLnJlc29sdmVTdGFnZVNjcmlwdChvcHRpb25zLnN0YWdlcyksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnQVdTIGNyZWRlbnRpYWxzIOKAlCBkZXBsb3ltZW50IHJvbGUnLFxuICAgICAgICAgICAgaWQ6ICdhd3NfY3JlZGVudGlhbHNfZGVwbG95bWVudF9yb2xlJyxcbiAgICAgICAgICAgIHVzZXM6ICdhd3MtYWN0aW9ucy9jb25maWd1cmUtYXdzLWNyZWRlbnRpYWxzQHY1JyxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogb3B0aW9ucy5kZXBsb3ltZW50Um9sZUFybixcbiAgICAgICAgICAgICAgJ3JvbGUtc2Vzc2lvbi1uYW1lJzogJ0dpdEh1YkFjdGlvbicsXG4gICAgICAgICAgICAgICdhd3MtcmVnaW9uJzogdGhpcy5yZWdpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0FXUyBjcmVkZW50aWFscyDigJQgQW1wbGlmeSBidWlsZCB0cmlnZ2VyJyxcbiAgICAgICAgICAgIGlkOiAnYXdzX2NyZWRlbnRpYWxzX2FtcGxpZnlfYnVpbGRfdHJpZ2dlcicsXG4gICAgICAgICAgICB1c2VzOiAnYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0B2NScsXG4gICAgICAgICAgICB3aXRoOiB7XG4gICAgICAgICAgICAgICdyb2xlLXRvLWFzc3VtZSc6ICcke3sgc3RlcHMuc3RhZ2Uub3V0cHV0cy5yb2xlX2FybiB9fScsXG4gICAgICAgICAgICAgICdyb2xlLXNlc3Npb24tbmFtZSc6ICdBbXBsaWZ5QnVpbGRUcmlnZ2VyJyxcbiAgICAgICAgICAgICAgJ2F3cy1yZWdpb24nOiB0aGlzLnJlZ2lvbixcbiAgICAgICAgICAgICAgLy8gQ2hhaW4gZnJvbSB0aGUgZGVwbG95bWVudCByb2xlIHJhdGhlciB0aGFuIHJlLXVzaW5nIHRoZSBPSURDXG4gICAgICAgICAgICAgIC8vIHRva2VuLCBzbyBubyBpZGVudGl0eSBwcm92aWRlciBpcyBuZWVkZWQgaW4gdGhlIHN0YWdlIGFjY291bnQuXG4gICAgICAgICAgICAgICdyb2xlLWNoYWluaW5nJzogdHJ1ZSxcbiAgICAgICAgICAgICAgLy8gVGhlIGFjdGlvbiB0YWdzIHNlc3Npb25zIGJ5IGRlZmF1bHQsIHdoaWNoIHR1cm5zIHRoZSBjaGFpbmVkXG4gICAgICAgICAgICAgIC8vIGNhbGwgaW50byBBc3N1bWVSb2xlICsgVGFnU2Vzc2lvbi4gVGhlIHRydXN0IHBvbGljeSBncmFudHNcbiAgICAgICAgICAgICAgLy8gQXNzdW1lUm9sZSBvbmx5LCBzbyB0YWdnaW5nIGZhaWxzIHRoZSBzdGVwOyB0aGUgc2Vzc2lvbiBpc1xuICAgICAgICAgICAgICAvLyBhbHJlYWR5IHRhZ2dlZCBieSB0aGUgZmlyc3QgYXNzdW1lIGFueXdheS5cbiAgICAgICAgICAgICAgJ3JvbGUtc2tpcC1zZXNzaW9uLXRhZ2dpbmcnOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IGBTdGFydCAke2xhYmVsfSBidWlsZGAsXG4gICAgICAgICAgICBpZDogJ3N0YXJ0JyxcbiAgICAgICAgICAgIHJ1bjogdGhpcy5zdGFydEJ1aWxkU2NyaXB0KGFwcCwgbGFiZWwpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1dhaXQgZm9yIGJ1aWxkIHRvIGZpbmlzaCcsXG4gICAgICAgICAgICBpZDogJ3dhaXRfZm9yX2J1aWxkX3RvX2ZpbmlzaCcsXG4gICAgICAgICAgICBydW46IHRoaXMud2FpdEZvckJ1aWxkU2NyaXB0KGxhYmVsKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMud29ya2Zsb3dzLnB1c2god29ya2Zsb3cpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgU1NNIHBhcmFtZXRlciBwYXRoIGhvbGRpbmcgYW4gYXBwJ3MgQW1wbGlmeSBhcHAgaWQuIFRoZSBDREsgc2lkZSBtdXN0XG4gICAqIHB1Ymxpc2ggdGhlIGlkIHVuZGVyIGV4YWN0bHkgdGhpcyBuYW1lLlxuICAgKi9cbiAgcHVibGljIGFwcElkUGFyYW1ldGVyTmFtZShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMucGFyYW1ldGVyUHJlZml4fS8ke2tleX0vYXBwLWlkYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgam9iLWxldmVsIGBlbnZpcm9ubWVudDpgIGV4cHJlc3Npb24gbWFwcGluZyBicmFuY2ggdG8gc3RhZ2UsIHNvIGVhY2hcbiAgICogc3RhZ2Uga2VlcHMgd2hhdGV2ZXIgR2l0SHViIGVudmlyb25tZW50IHByb3RlY3Rpb24gcnVsZXMgaXQgaGFzLiBUaGUgZmlyc3RcbiAgICogc3RhZ2UgaXMgdGhlIGZhbGxiYWNrOyBldmVyeSBsYXRlciBzdGFnZSBnZXRzIGFuIGV4cGxpY2l0IGJyYW5jaCB0ZXN0LlxuICAgKi9cbiAgcHJpdmF0ZSBlbnZpcm9ubWVudEV4cHJlc3Npb24oc3RhZ2VzOiBBbXBsaWZ5RGVwbG95U3RhZ2VbXSk6IHN0cmluZyB7XG4gICAgY29uc3QgW2ZhbGxiYWNrLCAuLi5yZXN0XSA9IHN0YWdlcztcbiAgICBjb25zdCB0ZXN0cyA9IHJlc3QubWFwKChzKSA9PiBgZ2l0aHViLnJlZl9uYW1lID09ICcke3MuYnJhbmNofScgJiYgJyR7cy5zdGFnZU5hbWV9JyB8fCBgKS5qb2luKCcnKTtcbiAgICByZXR1cm4gYFxcJHt7ICR7dGVzdHN9JyR7ZmFsbGJhY2suc3RhZ2VOYW1lfScgfX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEJhc2ggbWFwcGluZyB0aGUgcHVzaGVkIGJyYW5jaCB0byBpdHMgc3RhZ2UgYW5kIGJ1aWxkLXRyaWdnZXIgcm9sZSBBUk4sIHNvXG4gICAqIGFjY291bnQgaWRzIGxpdmUgb25seSBpbiB0aGUgcHJvamVucmMuIEEgYnJhbmNoIHRoYXQgaXMgbm90IGEgZGVwbG95IGJyYW5jaFxuICAgKiBpcyBhbiBlcnJvciByYXRoZXIgdGhhbiBhIHNpbGVudCBuby1vcC5cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZVN0YWdlU2NyaXB0KHN0YWdlczogQW1wbGlmeURlcGxveVN0YWdlW10pOiBzdHJpbmcge1xuICAgIGNvbnN0IGNhc2VzID0gc3RhZ2VzLm1hcCgocykgPT4gYCAgJHtzLmJyYW5jaH0pIHN0YWdlPScke3Muc3RhZ2VOYW1lfSc7IGFjY291bnQ9JyR7cy5hY2NvdW50fScgOztgKTtcbiAgICByZXR1cm4gW1xuICAgICAgJ3NldCAtZXVvIHBpcGVmYWlsJyxcbiAgICAgICdjYXNlIFwiJEdJVEhVQl9SRUZfTkFNRVwiIGluJyxcbiAgICAgIC4uLmNhc2VzLFxuICAgICAgJyAgKiknLFxuICAgICAgJyAgICBlY2hvIFwiOjplcnJvcjo6JEdJVEhVQl9SRUZfTkFNRSBpcyBub3QgYSBkZXBsb3kgYnJhbmNoXCInLFxuICAgICAgJyAgICBleGl0IDEnLFxuICAgICAgJyAgICA7OycsXG4gICAgICAnZXNhYycsXG4gICAgICBgcm9sZT1cImFybjphd3M6aWFtOjokYWNjb3VudDpyb2xlLyR7dGhpcy5idWlsZFRyaWdnZXJSb2xlTmFtZX1cImAsXG4gICAgICAnZWNobyBcInN0YWdlPSRzdGFnZVwiID4+IFwiJEdJVEhVQl9PVVRQVVRcIicsXG4gICAgICAnZWNobyBcInJvbGVfYXJuPSRyb2xlXCIgPj4gXCIkR0lUSFVCX09VVFBVVFwiJyxcbiAgICAgICdlY2hvIFwiRGVwbG95aW5nICRHSVRIVUJfUkVGX05BTUUgdG8gc3RhZ2UgJHN0YWdlICgkYWNjb3VudClcIiA+PiBcIiRHSVRIVUJfU1RFUF9TVU1NQVJZXCInLFxuICAgIF0uam9pbignXFxuJyk7XG4gIH1cblxuICAvKiogUmVhZHMgdGhlIGFwcCBpZCBmcm9tIFNTTSBhbmQgc3RhcnRzIGEgUkVMRUFTRSBidWlsZC4gKi9cbiAgcHJpdmF0ZSBzdGFydEJ1aWxkU2NyaXB0KGFwcDogQW1wbGlmeURlcGxveUFwcCwgbGFiZWw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFtcbiAgICAgICdzZXQgLWV1byBwaXBlZmFpbCcsXG4gICAgICBgYXBwX2lkPVwiJChhd3Mgc3NtIGdldC1wYXJhbWV0ZXIgLS1uYW1lICcke3RoaXMuYXBwSWRQYXJhbWV0ZXJOYW1lKGFwcC5rZXkpfScgLS1xdWVyeSBQYXJhbWV0ZXIuVmFsdWUgLS1vdXRwdXQgdGV4dClcImAsXG4gICAgICAnIyBSRUxFQVNFIGJ1aWxkcyB0aGUgY3VycmVudCB0aXAgb2YgdGhlIGJyYW5jaC4gVGhhdCBpcyBub3JtYWxseSAkR0lUSFVCX1NIQTsnLFxuICAgICAgJyMgaWYgdHdvIHB1c2hlcyByYWNlLCB0aGUgdGlwIHdpbnMgYW5kIHRoZSBlYXJsaWVyIHJ1biBpcyByZWR1bmRhbnQgcmF0aGVyJyxcbiAgICAgICcjIHRoYW4gd3JvbmcuIFRoZSBqb2IgY29uY3VycmVuY3kgZ3JvdXAga2VlcHMgdGhhdCByYXJlLicsXG4gICAgICAnam9iX2lkPVwiJChhd3MgYW1wbGlmeSBzdGFydC1qb2IgXFxcXCcsXG4gICAgICAnICAtLWFwcC1pZCBcIiRhcHBfaWRcIiBcXFxcJyxcbiAgICAgICcgIC0tYnJhbmNoLW5hbWUgXCIkR0lUSFVCX1JFRl9OQU1FXCIgXFxcXCcsXG4gICAgICAnICAtLWpvYi10eXBlIFJFTEVBU0UgXFxcXCcsXG4gICAgICAnICAtLWpvYi1yZWFzb24gXCJHaXRIdWIgQWN0aW9ucyAkR0lUSFVCX1dPUktGTE9XIHJ1biAkR0lUSFVCX1JVTl9JRCBmb3IgJEdJVEhVQl9TSEFcIiBcXFxcJyxcbiAgICAgICcgIC0tcXVlcnkgam9iU3VtbWFyeS5qb2JJZCAtLW91dHB1dCB0ZXh0KVwiJyxcbiAgICAgICdlY2hvIFwiYXBwX2lkPSRhcHBfaWRcIiA+PiBcIiRHSVRIVUJfT1VUUFVUXCInLFxuICAgICAgJ2VjaG8gXCJqb2JfaWQ9JGpvYl9pZFwiID4+IFwiJEdJVEhVQl9PVVRQVVRcIicsXG4gICAgICBgZWNobyBcIlN0YXJ0ZWQgJHtsYWJlbH0gQW1wbGlmeSBqb2IgXFwkam9iX2lkIG9uIGFwcCBcXCRhcHBfaWRcIiA+PiBcIlxcJEdJVEhVQl9TVEVQX1NVTU1BUllcImAsXG4gICAgXS5qb2luKCdcXG4nKTtcbiAgfVxuXG4gIC8qKiBQb2xscyB0aGUgam9iIHVudGlsIGl0IHJlYWNoZXMgYSB0ZXJtaW5hbCBzdGF0ZSwgZmFpbGluZyBvbiBhIGJhZCBvbmUuICovXG4gIHByaXZhdGUgd2FpdEZvckJ1aWxkU2NyaXB0KGxhYmVsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBbXG4gICAgICAnc2V0IC1ldW8gcGlwZWZhaWwnLFxuICAgICAgJ3doaWxlIHRydWU7IGRvJyxcbiAgICAgICcgIHN0YXR1cz1cIiQoYXdzIGFtcGxpZnkgZ2V0LWpvYiBcXFxcJyxcbiAgICAgICcgICAgLS1hcHAtaWQgXCIke3sgc3RlcHMuc3RhcnQub3V0cHV0cy5hcHBfaWQgfX1cIiBcXFxcJyxcbiAgICAgICcgICAgLS1icmFuY2gtbmFtZSBcIiRHSVRIVUJfUkVGX05BTUVcIiBcXFxcJyxcbiAgICAgICcgICAgLS1qb2ItaWQgXCIke3sgc3RlcHMuc3RhcnQub3V0cHV0cy5qb2JfaWQgfX1cIiBcXFxcJyxcbiAgICAgICcgICAgLS1xdWVyeSBqb2Iuc3VtbWFyeS5zdGF0dXMgLS1vdXRwdXQgdGV4dClcIicsXG4gICAgICAnICBjYXNlIFwiJHN0YXR1c1wiIGluJyxcbiAgICAgICcgICAgU1VDQ0VFRCknLFxuICAgICAgYCAgICAgIGVjaG8gXCIke2xhYmVsfSBidWlsZCBzdWNjZWVkZWRcIiA+PiBcIlxcJEdJVEhVQl9TVEVQX1NVTU1BUllcImAsXG4gICAgICAnICAgICAgZXhpdCAwJyxcbiAgICAgICcgICAgICA7OycsXG4gICAgICAnICAgIEZBSUxFRHxDQU5DRUxMRUQpJyxcbiAgICAgIGAgICAgICBlY2hvIFwiOjplcnJvcjo6JHtsYWJlbH0gQW1wbGlmeSBqb2IgXFwke3sgc3RlcHMuc3RhcnQub3V0cHV0cy5qb2JfaWQgfX0gZW5kZWQgYXMgXFwkc3RhdHVzXCJgLFxuICAgICAgJyAgICAgIGV4aXQgMScsXG4gICAgICAnICAgICAgOzsnLFxuICAgICAgJyAgZXNhYycsXG4gICAgICAnICBlY2hvIFwic3RhdHVzOiAkc3RhdHVzXCInLFxuICAgICAgJyAgc2xlZXAgMTUnLFxuICAgICAgJ2RvbmUnLFxuICAgIF0uam9pbignXFxuJyk7XG4gIH1cbn1cbiJdfQ==
|
package/lib/components/index.js
CHANGED
|
@@ -14,5 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./amplify-deploy"), exports);
|
|
17
18
|
__exportStar(require("./production-release"), exports);
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbURBQWlDO0FBQ2pDLHVEQUFxQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vYW1wbGlmeS1kZXBsb3knO1xuZXhwb3J0ICogZnJvbSAnLi9wcm9kdWN0aW9uLXJlbGVhc2UnO1xuIl19
|
|
@@ -15,7 +15,7 @@ const projen_1 = require("projen");
|
|
|
15
15
|
* dispatch time.
|
|
16
16
|
*/
|
|
17
17
|
class GitHubProductionRelease extends projen_1.Component {
|
|
18
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.GitHubProductionRelease", version: "0.1.
|
|
18
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.GitHubProductionRelease", version: "0.1.80" };
|
|
19
19
|
/**
|
|
20
20
|
* Resolves the branch that is promoted — the project's default release branch.
|
|
21
21
|
*
|
package/lib/projects/cdk-app.js
CHANGED
|
@@ -9,7 +9,7 @@ const projen_1 = require("projen");
|
|
|
9
9
|
* @pjid taimos-cdk-app
|
|
10
10
|
*/
|
|
11
11
|
class TaimosCdkApp extends projen_1.awscdk.AwsCdkTypeScriptApp {
|
|
12
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.TaimosCdkApp", version: "0.1.
|
|
12
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.TaimosCdkApp", version: "0.1.80" };
|
|
13
13
|
constructor(options) {
|
|
14
14
|
super({
|
|
15
15
|
authorEmail: 'info@taimos.de',
|
|
@@ -9,7 +9,7 @@ const projen_1 = require("projen");
|
|
|
9
9
|
* @pjid taimos-awscdk-construct
|
|
10
10
|
*/
|
|
11
11
|
class TaimosCdkConstructLibrary extends projen_1.awscdk.AwsCdkConstructLibrary {
|
|
12
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.TaimosCdkConstructLibrary", version: "0.1.
|
|
12
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@taimos/projen.TaimosCdkConstructLibrary", version: "0.1.80" };
|
|
13
13
|
constructor(options) {
|
|
14
14
|
super({
|
|
15
15
|
authorOrganization: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { github, typescript, YamlFile } from 'projen';
|
|
2
2
|
import { GitHubAssignApprover } from 'projen-pipelines';
|
|
3
|
-
import { GitHubProductionRelease, GitHubProductionReleaseOptions } from '../components';
|
|
3
|
+
import { GitHubAmplifyDeploy, GitHubAmplifyDeployOptions, GitHubProductionRelease, GitHubProductionReleaseOptions } from '../components';
|
|
4
4
|
/**
|
|
5
5
|
* The frontend framework an Amplify Hosting application is built with.
|
|
6
6
|
*
|
|
@@ -211,6 +211,18 @@ export interface MonorepoProjectOptions extends typescript.TypeScriptProjectOpti
|
|
|
211
211
|
* @default - promote `main` to a `production` branch
|
|
212
212
|
*/
|
|
213
213
|
readonly productionReleaseOptions?: GitHubProductionReleaseOptions;
|
|
214
|
+
/**
|
|
215
|
+
* Drive Amplify Hosting builds from GitHub Actions instead of Amplify's own
|
|
216
|
+
* auto-build, so an app only rebuilds when the packages it is built from
|
|
217
|
+
* actually changed (see `GitHubAmplifyDeploy`).
|
|
218
|
+
*
|
|
219
|
+
* Setting this generates one deploy workflow per listed app. The project's
|
|
220
|
+
* CDK app must disable `autoBuild` on the tracked branches and provide the
|
|
221
|
+
* app-id parameters and build-trigger role the workflows expect.
|
|
222
|
+
*
|
|
223
|
+
* @default - Amplify's own auto-build is left in place
|
|
224
|
+
*/
|
|
225
|
+
readonly amplifyDeployOptions?: GitHubAmplifyDeployOptions;
|
|
214
226
|
}
|
|
215
227
|
/**
|
|
216
228
|
* Private PNPM-workspace monorepo root, following Taimos ADR-0002.
|
|
@@ -236,6 +248,8 @@ export declare class MonorepoProject extends typescript.TypeScriptProject {
|
|
|
236
248
|
readonly assignApprover?: GitHubAssignApprover;
|
|
237
249
|
/** The production release workflow, if enabled. */
|
|
238
250
|
readonly productionRelease?: GitHubProductionRelease;
|
|
251
|
+
/** The Amplify deploy workflows, when `amplifyDeployOptions` is set. */
|
|
252
|
+
readonly amplifyDeploy?: GitHubAmplifyDeploy;
|
|
239
253
|
/** The default release branch (promoted by the production release workflow). */
|
|
240
254
|
readonly defaultReleaseBranch: string;
|
|
241
255
|
constructor(options: MonorepoProjectOptions);
|