UNPKG

opinionated-ci-pipeline

Version:

CI/CD on AWS with feature-branch builds, developer-environment deployments, and build status notifications.

182 lines 29.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MainPipeline = void 0; const targets = require("aws-cdk-lib/aws-events-targets"); const constructs_1 = require("constructs"); const customNodejsFunction_1 = require("./customNodejsFunction"); const path = require("path"); const notificationsTopic_1 = require("./notificationsTopic"); const pipelines_1 = require("aws-cdk-lib/pipelines"); const lodash_1 = require("lodash"); const context_1 = require("../util/context"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const appStage_1 = require("./appStage"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); const aws_lambda_1 = require("aws-cdk-lib/aws-lambda"); const aws_codepipeline_1 = require("aws-cdk-lib/aws-codepipeline"); const string_1 = require("../util/string"); const aws_codepipeline_actions_1 = require("aws-cdk-lib/aws-codepipeline-actions"); const checkout_1 = require("../util/checkout"); class MainPipeline extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); const source = pipelines_1.CodePipelineSource.s3(props.sourceBucket, `repository-${props.repository.defaultBranch}.zip`, { trigger: aws_codepipeline_actions_1.S3Trigger.NONE, }); const pipeline = new pipelines_1.CodePipeline(this, 'Pipeline', (0, lodash_1.merge)({ pipelineName: aws_cdk_lib_1.Stack.of(this).stackName, synth: new pipelines_1.ShellStep('Synth', { input: source, installCommands: [ ...checkout_1.checkoutCommands, ...(props.commands.preInstall || []), ...(props.commands.install || []), ], commands: [ ...(props.commands.buildAndTest || []), ...props.commands.synthPipeline, ], primaryOutputDirectory: '../repository/' + (props.cdkOutputDirectory || 'cdk.out'), }), crossAccountKeys: true, synthCodeBuildDefaults: props.codeBuild, }, props.codePipeline)); props.pipeline.forEach(step => { if (this.isWave(step)) { this.addWaveDeployment(pipeline, step, props); } else { this.addEnvironmentDeployment(pipeline, step, props); } }); pipeline.buildPipeline(); this.createPipelineBuildNotifications(pipeline, props.repository, props.repositoryTokenParam, props.sourceBucket); this.failuresTopic = this.createPipelineFailuresTopic(pipeline); } isWave(waveOrEnvironment) { return 'wave' in waveOrEnvironment; } addWaveDeployment(pipeline, step, props) { const wave = pipeline.addWave(step.wave); step.environments.forEach(env => { const environmentDeployment = { ...env, pre: [ ...(step.preEachEnvironment || []), ...(env.pre || []), ], post: [ ...(env.post || []), ...(step.postEachEnvironment || []), ], }; this.addEnvironmentDeployment(wave, environmentDeployment, props, `Wave${(0, string_1.capitalizeFirstLetter)(step.wave)}`, { WAVE_NAME: step.wave }); }); if (step.manualApproval) { wave.addPre(new pipelines_1.ManualApprovalStep(`Wave${(0, string_1.capitalizeFirstLetter)(step.wave)}ManualApproval`)); } if (step.pre && step.pre.length > 0) { wave.addPre(new pipelines_1.CodeBuildStep(`PreWave${(0, string_1.capitalizeFirstLetter)(step.wave)}`, { env: { WAVE_NAME: step.wave }, commands: [ ...checkout_1.checkoutCommands, ...step.pre, ], ...props.codeBuild, rolePolicyStatements: props.codeBuild.rolePolicy, })); } if (step.post && step.post.length > 0) { wave.addPost(new pipelines_1.CodeBuildStep(`PostWave${(0, string_1.capitalizeFirstLetter)(step.wave)}`, { env: { WAVE_NAME: step.wave }, commands: [ ...checkout_1.checkoutCommands, ...step.post, ], ...props.codeBuild, rolePolicyStatements: props.codeBuild.rolePolicy, })); } } addEnvironmentDeployment(parent, step, props, idPrefix = '', envVariables) { const stage = parent.addStage(new appStage_1.AppStage(this, `${idPrefix}DeployEnv${(0, string_1.capitalizeFirstLetter)(step.environment)}`, { envName: step.environment, env: (0, context_1.getEnvironmentConfig)(this, step.environment), stacks: props.stacks, fixPathsMetadata: props.fixPathsMetadata, })); if (step.manualApproval) { stage.addPre(new pipelines_1.ManualApprovalStep(`${idPrefix}${(0, string_1.capitalizeFirstLetter)(step.environment)}ManualApproval`)); } if (step.pre && step.pre.length > 0) { stage.addPre(new pipelines_1.CodeBuildStep(`${idPrefix}PreEnv${(0, string_1.capitalizeFirstLetter)(step.environment)}`, { env: { ...envVariables, ENV_NAME: step.environment, }, commands: [ ...checkout_1.checkoutCommands, ...step.pre, ], ...props.codeBuild, rolePolicyStatements: props.codeBuild.rolePolicy, })); } if (step.post && step.post.length > 0) { stage.addPost(new pipelines_1.CodeBuildStep(`${idPrefix}PostEnv${(0, string_1.capitalizeFirstLetter)(step.environment)}`, { env: { ...envVariables, ENV_NAME: step.environment, }, commands: [ ...checkout_1.checkoutCommands, ...step.post, ], ...props.codeBuild, rolePolicyStatements: props.codeBuild.rolePolicy, })); } } createPipelineFailuresTopic(pipeline) { const failuresTopic = new notificationsTopic_1.NotificationsTopic(this, 'PipelineFailuresTopic', { projectName: (0, context_1.getProjectName)(this), notificationName: 'pipelineFailures', }); pipeline.pipeline.notifyOn('NotifyOnPipelineFailure', failuresTopic.topic, { events: [aws_codepipeline_1.PipelineNotificationEvents.PIPELINE_EXECUTION_FAILED], notificationRuleName: `${aws_cdk_lib_1.Stack.of(this).stackName}-pipelineFailure`, // ensure unique name }); return failuresTopic.topic; } /** * To send CodePipeline build status back to repository: * - trigger Lambda function on CodePipeline state change events, * - in Lambda: * - get CodePipeline execution details to get commit SHA, * - send custom event to EventBridge including the commit SHA, * - use EventBridge to send build status to repository. */ createPipelineBuildNotifications(pipeline, repository, repoTokenParam, sourceBucket) { const pipelineBuildStatusFunction = new customNodejsFunction_1.CustomNodejsFunction(this, 'PipelineBuildStatus', { code: aws_lambda_1.Code.fromAsset(path.join(__dirname, '..', 'lambda', 'pipelineBuildStatus')), environment: { REPOSITORY_HOST: repository.host, REPOSITORY_NAME: repository.name, REPOSITORY_TOKEN_PARAM_NAME: repoTokenParam.parameterName, DEFAULT_BRANCH_NAME: repository.defaultBranch || '', SOURCE_BUCKET_NAME: sourceBucket.bucketName, }, }); repoTokenParam.grantRead(pipelineBuildStatusFunction); sourceBucket.grantRead(pipelineBuildStatusFunction); pipelineBuildStatusFunction.addToRolePolicy(new aws_iam_1.PolicyStatement({ actions: ['codepipeline:GetPipelineExecution'], resources: [`arn:aws:codepipeline:${aws_cdk_lib_1.Aws.REGION}:${aws_cdk_lib_1.Aws.ACCOUNT_ID}:${pipeline.pipeline.pipelineName}`], })); pipeline.pipeline.onStateChange('OnPipelineStateChange', { target: new targets.LambdaFunction(pipelineBuildStatusFunction), }); } } exports.MainPipeline = MainPipeline; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpblBpcGVsaW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvbWFpblBpcGVsaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDBEQUEwRDtBQUMxRCwyQ0FBcUM7QUFFckMsaUVBQTREO0FBQzVELDZCQUE2QjtBQUM3Qiw2REFBd0Q7QUFDeEQscURBRStCO0FBQy9CLG1DQUE2QjtBQUM3Qiw2Q0FBcUU7QUFDckUsNkNBQXVDO0FBQ3ZDLHlDQUFvQztBQUNwQyxpREFBb0Q7QUFDcEQsdURBQTRDO0FBRzVDLG1FQUF3RTtBQUV4RSwyQ0FBcUQ7QUFDckQsbUZBQStEO0FBQy9ELCtDQUFrRDtBQVdsRCxNQUFhLFlBQWEsU0FBUSxzQkFBUztJQUl2QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXdCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxNQUFNLEdBQUcsOEJBQWtCLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsY0FBYyxLQUFLLENBQUMsVUFBVSxDQUFDLGFBQWEsTUFBTSxFQUFFO1lBQ3pHLE9BQU8sRUFBRSxvQ0FBUyxDQUFDLElBQUk7U0FDMUIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxRQUFRLEdBQUcsSUFBSSx3QkFBWSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBQSxjQUFLLEVBQTREO1lBQ2pILFlBQVksRUFBRSxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTO1lBQ3RDLEtBQUssRUFBRSxJQUFJLHFCQUFTLENBQUMsT0FBTyxFQUFFO2dCQUMxQixLQUFLLEVBQUUsTUFBTTtnQkFDYixlQUFlLEVBQUU7b0JBQ2IsR0FBRywyQkFBZ0I7b0JBQ25CLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7b0JBQ3BDLEdBQUcsQ0FBQyxLQUFL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RSxxQkFBcUIsQ0FBQyxDQUFDO1lBQ2pGLFdBQVcsRUFBRTtnQkFDVCxlQUFlLEVBQUUsVUFBVSxDQUFDLElBQUk7Z0JBQ2hDLGVBQWUsRUFBRSxVQUFVLENBQUMsSUFBSTtnQkFDaEMsMkJBQTJCLEVBQUUsY0FBYyxDQUFDLGFBQWE7Z0JBQ3pELG1CQUFtQixFQUFFLFVBQVUsQ0FBQyxhQUFhLElBQUksRUFBRTtnQkFDbkQsa0JBQWtCLEVBQUUsWUFBWSxDQUFDLFVBQVU7YUFDOUM7U0FDSixDQUFDLENBQUM7UUFDSCxjQUFjLENBQUMsU0FBUyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDdEQsWUFBWSxDQUFDLFNBQVMsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBRXBELDJCQUEyQixDQUFDLGVBQWUsQ0FBQyxJQUFJLHlCQUFlLENBQUM7WUFDNUQsT0FBTyxFQUFFLENBQUMsbUNBQW1DLENBQUM7WUFDOUMsU0FBUyxFQUFFLENBQUMsd0JBQXdCLGlCQUFHLENBQUMsTUFBTSxJQUFJLGlCQUFHLENBQUMsVUFBVSxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLENBQUM7U0FDeEcsQ0FBQyxDQUFDLENBQUM7UUFFSixRQUFRLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyx1QkFBdUIsRUFBRTtZQUNyRCxNQUFNLEVBQUUsSUFBSSxPQUFPLENBQUMsY0FBYyxDQUFDLDJCQUEyQixDQUFDO1NBQ2xFLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSjtBQXhNRCxvQ0F3TUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB0YXJnZXRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0cyc7XG5pbXBvcnQge0NvbnN0cnVjdH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQge0FwcGxpY2F0aW9uUHJvcHMsIEVudmlyb25tZW50RGVwbG95bWVudCwgUmVzb2x2ZWRBcHBsaWNhdGlvblByb3BzLCBXYXZlRGVwbG95bWVudH0gZnJvbSAnLi4vYXBwbGljYXRpb25Qcm9wcyc7XG5pbXBvcnQge0N1c3RvbU5vZGVqc0Z1bmN0aW9ufSBmcm9tICcuL2N1c3RvbU5vZGVqc0Z1bmN0aW9uJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQge05vdGlmaWNhdGlvbnNUb3BpY30gZnJvbSAnLi9ub3RpZmljYXRpb25zVG9waWMnO1xuaW1wb3J0IHtcbiAgICBDb2RlQnVpbGRTdGVwLCBDb2RlUGlwZWxpbmUsIENvZGVQaXBlbGluZVByb3BzLCBDb2RlUGlwZWxpbmVTb3VyY2UsIE1hbnVhbEFwcHJvdmFsU3RlcCwgU2hlbGxTdGVwLCBXYXZlLFxufSBmcm9tICdhd3MtY2RrLWxpYi9waXBlbGluZXMnO1xuaW1wb3J0IHttZXJnZX0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7Z2V0RW52aXJvbm1lbnRDb25maWcsIGdldFByb2plY3ROYW1lfSBmcm9tICcuLi91dGlsL2NvbnRleHQnO1xuaW1wb3J0IHtBd3MsIFN0YWNrfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQge0FwcFN0YWdlfSBmcm9tICcuL2FwcFN0YWdlJztcbmltcG9ydCB7UG9saWN5U3RhdGVtZW50fSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7Q29kZX0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQge1RvcGljfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zJztcbmltcG9ydCB7SVN0cmluZ1BhcmFtZXRlcn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNzbSc7XG5pbXBvcnQge1BpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY29kZXBpcGVsaW5lJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQge2NhcGl0YWxpemVGaXJzdExldHRlcn0gZnJvbSAnLi4vdXRpbC9zdHJpbmcnO1xuaW1wb3J0IHtTM1RyaWdnZXJ9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jb2RlcGlwZWxpbmUtYWN0aW9ucyc7XG5pbXBvcnQge2NoZWNrb3V0Q29tbWFuZHN9IGZyb20gJy4uL3V0aWwvY2hlY2tvdXQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE1haW5QaXBlbGluZVByb3BzIGV4dGVuZHMgUGljazxSZXNvbHZlZEFwcGxpY2F0aW9uUHJvcHMsXG4gICAgJ3N0YWNrcycgfCAncmVwb3NpdG9yeScgfCAnY29tbWFuZHMnIHxcbiAgICAncGlwZWxpbmUnIHwgJ2Nka091dHB1dERpcmVjdG9yeScgfCAnY29kZUJ1aWxkJyB8ICdjb2RlUGlwZWxpbmUnIHxcbiAgICAnZml4UGF0aHNNZXRhZGF0YSdcbj4ge1xuICAgIHNvdXJjZUJ1Y2tldDogczMuSUJ1Y2tldDtcbiAgICByZXBvc2l0b3J5VG9rZW5QYXJhbTogSVN0cmluZ1BhcmFtZXRlcjtcbn1cblxuZXhwb3J0IGNsYXNzIE1haW5QaXBlbGluZSBleHRlbmRzIENvbnN0cnVjdCB7XG5cbiAgICByZWFkb25seSBmYWlsdXJlc1RvcGljOiBUb3BpYztcblxuICAgIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBNYWluUGlwZWxpbmVQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IENvZGVQaXBlbGluZVNvdXJjZS5zMyhwcm9wcy5zb3VyY2VCdWNrZXQsIGByZXBvc2l0b3J5LSR7cHJvcHMucmVwb3NpdG9yeS5kZWZhdWx0QnJhbmNofS56aXBgLCB7XG4gICAgICAgICAgICB0cmlnZ2VyOiBTM1RyaWdnZXIuTk9ORSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcGlwZWxpbmUgPSBuZXcgQ29kZVBpcGVsaW5lKHRoaXMsICdQaXBlbGluZScsIG1lcmdlPENvZGVQaXBlbGluZVByb3BzLCBQYXJ0aWFsPENvZGVQaXBlbGluZVByb3BzPiB8IHVuZGVmaW5lZD4oe1xuICAgICAgICAgICAgcGlwZWxpbmVOYW1lOiBTdGFjay5vZih0aGlzKS5zdGFja05hbWUsXG4gICAgICAgICAgICBzeW50aDogbmV3IFNoZWxsU3RlcCgnU3ludGgnLCB7XG4gICAgICAgICAgICAgICAgaW5wdXQ6IHNvdXJjZSxcbiAgICAgICAgICAgICAgICBpbnN0YWxsQ29tbWFuZHM6IFtcbiAgICAgICAgICAgICAgICAgICAgLi4uY2hlY2tvdXRDb21tYW5kcyxcbiAgICAgICAgICAgICAgICAgICAgLi4uKHByb3BzLmNvbW1hbmRzLnByZUluc3RhbGwgfHwgW10pLFxuICAgICAgICAgICAgICAgICAgICAuLi4ocHJvcHMuY29tbWFuZHMuaW5zdGFsbCB8fCBbXSksXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAgICAgICAuLi4ocHJvcHMuY29tbWFuZHMuYnVpbGRBbmRUZXN0IHx8IFtdKSxcbiAgICAgICAgICAgICAgICAgICAgLi4ucHJvcHMuY29tbWFuZHMuc3ludGhQaXBlbGluZSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHByaW1hcnlPdXRwdXREaXJlY3Rvcnk6ICcuLi9yZXBvc2l0b3J5LycgKyAocHJvcHMuY2RrT3V0cHV0RGlyZWN0b3J5IHx8ICdjZGsub3V0JyksXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGNyb3NzQWNjb3VudEtleXM6IHRydWUsXG4gICAgICAgICAgICBzeW50aENvZGVCdWlsZERlZmF1bHRzOiBwcm9wcy5jb2RlQnVpbGQsXG4gICAgICAgIH0sIHByb3BzLmNvZGVQaXBlbGluZSkpO1xuXG4gICAgICAgIHByb3BzLnBpcGVsaW5lLmZvckVhY2goc3RlcCA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1dhdmUoc3RlcCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFdhdmVEZXBsb3ltZW50KHBpcGVsaW5lLCBzdGVwLCBwcm9wcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkRW52aXJvbm1lbnREZXBsb3ltZW50KHBpcGVsaW5lLCBzdGVwLCBwcm9wcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHBpcGVsaW5lLmJ1aWxkUGlwZWxpbmUoKTtcblxuICAgICAgICB0aGlzLmNyZWF0ZVBpcGVsaW5lQnVpbGROb3RpZmljYXRpb25zKHBpcGVsaW5lLCBwcm9wcy5yZXBvc2l0b3J5LCBwcm9wcy5yZXBvc2l0b3J5VG9rZW5QYXJhbSwgcHJvcHMuc291cmNlQnVja2V0KTtcblxuICAgICAgICB0aGlzLmZhaWx1cmVzVG9waWMgPSB0aGlzLmNyZWF0ZVBpcGVsaW5lRmFpbHVyZXNUb3BpYyhwaXBlbGluZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1dhdmUod2F2ZU9yRW52aXJvbm1lbnQ6IFdhdmVEZXBsb3ltZW50IHwgRW52aXJvbm1lbnREZXBsb3ltZW50KTogd2F2ZU9yRW52aXJvbm1lbnQgaXMgV2F2ZURlcGxveW1lbnQge1xuICAgICAgICByZXR1cm4gJ3dhdmUnIGluIHdhdmVPckVudmlyb25tZW50O1xuICAgIH1cblxuICAgIHByaXZhdGUgYWRkV2F2ZURlcGxveW1lbnQocGlwZWxpbmU6IENvZGVQaXBlbGluZSwgc3RlcDogV2F2ZURlcGxveW1lbnQsIHByb3BzOiBNYWluUGlwZWxpbmVQcm9wcykge1xuICAgICAgICBjb25zdCB3YXZlID0gcGlwZWxpbmUuYWRkV2F2ZShzdGVwLndhdmUpO1xuICAgICAgICBzdGVwLmVudmlyb25tZW50cy5mb3JFYWNoKGVudiA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbnZpcm9ubWVudERlcGxveW1lbnQ6IEVudmlyb25tZW50RGVwbG95bWVudCA9IHtcbiAgICAgICAgICAgICAgICAuLi5lbnYsXG4gICAgICAgICAgICAgICAgcHJlOiBbXG4gICAgICAgICAgICAgICAgICAgIC4uLihzdGVwLnByZUVhY2hFbnZpcm9ubWVudCB8fCBbXSksXG4gICAgICAgICAgICAgICAgICAgIC4uLihlbnYucHJlIHx8IFtdKSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHBvc3Q6IFtcbiAgICAgICAgICAgICAgICAgICAgLi4uKGVudi5wb3N0IHx8IFtdKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uKHN0ZXAucG9zdEVhY2hFbnZpcm9ubWVudCB8fCBbXSksXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuYWRkRW52aXJvbm1lbnREZXBsb3ltZW50KHdhdmUsIGVudmlyb25tZW50RGVwbG95bWVudCwgcHJvcHMsXG4gICAgICAgICAgICAgICAgYFdhdmUke2NhcGl0YWxpemVGaXJzdExldHRlcihzdGVwLndhdmUpfWAsIHtXQVZFX05BTUU6IHN0ZXAud2F2ZX0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoc3RlcC5tYW51YWxBcHByb3ZhbCkge1xuICAgICAgICAgICAgd2F2ZS5hZGRQcmUoXG4gICAgICAgICAgICAgICAgbmV3IE1hbnVhbEFwcHJvdmFsU3RlcChcbiAgICAgICAgICAgICAgICAgICAgYFdhdmUke2NhcGl0YWxpemVGaXJzdExldHRlcihzdGVwLndhdmUpfU1hbnVhbEFwcHJvdmFsYCxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdGVwLnByZSAmJiBzdGVwLnByZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB3YXZlLmFkZFByZShuZXcgQ29kZUJ1aWxkU3RlcChgUHJlV2F2ZSR7Y2FwaXRhbGl6ZUZpcnN0TGV0dGVyKHN0ZXAud2F2ZSl9YCwge1xuICAgICAgICAgICAgICAgIGVudjoge1dBVkVfTkFNRTogc3RlcC53YXZlfSxcbiAgICAgICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAgICAgICAuLi5jaGVja291dENvbW1hbmRzLFxuICAgICAgICAgICAgICAgICAgICAuLi5zdGVwLnByZSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIC4uLnByb3BzLmNvZGVCdWlsZCxcbiAgICAgICAgICAgICAgICByb2xlUG9saWN5U3RhdGVtZW50czogcHJvcHMuY29kZUJ1aWxkLnJvbGVQb2xpY3ksXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0ZXAucG9zdCAmJiBzdGVwLnBvc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgd2F2ZS5hZGRQb3N0KG5ldyBDb2RlQnVpbGRTdGVwKGBQb3N0V2F2ZSR7Y2FwaXRhbGl6ZUZpcnN0TGV0dGVyKHN0ZXAud2F2ZSl9YCwge1xuICAgICAgICAgICAgICAgIGVudjoge1dBVkVfTkFNRTogc3RlcC53YXZlfSxcbiAgICAgICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAgICAgICAuLi5jaGVja291dENvbW1hbmRzLFxuICAgICAgICAgICAgICAgICAgICAuLi5zdGVwLnBvc3QsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAuLi5wcm9wcy5jb2RlQnVpbGQsXG4gICAgICAgICAgICAgICAgcm9sZVBvbGljeVN0YXRlbWVudHM6IHByb3BzLmNvZGVCdWlsZC5yb2xlUG9saWN5LFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRFbnZpcm9ubWVudERlcGxveW1lbnQocGFyZW50OiBDb2RlUGlwZWxpbmUgfCBXYXZlLCBzdGVwOiBFbnZpcm9ubWVudERlcGxveW1lbnQsIHByb3BzOiBNYWluUGlwZWxpbmVQcm9wcywgaWRQcmVmaXggPSAnJywgZW52VmFyaWFibGVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPikge1xuICAgICAgICBjb25zdCBzdGFnZSA9IHBhcmVudC5hZGRTdGFnZShuZXcgQXBwU3RhZ2UodGhpcywgYCR7aWRQcmVmaXh9RGVwbG95RW52JHtjYXBpdGFsaXplRmlyc3RMZXR0ZXIoc3RlcC5lbnZpcm9ubWVudCl9YCwge1xuICAgICAgICAgICAgZW52TmFtZTogc3RlcC5lbnZpcm9ubWVudCxcbiAgICAgICAgICAgIGVudjogZ2V0RW52aXJvbm1lbnRDb25maWcodGhpcywgc3RlcC5lbnZpcm9ubWVudCksXG4gICAgICAgICAgICBzdGFja3M6IHByb3BzLnN0YWNrcyxcbiAgICAgICAgICAgIGZpeFBhdGhzTWV0YWRhdGE6IHByb3BzLmZpeFBhdGhzTWV0YWRhdGEsXG4gICAgICAgIH0pKTtcblxuICAgICAgICBpZiAoc3RlcC5tYW51YWxBcHByb3ZhbCkge1xuICAgICAgICAgICAgc3RhZ2UuYWRkUHJlKFxuICAgICAgICAgICAgICAgIG5ldyBNYW51YWxBcHByb3ZhbFN0ZXAoXG4gICAgICAgICAgICAgICAgICAgIGAke2lkUHJlZml4fSR7Y2FwaXRhbGl6ZUZpcnN0TGV0dGVyKHN0ZXAuZW52aXJvbm1lbnQpfU1hbnVhbEFwcHJvdmFsYCxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdGVwLnByZSAmJiBzdGVwLnByZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzdGFnZS5hZGRQcmUobmV3IENvZGVCdWlsZFN0ZXAoYCR7aWRQcmVmaXh9UHJlRW52JHtjYXBpdGFsaXplRmlyc3RMZXR0ZXIoc3RlcC5lbnZpcm9ubWVudCl9YCwge1xuICAgICAgICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgICAgICAgICAuLi5lbnZWYXJpYWJsZXMsXG4gICAgICAgICAgICAgICAgICAgIEVOVl9OQU1FOiBzdGVwLmVudmlyb25tZW50LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY29tbWFuZHM6IFtcbiAgICAgICAgICAgICAgICAgICAgLi4uY2hlY2tvdXRDb21tYW5kcyxcbiAgICAgICAgICAgICAgICAgICAgLi4uc3RlcC5wcmUsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAuLi5wcm9wcy5jb2RlQnVpbGQsXG4gICAgICAgICAgICAgICAgcm9sZVBvbGljeVN0YXRlbWVudHM6IHByb3BzLmNvZGVCdWlsZC5yb2xlUG9saWN5LFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGVwLnBvc3QgJiYgc3RlcC5wb3N0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHN0YWdlLmFkZFBvc3QobmV3IENvZGVCdWlsZFN0ZXAoYCR7aWRQcmVmaXh9UG9zdEVudiR7Y2FwaXRhbGl6ZUZpcnN0TGV0dGVyKHN0ZXAuZW52aXJvbm1lbnQpfWAsIHtcbiAgICAgICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uZW52VmFyaWFibGVzLFxuICAgICAgICAgICAgICAgICAgICBFTlZfTkFNRTogc3RlcC5lbnZpcm9ubWVudCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNvbW1hbmRzOiBbXG4gICAgICAgICAgICAgICAgICAgIC4uLmNoZWNrb3V0Q29tbWFuZHMsXG4gICAgICAgICAgICAgICAgICAgIC4uLnN0ZXAucG9zdCxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIC4uLnByb3BzLmNvZGVCdWlsZCxcbiAgICAgICAgICAgICAgICByb2xlUG9saWN5U3RhdGVtZW50czogcHJvcHMuY29kZUJ1aWxkLnJvbGVQb2xpY3ksXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVBpcGVsaW5lRmFpbHVyZXNUb3BpYyhwaXBlbGluZTogQ29kZVBpcGVsaW5lKTogVG9waWMge1xuICAgICAgICBjb25zdCBmYWlsdXJlc1RvcGljID0gbmV3IE5vdGlmaWNhdGlvbnNUb3BpYyh0aGlzLCAnUGlwZWxpbmVGYWlsdXJlc1RvcGljJywge1xuICAgICAgICAgICAgcHJvamVjdE5hbWU6IGdldFByb2plY3ROYW1lKHRoaXMpLFxuICAgICAgICAgICAgbm90aWZpY2F0aW9uTmFtZTogJ3BpcGVsaW5lRmFpbHVyZXMnLFxuICAgICAgICB9KTtcblxuICAgICAgICBwaXBlbGluZS5waXBlbGluZS5ub3RpZnlPbihcbiAgICAgICAgICAgICdOb3RpZnlPblBpcGVsaW5lRmFpbHVyZScsXG4gICAgICAgICAgICBmYWlsdXJlc1RvcGljLnRvcGljLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGV2ZW50czogW1BpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzLlBJUEVMSU5FX0VYRUNVVElPTl9GQUlMRURdLFxuICAgICAgICAgICAgICAgIG5vdGlmaWNhdGlvblJ1bGVOYW1lOiBgJHtTdGFjay5vZih0aGlzKS5zdGFja05hbWV9LXBpcGVsaW5lRmFpbHVyZWAsIC8vIGVuc3VyZSB1bmlxdWUgbmFtZVxuICAgICAgICAgICAgfSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gZmFpbHVyZXNUb3BpYy50b3BpYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUbyBzZW5kIENvZGVQaXBlbGluZSBidWlsZCBzdGF0dXMgYmFjayB0byByZXBvc2l0b3J5OlxuICAgICAqIC0gdHJpZ2dlciBMYW1iZGEgZnVuY3Rpb24gb24gQ29kZVBpcGVsaW5lIHN0YXRlIGNoYW5nZSBldmVudHMsXG4gICAgICogLSBpbiBMYW1iZGE6XG4gICAgICogICAtIGdldCBDb2RlUGlwZWxpbmUgZXhlY3V0aW9uIGRldGFpbHMgdG8gZ2V0IGNvbW1pdCBTSEEsXG4gICAgICogICAtIHNlbmQgY3VzdG9tIGV2ZW50IHRvIEV2ZW50QnJpZGdlIGluY2x1ZGluZyB0aGUgY29tbWl0IFNIQSxcbiAgICAgKiAtIHVzZSBFdmVudEJyaWRnZSB0byBzZW5kIGJ1aWxkIHN0YXR1cyB0byByZXBvc2l0b3J5LlxuICAgICAqL1xuICAgIHByaXZhdGUgY3JlYXRlUGlwZWxpbmVCdWlsZE5vdGlmaWNhdGlvbnMoXG4gICAgICAgIHBpcGVsaW5lOiBDb2RlUGlwZWxpbmUsXG4gICAgICAgIHJlcG9zaXRvcnk6IEFwcGxpY2F0aW9uUHJvcHNbJ3JlcG9zaXRvcnknXSxcbiAgICAgICAgcmVwb1Rva2VuUGFyYW06IElTdHJpbmdQYXJhbWV0ZXIsXG4gICAgICAgIHNvdXJjZUJ1Y2tldDogczMuSUJ1Y2tldCxcbiAgICApIHtcbiAgICAgICAgY29uc3QgcGlwZWxpbmVCdWlsZFN0YXR1c0Z1bmN0aW9uID0gbmV3IEN1c3RvbU5vZGVqc0Z1bmN0aW9uKHRoaXMsICdQaXBlbGluZUJ1aWxkU3RhdHVzJywge1xuICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uJywgJ2xhbWJkYScsICdwaXBlbGluZUJ1aWxkU3RhdHVzJykpLFxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICAgICAgICBSRVBPU0lUT1JZX0hPU1Q6IHJlcG9zaXRvcnkuaG9zdCxcbiAgICAgICAgICAgICAgICBSRVBPU0lUT1JZX05BTUU6IHJlcG9zaXRvcnkubmFtZSxcbiAgICAgICAgICAgICAgICBSRVBPU0lUT1JZX1RPS0VOX1BBUkFNX05BTUU6IHJlcG9Ub2tlblBhcmFtLnBhcmFtZXRlck5hbWUsXG4gICAgICAgICAgICAgICAgREVGQVVMVF9CUkFOQ0hfTkFNRTogcmVwb3NpdG9yeS5kZWZhdWx0QnJhbmNoIHx8ICcnLFxuICAgICAgICAgICAgICAgIFNPVVJDRV9CVUNLRVRfTkFNRTogc291cmNlQnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgcmVwb1Rva2VuUGFyYW0uZ3JhbnRSZWFkKHBpcGVsaW5lQnVpbGRTdGF0dXNGdW5jdGlvbik7XG4gICAgICAgIHNvdXJjZUJ1Y2tldC5ncmFudFJlYWQocGlwZWxpbmVCdWlsZFN0YXR1c0Z1bmN0aW9uKTtcblxuICAgICAgICBwaXBlbGluZUJ1aWxkU3RhdHVzRnVuY3Rpb24uYWRkVG9Sb2xlUG9saWN5KG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogWydjb2RlcGlwZWxpbmU6R2V0UGlwZWxpbmVFeGVjdXRpb24nXSxcbiAgICAgICAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOmNvZGVwaXBlbGluZToke0F3cy5SRUdJT059OiR7QXdzLkFDQ09VTlRfSUR9OiR7cGlwZWxpbmUucGlwZWxpbmUucGlwZWxpbmVOYW1lfWBdLFxuICAgICAgICB9KSk7XG5cbiAgICAgICAgcGlwZWxpbmUucGlwZWxpbmUub25TdGF0ZUNoYW5nZSgnT25QaXBlbGluZVN0YXRlQ2hhbmdlJywge1xuICAgICAgICAgICAgdGFyZ2V0OiBuZXcgdGFyZ2V0cy5MYW1iZGFGdW5jdGlvbihwaXBlbGluZUJ1aWxkU3RhdHVzRnVuY3Rpb24pLFxuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=