opinionated-ci-pipeline
Version:
CI/CD on AWS with feature-branch builds, developer-environment deployments, and build status notifications.
115 lines • 20.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MirrorRepository = void 0;
const constructs_1 = require("constructs");
const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const customNodejsFunction_1 = require("./customNodejsFunction");
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
const path = require("path");
const custom_resources_1 = require("aws-cdk-lib/custom-resources");
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
const lambda_layer_awscli_1 = require("aws-cdk-lib/lambda-layer-awscli");
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
const s3 = require("aws-cdk-lib/aws-s3");
const context_1 = require("../util/context");
class MirrorRepository extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
const webhookSecret = aws_cdk_lib_1.Fn.select(2, aws_cdk_lib_1.Fn.split('/', aws_cdk_lib_1.Stack.of(this).stackId));
this.sourceBucket = this.createSourceBucket();
const { triggerMirrorFunctionUrl, } = this.createRepositoryMirroring(webhookSecret, props.repoTokenParam, props.repository, this.sourceBucket);
this.createWebhook(props.repoTokenParam, props.repository, triggerMirrorFunctionUrl);
}
createSourceBucket() {
const bucket = new s3.Bucket(this, 'SourceBucket', {
enforceSSL: true,
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
versioned: true,
lifecycleRules: [
{
id: 'ExpireOldVersions',
noncurrentVersionExpiration: aws_cdk_lib_1.Duration.days(30),
noncurrentVersionsToRetain: 20,
},
],
});
new aws_ssm_1.StringParameter(this, 'SourceBucketNameParam', {
parameterName: `/${(0, context_1.getProjectName)(this)}/ci/sourceBucketName`,
stringValue: bucket.bucketName,
});
new aws_cdk_lib_1.CfnOutput(this, 'SourceBucketName', {
value: bucket.bucketName,
exportName: `${(0, context_1.getProjectName)(this)}-ci-sourceBucketName`,
});
return bucket;
}
createRepositoryMirroring(webhookSecret, repoTokenParam, repository, bucket) {
const sourceRepositoryDomain = repository.host === 'github' ? 'github.com' : 'bitbucket.org';
const mirrorFunction = new aws_lambda_1.Function(this, 'RepositoryMirroring', {
runtime: aws_lambda_1.Runtime.PYTHON_3_11, // AwsCliLayer requires Python function
code: aws_lambda_1.Code.fromAsset(path.join(__dirname, '..', 'lambda', 'mirrorRepository')),
handler: 'index.handler',
timeout: aws_cdk_lib_1.Duration.minutes(3),
memorySize: 2048,
environment: {
HOME: '/var/task',
SECRET: webhookSecret,
BUCKET_NAME: bucket.bucketName,
SOURCE_REPO_DOMAIN: sourceRepositoryDomain,
SOURCE_REPO_HOST: repository.host,
SOURCE_REPO_NAME: repository.name,
SOURCE_REPO_TOKEN_PARAM: repoTokenParam.parameterName,
DEFAULT_BRANCH_NAME: repository.defaultBranch || '',
MAIN_PIPELINE_NAME: aws_cdk_lib_1.Stack.of(this).stackName,
BRANCH_DEPLOY_PROJECT_NAME: `${aws_cdk_lib_1.Stack.of(this).stackName}-featureBranch-deploy`,
BRANCH_DESTROY_PROJECT_NAME: `${aws_cdk_lib_1.Stack.of(this).stackName}-featureBranch-destroy`,
FEATURE_BRANCH_PREFIXES: repository.featureBranchPrefixes?.join(',') || '',
},
initialPolicy: [
new aws_iam_1.PolicyStatement({
actions: ['codepipeline:StartPipelineExecution'],
resources: [`arn:aws:codepipeline:${aws_cdk_lib_1.Stack.of(this).region}:${aws_cdk_lib_1.Stack.of(this).account}:${aws_cdk_lib_1.Stack.of(this).stackName}`],
}),
new aws_iam_1.PolicyStatement({
actions: ['codebuild:StartBuild'],
resources: [`arn:aws:codebuild:${aws_cdk_lib_1.Stack.of(this).region}:${aws_cdk_lib_1.Stack.of(this).account}:project/${aws_cdk_lib_1.Stack.of(this).stackName}-featureBranch-*`],
}),
],
});
mirrorFunction.addLayers(new lambda_layer_awscli_1.AwsCliLayer(this, 'AwsCliLayer'), aws_lambda_1.LayerVersion.fromLayerVersionArn(this, 'GitLayer', `arn:aws:lambda:${aws_cdk_lib_1.Stack.of(this).region}:553035198032:layer:git-lambda2:8`));
bucket.grantWrite(mirrorFunction);
repoTokenParam.grantRead(mirrorFunction);
const triggerMirrorFunctionUrl = mirrorFunction.addFunctionUrl({
authType: aws_lambda_1.FunctionUrlAuthType.NONE,
});
return {
mirrorFunction,
triggerMirrorFunctionUrl: `${triggerMirrorFunctionUrl.url}?secret=${webhookSecret}`,
};
}
createWebhook(repoTokenParam, repository, webhookUrl) {
const setupWebhooksFunction = new customNodejsFunction_1.CustomNodejsFunction(this, 'SetupWebhooksFunction', {
code: aws_lambda_1.Code.fromAsset(path.join(__dirname, '..', 'lambda', 'setupWebhooks')),
timeout: aws_cdk_lib_1.Duration.seconds(30),
});
repoTokenParam.grantRead(setupWebhooksFunction);
const provider = new custom_resources_1.Provider(this, 'WebhookProvider', {
onEventHandler: setupWebhooksFunction,
logRetention: aws_logs_1.RetentionDays.ONE_MONTH,
});
new aws_cdk_lib_1.CustomResource(this, 'Webhook', {
serviceToken: provider.serviceToken,
properties: {
StackName: aws_cdk_lib_1.Stack.of(this).stackName,
RepositoryHost: repository.host,
RepositoryName: repository.name,
RepositoryTokenParamName: repoTokenParam.parameterName,
WebhookUrl: webhookUrl,
},
});
}
}
exports.MirrorRepository = MirrorRepository;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlycm9yUmVwb3NpdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25zdHJ1Y3RzL21pcnJvclJlcG9zaXRvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsMkNBQXFDO0FBQ3JDLGlEQUFzRTtBQUN0RSw2Q0FBMEY7QUFDMUYsaUVBQTREO0FBQzVELHVEQUFvSDtBQUNwSCw2QkFBNkI7QUFDN0IsbUVBQXNEO0FBQ3RELG1EQUFtRDtBQUNuRCx5RUFBNEQ7QUFDNUQsaURBQW9EO0FBQ3BELHlDQUF5QztBQUN6Qyw2Q0FBK0M7QUFNL0MsTUFBYSxnQkFBaUIsU0FBUSxzQkFBUztJQUkzQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTRCO1FBQ2xFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxhQUFhLEdBQUcsZ0JBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLGdCQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRTFFLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFOUMsTUFBTSxFQUNGLHdCQUF3QixHQUMzQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUU3RyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFTyxrQkFBa0I7UUFDdEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUU7WUFD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QyxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUMzRSxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1NBQ2hDLENBQUMsQ0FBQztRQUNILGNBQWMsQ0FBQyxTQUFTLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUVoRCxNQUFNLFFBQVEsR0FBRyxJQUFJLDJCQUFRLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ25ELGNBQWMsRUFBRSxxQkFBcUI7WUFDckMsWUFBWSxFQUFFLHdCQUFhLENBQUMsU0FBUztTQUN4QyxDQUFDLENBQUM7UUFFSCxJQUFJLDRCQUFjLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUNoQyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7WUFDbkMsVUFBVSxFQUFFO2dCQUNSLFNBQVMsRUFBRSxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTO2dCQUNuQyxjQUFjLEVBQUUsVUFBVSxDQUFDLElBQUk7Z0JBQy9CLGNBQWMsRUFBRSxVQUFVLENBQUMsSUFBSTtnQkFDL0Isd0JBQXdCLEVBQUUsY0FBYyxDQUFDLGFBQWE7Z0JBQ3RELFVBQVUsRUFBRSxVQUFVO2FBQ3pCO1NBQ0osQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNKO0FBL0hELDRDQStIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QXBwbGljYXRpb25Qcm9wcywgUmVzb2x2ZWRBcHBsaWNhdGlvblByb3BzfSBmcm9tICcuLi9hcHBsaWNhdGlvblByb3BzJztcbmltcG9ydCB7Q29uc3RydWN0fSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7SVN0cmluZ1BhcmFtZXRlciwgU3RyaW5nUGFyYW1ldGVyfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3NtJztcbmltcG9ydCB7Q2ZuT3V0cHV0LCBDdXN0b21SZXNvdXJjZSwgRHVyYXRpb24sIEZuLCBSZW1vdmFsUG9saWN5LCBTdGFja30gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtDdXN0b21Ob2RlanNGdW5jdGlvbn0gZnJvbSAnLi9jdXN0b21Ob2RlanNGdW5jdGlvbic7XG5pbXBvcnQge0NvZGUsIEZ1bmN0aW9uIGFzIExhbWJkYUZ1bmN0aW9uLCBGdW5jdGlvblVybEF1dGhUeXBlLCBMYXllclZlcnNpb24sIFJ1bnRpbWV9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7UHJvdmlkZXJ9IGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHtSZXRlbnRpb25EYXlzfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQge0F3c0NsaUxheWVyfSBmcm9tICdhd3MtY2RrLWxpYi9sYW1iZGEtbGF5ZXItYXdzY2xpJztcbmltcG9ydCB7UG9saWN5U3RhdGVtZW50fSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQge2dldFByb2plY3ROYW1lfSBmcm9tICcuLi91dGlsL2NvbnRleHQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE1pcnJvclJlcG9zaXRvcnlQcm9wcyBleHRlbmRzIFBpY2s8UmVzb2x2ZWRBcHBsaWNhdGlvblByb3BzLCAncmVwb3NpdG9yeSc+IHtcbiAgICByZXBvVG9rZW5QYXJhbTogSVN0cmluZ1BhcmFtZXRlcjtcbn1cblxuZXhwb3J0IGNsYXNzIE1pcnJvclJlcG9zaXRvcnkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuXG4gICAgcmVhZG9ubHkgc291cmNlQnVja2V0OiBzMy5JQnVja2V0O1xuXG4gICAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE1pcnJvclJlcG9zaXRvcnlQcm9wcykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgICAgIGNvbnN0IHdlYmhvb2tTZWNyZXQgPSBGbi5zZWxlY3QoMiwgRm4uc3BsaXQoJy8nLCBTdGFjay5vZih0aGlzKS5zdGFja0lkKSk7XG5cbiAgICAgICAgdGhpcy5zb3VyY2VCdWNrZXQgPSB0aGlzLmNyZWF0ZVNvdXJjZUJ1Y2tldCgpO1xuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIHRyaWdnZXJNaXJyb3JGdW5jdGlvblVybCxcbiAgICAgICAgfSA9IHRoaXMuY3JlYXRlUmVwb3NpdG9yeU1pcnJvcmluZyh3ZWJob29rU2VjcmV0LCBwcm9wcy5yZXBvVG9rZW5QYXJhbSwgcHJvcHMucmVwb3NpdG9yeSwgdGhpcy5zb3VyY2VCdWNrZXQpO1xuXG4gICAgICAgIHRoaXMuY3JlYXRlV2ViaG9vayhwcm9wcy5yZXBvVG9rZW5QYXJhbSwgcHJvcHMucmVwb3NpdG9yeSwgdHJpZ2dlck1pcnJvckZ1bmN0aW9uVXJsKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVNvdXJjZUJ1Y2tldCgpIHtcbiAgICAgICAgY29uc3QgYnVja2V0ID0gbmV3IHMzLkJ1Y2tldCh0aGlzLCAnU291cmNlQnVja2V0Jywge1xuICAgICAgICAgICAgZW5mb3JjZVNTTDogdHJ1ZSxcbiAgICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBzMy5CbG9ja1B1YmxpY0FjY2Vzcy5CTE9DS19BTEwsXG4gICAgICAgICAgICB2ZXJzaW9uZWQ6IHRydWUsXG4gICAgICAgICAgICBsaWZlY3ljbGVSdWxlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICdFeHBpcmVPbGRWZXJzaW9ucycsXG4gICAgICAgICAgICAgICAgICAgIG5vbmN1cnJlbnRWZXJzaW9uRXhwaXJhdGlvbjogRHVyYXRpb24uZGF5cygzMCksXG4gICAgICAgICAgICAgICAgICAgIG5vbmN1cnJlbnRWZXJzaW9uc1RvUmV0YWluOiAyMCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbmV3IFN0cmluZ1BhcmFtZXRlcih0aGlzLCAnU291cmNlQnVja2V0TmFtZVBhcmFtJywge1xuICAgICAgICAgICAgcGFyYW1ldGVyTmFtZTogYC8ke2dldFByb2plY3ROYW1lKHRoaXMpfS9jaS9zb3VyY2VCdWNrZXROYW1lYCxcbiAgICAgICAgICAgIHN0cmluZ1ZhbHVlOiBidWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCAnU291cmNlQnVja2V0TmFtZScsIHtcbiAgICAgICAgICAgIHZhbHVlOiBidWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAgICAgIGV4cG9ydE5hbWU6IGAke2dldFByb2plY3ROYW1lKHRoaXMpfS1jaS1zb3VyY2VCdWNrZXROYW1lYCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGJ1Y2tldDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVJlcG9zaXRvcnlNaXJyb3JpbmcoXG4gICAgICAgIHdlYmhvb2tTZWNyZXQ6IHN0cmluZyxcbiAgICAgICAgcmVwb1Rva2VuUGFyYW06IElTdHJpbmdQYXJhbWV0ZXIsXG4gICAgICAgIHJlcG9zaXRvcnk6IEFwcGxpY2F0aW9uUHJvcHNbJ3JlcG9zaXRvcnknXSxcbiAgICAgICAgYnVja2V0OiBzMy5JQnVja2V0LFxuICAgICkge1xuICAgICAgICBjb25zdCBzb3VyY2VSZXBvc2l0b3J5RG9tYWluID0gcmVwb3NpdG9yeS5ob3N0ID09PSAnZ2l0aHViJyA/ICdnaXRodWIuY29tJyA6ICdiaXRidWNrZXQub3JnJztcblxuICAgICAgICBjb25zdCBtaXJyb3JGdW5jdGlvbiA9IG5ldyBMYW1iZGFGdW5jdGlvbih0aGlzLCAnUmVwb3NpdG9yeU1pcnJvcmluZycsIHtcbiAgICAgICAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuUFlUSE9OXzNfMTEsIC8vIEF3c0NsaUxheWVyIHJlcXVpcmVzIFB5dGhvbiBmdW5jdGlvblxuICAgICAgICAgICAgY29kZTogQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uJywgJ2xhbWJkYScsICdtaXJyb3JSZXBvc2l0b3J5JykpLFxuICAgICAgICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygzKSxcbiAgICAgICAgICAgIG1lbW9yeVNpemU6IDIwNDgsXG4gICAgICAgICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICAgICAgICAgIEhPTUU6ICcvdmFyL3Rhc2snLFxuICAgICAgICAgICAgICAgIFNFQ1JFVDogd2ViaG9va1NlY3JldCxcbiAgICAgICAgICAgICAgICBCVUNLRVRfTkFNRTogYnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICAgICAgICAgICAgU09VUkNFX1JFUE9fRE9NQUlOOiBzb3VyY2VSZXBvc2l0b3J5RG9tYWluLFxuICAgICAgICAgICAgICAgIFNPVVJDRV9SRVBPX0hPU1Q6IHJlcG9zaXRvcnkuaG9zdCxcbiAgICAgICAgICAgICAgICBTT1VSQ0VfUkVQT19OQU1FOiByZXBvc2l0b3J5Lm5hbWUsXG4gICAgICAgICAgICAgICAgU09VUkNFX1JFUE9fVE9LRU5fUEFSQU06IHJlcG9Ub2tlblBhcmFtLnBhcmFtZXRlck5hbWUsXG4gICAgICAgICAgICAgICAgREVGQVVMVF9CUkFOQ0hfTkFNRTogcmVwb3NpdG9yeS5kZWZhdWx0QnJhbmNoIHx8ICcnLFxuICAgICAgICAgICAgICAgIE1BSU5fUElQRUxJTkVfTkFNRTogU3RhY2sub2YodGhpcykuc3RhY2tOYW1lLFxuICAgICAgICAgICAgICAgIEJSQU5DSF9ERVBMT1lfUFJPSkVDVF9OQU1FOiBgJHtTdGFjay5vZih0aGlzKS5zdGFja05hbWV9LWZlYXR1cmVCcmFuY2gtZGVwbG95YCxcbiAgICAgICAgICAgICAgICBCUkFOQ0hfREVTVFJPWV9QUk9KRUNUX05BTUU6IGAke1N0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZX0tZmVhdHVyZUJyYW5jaC1kZXN0cm95YCxcbiAgICAgICAgICAgICAgICBGRUFUVVJFX0JSQU5DSF9QUkVGSVhFUzogcmVwb3NpdG9yeS5mZWF0dXJlQnJhbmNoUHJlZml4ZXM/LmpvaW4oJywnKSB8fCAnJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbml0aWFsUG9saWN5OiBbXG4gICAgICAgICAgICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnM6IFsnY29kZXBpcGVsaW5lOlN0YXJ0UGlwZWxpbmVFeGVjdXRpb24nXSxcbiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbYGFybjphd3M6Y29kZXBpcGVsaW5lOiR7U3RhY2sub2YodGhpcykucmVnaW9ufToke1N0YWNrLm9mKHRoaXMpLmFjY291bnR9OiR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfWBdLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb25zOiBbJ2NvZGVidWlsZDpTdGFydEJ1aWxkJ10sXG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOmNvZGVidWlsZDoke1N0YWNrLm9mKHRoaXMpLnJlZ2lvbn06JHtTdGFjay5vZih0aGlzKS5hY2NvdW50fTpwcm9qZWN0LyR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS1mZWF0dXJlQnJhbmNoLSpgXSxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1pcnJvckZ1bmN0aW9uLmFkZExheWVycyhcbiAgICAgICAgICAgIG5ldyBBd3NDbGlMYXllcih0aGlzLCAnQXdzQ2xpTGF5ZXInKSxcbiAgICAgICAgICAgIExheWVyVmVyc2lvbi5mcm9tTGF5ZXJWZXJzaW9uQXJuKHRoaXMsICdHaXRMYXllcicsIGBhcm46YXdzOmxhbWJkYToke1N0YWNrLm9mKHRoaXMpLnJlZ2lvbn06NTUzMDM1MTk4MDMyOmxheWVyOmdpdC1sYW1iZGEyOjhgKSxcbiAgICAgICAgKTtcblxuICAgICAgICBidWNrZXQuZ3JhbnRXcml0ZShtaXJyb3JGdW5jdGlvbik7XG4gICAgICAgIHJlcG9Ub2tlblBhcmFtLmdyYW50UmVhZChtaXJyb3JGdW5jdGlvbik7XG5cbiAgICAgICAgY29uc3QgdHJpZ2dlck1pcnJvckZ1bmN0aW9uVXJsID0gbWlycm9yRnVuY3Rpb24uYWRkRnVuY3Rpb25Vcmwoe1xuICAgICAgICAgICAgYXV0aFR5cGU6IEZ1bmN0aW9uVXJsQXV0aFR5cGUuTk9ORSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pcnJvckZ1bmN0aW9uLFxuICAgICAgICAgICAgdHJpZ2dlck1pcnJvckZ1bmN0aW9uVXJsOiBgJHt0cmlnZ2VyTWlycm9yRnVuY3Rpb25VcmwudXJsfT9zZWNyZXQ9JHt3ZWJob29rU2VjcmV0fWAsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVXZWJob29rKHJlcG9Ub2tlblBhcmFtOiBJU3RyaW5nUGFyYW1ldGVyLCByZXBvc2l0b3J5OiBBcHBsaWNhdGlvblByb3BzWydyZXBvc2l0b3J5J10sIHdlYmhvb2tVcmw6IHN0cmluZykge1xuICAgICAgICBjb25zdCBzZXR1cFdlYmhvb2tzRnVuY3Rpb24gPSBuZXcgQ3VzdG9tTm9kZWpzRnVuY3Rpb24odGhpcywgJ1NldHVwV2ViaG9va3NGdW5jdGlvbicsIHtcbiAgICAgICAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdsYW1iZGEnLCAnc2V0dXBXZWJob29rcycpKSxcbiAgICAgICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoMzApLFxuICAgICAgICB9KTtcbiAgICAgICAgcmVwb1Rva2VuUGFyYW0uZ3JhbnRSZWFkKHNldHVwV2ViaG9va3NGdW5jdGlvbik7XG5cbiAgICAgICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgUHJvdmlkZXIodGhpcywgJ1dlYmhvb2tQcm92aWRlcicsIHtcbiAgICAgICAgICAgIG9uRXZlbnRIYW5kbGVyOiBzZXR1cFdlYmhvb2tzRnVuY3Rpb24sXG4gICAgICAgICAgICBsb2dSZXRlbnRpb246IFJldGVudGlvbkRheXMuT05FX01PTlRILFxuICAgICAgICB9KTtcblxuICAgICAgICBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1dlYmhvb2snLCB7XG4gICAgICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICBTdGFja05hbWU6IFN0YWNrLm9mKHRoaXMpLnN0YWNrTmFtZSxcbiAgICAgICAgICAgICAgICBSZXBvc2l0b3J5SG9zdDogcmVwb3NpdG9yeS5ob3N0LFxuICAgICAgICAgICAgICAgIFJlcG9zaXRvcnlOYW1lOiByZXBvc2l0b3J5Lm5hbWUsXG4gICAgICAgICAgICAgICAgUmVwb3NpdG9yeVRva2VuUGFyYW1OYW1lOiByZXBvVG9rZW5QYXJhbS5wYXJhbWV0ZXJOYW1lLFxuICAgICAgICAgICAgICAgIFdlYmhvb2tVcmw6IHdlYmhvb2tVcmwsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=