UNPKG

deploy-time-build

Version:
221 lines (216 loc) 29.7 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.NodejsBuild = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path_1 = require("path"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const aws_codebuild_1 = require("aws-cdk-lib/aws-codebuild"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); const aws_lambda_1 = require("aws-cdk-lib/aws-lambda"); const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets"); const constructs_1 = require("constructs"); /** * Build Node.js app and optionally publish the artifact to an S3 bucket. */ class NodejsBuild extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); const handler = new aws_lambda_1.SingletonFunction(this, 'CustomResourceHandler', { // Use raw string to avoid from tightening CDK version requirement runtime: new aws_lambda_1.Runtime('nodejs22.x', aws_lambda_1.RuntimeFamily.NODEJS), code: aws_lambda_1.Code.fromAsset((0, path_1.join)(__dirname, '..', 'lambda', 'trigger-codebuild', 'dist')), handler: 'index.handler', uuid: '25648b21-2c40-4f09-aa65-b6bbb0c44659', // generated for this construct lambdaPurpose: 'NodejsBuildCustomResourceHandler', timeout: aws_cdk_lib_1.Duration.minutes(5), }); const nodejsVersion = props.nodejsVersion ?? 18; let buildImage = 'aws/codebuild/standard:7.0'; // See: https://docs.aws.amazon.com/codebuild/latest/userguide/available-runtimes.html#linux-runtimes switch (nodejsVersion) { case 12: case 14: buildImage = 'aws/codebuild/standard:5.0'; break; case 16: buildImage = 'aws/codebuild/standard:6.0'; break; case 18: case 20: case 22: buildImage = 'aws/codebuild/standard:7.0'; break; default: aws_cdk_lib_1.Annotations.of(this).addWarning(`Possibly unsupported Node.js version: ${nodejsVersion}. Currently 12, 14, 16, 18, 20, and 22 are supported.`); } const outputEnvFile = props.outputEnvFile ?? false; const envFileKeyOutputKey = 'envFileKey'; const project = new aws_codebuild_1.Project(this, 'Project', { environment: { buildImage: aws_codebuild_1.LinuxBuildImage.fromCodeBuildImageId(buildImage) }, buildSpec: aws_codebuild_1.BuildSpec.fromObject({ version: '0.2', env: { shell: 'bash', }, phases: { install: { 'runtime-versions': { nodejs: nodejsVersion, }, }, build: { commands: [ 'current_dir=$(pwd)', // Iterate a json array using jq // https://www.starkandwayne.com/blog/bash-for-loop-over-json-array-using-jq/index.html ` echo "$input" for obj in $(echo "$input" | jq -r '.[] | @base64'); do decoded=$(echo "$obj" | base64 --decode) assetUrl=$(echo "$decoded" | jq -r '.assetUrl') extractPath=$(echo "$decoded" | jq -r '.extractPath') commands=$(echo "$decoded" | jq -r '.commands') # Download the zip file aws s3 cp "$assetUrl" temp.zip # Extract the zip file to the extractPath directory mkdir -p "$extractPath" unzip temp.zip -d "$extractPath" # Remove the zip file rm temp.zip # Run the specified commands in the extractPath directory cd "$extractPath" ls -la eval "$commands" cd "$current_dir" ls -la done `, 'ls -la', 'cd "$workingDirectory"', 'eval "$buildCommands"', 'ls -la', 'cd "$current_dir"', 'cd "$outputSourceDirectory"', 'aws s3 sync . "s3://$destinationBucketName/$destinationKeyPrefix" --delete', // Invalidate CloudFront cache if distribution is specified ` if [[ -n "$distributionId" ]] then INVALIDATION_OUTPUT=$(aws cloudfront create-invalidation --distribution-id "$distributionId" --paths "$distributionPath" --output json) INVALIDATION_ID=$(echo "$INVALIDATION_OUTPUT" | jq -r '.Invalidation.Id') aws cloudfront wait invalidation-completed --distribution-id "$distributionId" --id "$INVALIDATION_ID" fi `, // Upload .env if required ` if [[ $outputEnvFile == "true" ]] then # Split the comma-separated string into an array for var_name in \${envNames//,/ } do echo "Element: $var_name" var_value="\${!var_name}" echo "$var_name=$var_value" >> tmp.env done aws s3 cp tmp.env "s3://$assetBucketName/$envFileKey" fi `, ], }, post_build: { commands: [ 'echo Build completed on `date`', ` STATUS='SUCCESS' if [ $CODEBUILD_BUILD_SUCCEEDING -ne 1 ] # Test if the build is failing then STATUS='FAILED' REASON="NodejsBuild failed. See CloudWatch Log stream for the detailed reason: https://$AWS_REGION.console.aws.amazon.com/cloudwatch/home?region=$AWS_REGION#logsV2:log-groups/log-group/\\$252Faws\\$252Fcodebuild\\$252F$projectName/log-events/$CODEBUILD_LOG_PATH" fi cat <<EOF > payload.json { "StackId": "$stackId", "RequestId": "$requestId", "LogicalResourceId":"$logicalResourceId", "PhysicalResourceId": "$logicalResourceId", "Status": "$STATUS", "Reason": "$REASON", "Data": { "${envFileKeyOutputKey}": "$envFileKey" } } EOF curl -i -X PUT -H 'Content-Type:' -d "@payload.json" "$responseURL" `, ], }, }, }), }); handler.addToRolePolicy(new aws_iam_1.PolicyStatement({ actions: ['codebuild:StartBuild'], resources: [project.projectArn], })); this.grantPrincipal = project.grantPrincipal; props.destinationBucket.grantReadWrite(project); if (props.distribution) { project.addToRolePolicy(new aws_iam_1.PolicyStatement({ actions: ['cloudfront:GetInvalidation', 'cloudfront:CreateInvalidation'], resources: [props.distribution.distributionArn], })); } const commonExclude = ['.DS_Store', '.git', 'node_modules']; const assets = props.assets.map((assetProps) => { const asset = new aws_s3_assets_1.Asset(this, `Source-${assetProps.path.replace('/', '')}`, { ...assetProps, ...(props.excludeCommonFiles ?? true ? { exclude: [...commonExclude, ...(assetProps.exclude ?? [])] } : {}), }); asset.grantRead(project); return asset; }); const bucket = assets[0].bucket; if (outputEnvFile) { // use the asset bucket that are created by CDK bootstrap to store .env file bucket.grantWrite(project); } const sources = props.assets.map((s, i) => ({ sourceBucketName: assets[i].s3BucketName, sourceObjectKey: assets[i].s3ObjectKey, extractPath: s.extractPath ?? (0, path_1.basename)(s.path), commands: s.commands, })); const workingDirectory = props.workingDirectory ?? sources[0].extractPath; const properties = { type: 'NodejsBuild', sources, destinationBucketName: props.destinationBucket.bucketName, destinationKeyPrefix: props.destinationKeyPrefix ?? '/', distributionId: props.distribution?.distributionId, assetBucketName: bucket.bucketName, workingDirectory, // join paths for CodeBuild (Linux) platform outputSourceDirectory: path_1.posix.join(workingDirectory, props.outputSourceDirectory), environment: props.buildEnvironment, buildCommands: props.buildCommands ?? ['npm run build'], codeBuildProjectName: project.projectName, outputEnvFile, }; const custom = new aws_cdk_lib_1.CustomResource(this, 'Resource', { serviceToken: handler.functionArn, resourceType: 'Custom::CDKNodejsBuild', properties, }); if (project.role) { custom.node.addDependency(project.role); } if (props.outputEnvFile) { new aws_cdk_lib_1.CfnOutput(this, 'DownloadEnvFile', { value: `aws s3 cp ${bucket.s3UrlForObject(custom.getAttString(envFileKeyOutputKey))} .env.local` }); } } } exports.NodejsBuild = NodejsBuild; _a = JSII_RTTI_SYMBOL_1; NodejsBuild[_a] = { fqn: "deploy-time-build.NodejsBuild", version: "0.4.5" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25vZGVqcy1idWlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLCtCQUE2QztBQUM3Qyw2Q0FBK0U7QUFFL0UsNkRBQWdGO0FBQ2hGLGlEQUE4RTtBQUM5RSx1REFBeUY7QUFFekYsNkRBQThEO0FBQzlELDJDQUF1QztBQTRFdkM7O0dBRUc7QUFDSCxNQUFhLFdBQVksU0FBUSxzQkFBUztJQUd4QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXVCO1FBQy9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxPQUFPLEdBQUcsSUFBSSw4QkFBaUIsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7WUFDbkUsa0VBQWtFO1lBQ2xFLE9BQU8sRUFBRSxJQUFJLG9CQUFPLENBQUMsWUFBWSxFQUFFLDBCQUFhLENBQUMsTUFBTSxDQUFDO1lBQ3hELElBQUksRUFBRSxpQkFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsRixPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsc0NBQXNDLEVBQUUsK0JBQStCO1lBQzdFLGFBQWEsRUFBRSxrQ0FBa0M7WUFDakQsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztTQUM3QixDQUFDLENBQUM7UUFFSCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUNoRCxJQUFJLFVBQVUsR0FBRyw0QkFBNEIsQ0FBQztRQUM5QyxxR0FBcUc7UUFDckcsUUFBUSxhQUFhLEVBQUUsQ0FBQztZQUN0QixLQUFLLEVBQUUsQ0FBQztZQUNSLEtBQUssRUFBRTtnQkFDTCxVQUFVLEdBQUcsNEJBQTRCLENBQUM7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QW9CLElBQUksR0FBRztZQUN2RCxjQUFjLEVBQUUsS0FBSyxDQUFDLFlBQVksRUFBRSxjQUFjO1lBQ2xELGVBQWUsRUFBRSxNQUFNLENBQUMsVUFBVTtZQUNsQyxnQkFBZ0I7WUFDaEIsNENBQTRDO1lBQzVDLHFCQUFxQixFQUFFLFlBQUssQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLHFCQUFxQixDQUFDO1lBQ2hGLFdBQVcsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO1lBQ25DLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQ3ZELG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ3pDLGFBQWE7U0FDZCxDQUFDO1FBRUYsTUFBTSxNQUFNLEdBQUcsSUFBSSw0QkFBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbEQsWUFBWSxFQUFFLE9BQU8sQ0FBQyxXQUFXO1lBQ2pDLFlBQVksRUFBRSx3QkFBd0I7WUFDdEMsVUFBVTtTQUNYLENBQUMsQ0FBQztRQUNILElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDeEIsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEtBQUssRUFBRSxhQUFhLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7UUFDL0ksQ0FBQztJQUNILENBQUM7O0FBM05ILGtDQTROQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJhc2VuYW1lLCBqb2luLCBwb3NpeCB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQW5ub3RhdGlvbnMsIENmbk91dHB1dCwgQ3VzdG9tUmVzb3VyY2UsIER1cmF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSURpc3RyaWJ1dGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZGZyb250JztcbmltcG9ydCB7IEJ1aWxkU3BlYywgTGludXhCdWlsZEltYWdlLCBQcm9qZWN0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNvZGVidWlsZCc7XG5pbXBvcnQgeyBJR3JhbnRhYmxlLCBJUHJpbmNpcGFsLCBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IENvZGUsIFJ1bnRpbWUsIFJ1bnRpbWVGYW1pbHksIFNpbmdsZXRvbkZ1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBJQnVja2V0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IEFzc2V0LCBBc3NldFByb3BzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLWFzc2V0cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE5vZGVqc0J1aWxkUmVzb3VyY2VQcm9wcyB9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFzc2V0Q29uZmlnIGV4dGVuZHMgQXNzZXRQcm9wcyB7XG4gIC8qKlxuICAgKiBTaGVsbCBjb21tYW5kcyBleGVjdXRlZCByaWdodCBhZnRlciB0aGUgYXNzZXQgemlwIGlzIGV4dHJhY3RlZCB0byB0aGUgYnVpbGQgZW52aXJvbm1lbnQuXG4gICAqIEBkZWZhdWx0IE5vIGNvbW1hbmQgaXMgZXhlY3V0ZWQuXG4gICAqL1xuICByZWFkb25seSBjb21tYW5kcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBSZWxhdGl2ZSBwYXRoIGZyb20gYSBidWlsZCBkaXJlY3RvcnkgdG8gdGhlIGRpcmVjdG9yeSB3aGVyZSB0aGUgYXNzZXQgaXMgZXh0cmFjdGVkLlxuICAgKiBAZGVmYXVsdCBiYXNlbmFtZSBvZiB0aGUgYXNzZXQgcGF0aC5cbiAgICovXG4gIHJlYWRvbmx5IGV4dHJhY3RQYXRoPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5vZGVqc0J1aWxkUHJvcHMge1xuICAvKipcbiAgICogVGhlIEFzc2V0UHJvcHMgZnJvbSB3aGljaCBzMy1hc3NldHMgYXJlIGNyZWF0ZWQgYW5kIGNvcGllZCB0byB0aGUgYnVpbGQgZW52aXJvbm1lbnQuXG4gICAqL1xuICByZWFkb25seSBhc3NldHM6IEFzc2V0Q29uZmlnW107XG4gIC8qKlxuICAgKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgaW5qZWN0ZWQgdG8gdGhlIGJ1aWxkIGVudmlyb25tZW50LlxuICAgKiBZb3UgY2FuIHVzZSBDREsgZGVwbG95LXRpbWUgdmFsdWVzIGFzIHdlbGwgYXMgbGl0ZXJhbHMuXG4gICAqIEBkZWZhdWx0IHt9XG4gICAqL1xuICByZWFkb25seSBidWlsZEVudmlyb25tZW50PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgLyoqXG4gICAqIFMzIEJ1Y2tldCB0byB3aGljaCB5b3VyIGJ1aWxkIGFydGlmYWN0cyBhcmUgZmluYWxseSBkZXBsb3llZC5cbiAgICovXG4gIHJlYWRvbmx5IGRlc3RpbmF0aW9uQnVja2V0OiBJQnVja2V0O1xuICAvKipcbiAgICogS2V5IHByZWZpeCB0byBkZXBsb3kgeW91ciBidWlsZCBhcnRpZmFjdC5cbiAgICogQGRlZmF1bHQgJy8nXG4gICAqL1xuICByZWFkb25seSBkZXN0aW5hdGlvbktleVByZWZpeD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBkaXN0cmlidXRpb24geW91IGFyZSB1c2luZyB0byBwdWJsaXNoIHlvdSBidWlsZCBhcnRpZmFjdC5cbiAgICogSWYgYW55IHNwZWNpZmllZCwgdGhlIGNhY2hlcyBhcmUgaW52YWxpZGF0ZWQgb24gbmV3IGFydGlmYWN0IGRlcGxveW1lbnRzLlxuICAgKiBAZGVmYXVsdCBObyBkaXN0cmlidXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbj86IElEaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBTaGVsbCBjb21tYW5kcyB0byBidWlsZCB5b3VyIHByb2plY3QuIFRoZXkgYXJlIGV4ZWN1dGVkIG9uIHRoZSB3b3JraW5nIGRpcmVjdG9yeSB5b3Ugc3BlY2lmaWVkLlxuICAgKiBAZGVmYXVsdCBbJ25wbSBydW4gYnVpbGQnXVxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRDb21tYW5kcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogUmVsYXRpdmUgcGF0aCBmcm9tIHRoZSBidWlsZCBkaXJlY3RvcnkgdG8gdGhlIGRpcmVjdG9yeSB3aGVyZSBidWlsZCBjb21tYW5kcyBydW4uXG4gICAqIEBkZWZhdWx0IGFzc2V0UHJvcHNbMF0uZXh0cmFjdFBhdGhcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtpbmdEaXJlY3Rvcnk/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSZWxhdGl2ZSBwYXRoIGZyb20gdGhlIHdvcmtpbmcgZGlyZWN0b3J5IHRvIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIGJ1aWxkIGFydGlmYWN0cyBhcmUgb3V0cHV0LlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0U291cmNlRGlyZWN0b3J5OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdmVyc2lvbiBvZiBOb2RlLmpzIHRvIHVzZSBpbiBhIGJ1aWxkIGVudmlyb25tZW50LiBBdmFpbGFibGUgdmVyc2lvbnM6IDEyLCAxNCwgMTYsIDE4LCAyMCwgYW5kIDIyLlxuICAgKiBAZGVmYXVsdCAxOFxuICAgKi9cbiAgcmVhZG9ubHkgbm9kZWpzVmVyc2lvbj86IG51bWJlcjtcbiAgLyoqXG4gICAqIElmIHRydWUsIGEgLmVudiBmaWxlIGlzIHVwbG9hZGVkIHRvIGFuIFMzIGJ1Y2tldCB3aXRoIHZhbHVlcyBvZiBgYnVpbGRFbnZpcm9ubWVudGAgcHJvcGVydHkuXG4gICAqIFlvdSBjYW4gY29weSBpdCB0byB5b3VyIGxvY2FsIG1hY2hpbmUgYnkgcnVubmluZyB0aGUgY29tbWFuZCBpbiB0aGUgc3RhY2sgb3V0cHV0LlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0RW52RmlsZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZiB0cnVlLCBjb21tb24gdW5uZWNlc3NhcnkgZmlsZXMvZGlyZWN0b3JpZXMgc3VjaCBhcyAuRFNfU3RvcmUsIC5naXQsIG5vZGVfbW9kdWxlcywgZXRjIGFyZSBleGNsdWRlZFxuICAgKiBmcm9tIHRoZSBhc3NldHMgYnkgZGVmYXVsdC5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZUNvbW1vbkZpbGVzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBCdWlsZCBOb2RlLmpzIGFwcCBhbmQgb3B0aW9uYWxseSBwdWJsaXNoIHRoZSBhcnRpZmFjdCB0byBhbiBTMyBidWNrZXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb2RlanNCdWlsZCBleHRlbmRzIENvbnN0cnVjdCBpbXBsZW1lbnRzIElHcmFudGFibGUge1xuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnRQcmluY2lwYWw6IElQcmluY2lwYWw7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE5vZGVqc0J1aWxkUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBTaW5nbGV0b25GdW5jdGlvbih0aGlzLCAnQ3VzdG9tUmVzb3VyY2VIYW5kbGVyJywge1xuICAgICAgLy8gVXNlIHJhdyBzdHJpbmcgdG8gYXZvaWQgZnJvbSB0aWdodGVuaW5nIENESyB2ZXJzaW9uIHJlcXVpcmVtZW50XG4gICAgICBydW50aW1lOiBuZXcgUnVudGltZSgnbm9kZWpzMjIueCcsIFJ1bnRpbWVGYW1pbHkuTk9ERUpTKSxcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KGpvaW4oX19kaXJuYW1lLCAnLi4nLCAnbGFtYmRhJywgJ3RyaWdnZXItY29kZWJ1aWxkJywgJ2Rpc3QnKSksXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICB1dWlkOiAnMjU2NDhiMjEtMmM0MC00ZjA5LWFhNjUtYjZiYmIwYzQ0NjU5JywgLy8gZ2VuZXJhdGVkIGZvciB0aGlzIGNvbnN0cnVjdFxuICAgICAgbGFtYmRhUHVycG9zZTogJ05vZGVqc0J1aWxkQ3VzdG9tUmVzb3VyY2VIYW5kbGVyJyxcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBub2RlanNWZXJzaW9uID0gcHJvcHMubm9kZWpzVmVyc2lvbiA/PyAxODtcbiAgICBsZXQgYnVpbGRJbWFnZSA9ICdhd3MvY29kZWJ1aWxkL3N0YW5kYXJkOjcuMCc7XG4gICAgLy8gU2VlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY29kZWJ1aWxkL2xhdGVzdC91c2VyZ3VpZGUvYXZhaWxhYmxlLXJ1bnRpbWVzLmh0bWwjbGludXgtcnVudGltZXNcbiAgICBzd2l0Y2ggKG5vZGVqc1ZlcnNpb24pIHtcbiAgICAgIGNhc2UgMTI6XG4gICAgICBjYXNlIDE0OlxuICAgICAgICBidWlsZEltYWdlID0gJ2F3cy9jb2RlYnVpbGQvc3RhbmRhcmQ6NS4wJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE2OlxuICAgICAgICBidWlsZEltYWdlID0gJ2F3cy9jb2RlYnVpbGQvc3RhbmRhcmQ6Ni4wJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE4OlxuICAgICAgY2FzZSAyMDpcbiAgICAgIGNhc2UgMjI6XG4gICAgICAgIGJ1aWxkSW1hZ2UgPSAnYXdzL2NvZGVidWlsZC9zdGFuZGFyZDo3LjAnO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmcoYFBvc3NpYmx5IHVuc3VwcG9ydGVkIE5vZGUuanMgdmVyc2lvbjogJHtub2RlanNWZXJzaW9ufS4gQ3VycmVudGx5IDEyLCAxNCwgMTYsIDE4LCAyMCwgYW5kIDIyIGFyZSBzdXBwb3J0ZWQuYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0RW52RmlsZSA9IHByb3BzLm91dHB1dEVudkZpbGUgPz8gZmFsc2U7XG4gICAgY29uc3QgZW52RmlsZUtleU91dHB1dEtleSA9ICdlbnZGaWxlS2V5JztcblxuICAgIGNvbnN0IHByb2plY3QgPSBuZXcgUHJvamVjdCh0aGlzLCAnUHJvamVjdCcsIHtcbiAgICAgIGVudmlyb25tZW50OiB7IGJ1aWxkSW1hZ2U6IExpbnV4QnVpbGRJbWFnZS5mcm9tQ29kZUJ1aWxkSW1hZ2VJZChidWlsZEltYWdlKSB9LFxuICAgICAgYnVpbGRTcGVjOiBCdWlsZFNwZWMuZnJvbU9iamVjdCh7XG4gICAgICAgIHZlcnNpb246ICcwLjInLFxuICAgICAgICBlbnY6IHtcbiAgICAgICAgICBzaGVsbDogJ2Jhc2gnLFxuICAgICAgICB9LFxuICAgICAgICBwaGFzZXM6IHtcbiAgICAgICAgICBpbnN0YWxsOiB7XG4gICAgICAgICAgICAncnVudGltZS12ZXJzaW9ucyc6IHtcbiAgICAgICAgICAgICAgbm9kZWpzOiBub2RlanNWZXJzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJ1aWxkOiB7XG4gICAgICAgICAgICBjb21tYW5kczogW1xuICAgICAgICAgICAgICAnY3VycmVudF9kaXI9JChwd2QpJyxcbiAgICAgICAgICAgICAgLy8gSXRlcmF0ZSBhIGpzb24gYXJyYXkgdXNpbmcganFcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cuc3RhcmthbmR3YXluZS5jb20vYmxvZy9iYXNoLWZvci1sb29wLW92ZXItanNvbi1hcnJheS11c2luZy1qcS9pbmRleC5odG1sXG4gICAgICAgICAgICAgIGBcbmVjaG8gXCIkaW5wdXRcIlxuZm9yIG9iaiBpbiAkKGVjaG8gXCIkaW5wdXRcIiB8IGpxIC1yICcuW10gfCBAYmFzZTY0Jyk7IGRvXG4gIGRlY29kZWQ9JChlY2hvIFwiJG9ialwiIHwgYmFzZTY0IC0tZGVjb2RlKVxuICBhc3NldFVybD0kKGVjaG8gXCIkZGVjb2RlZFwiIHwganEgLXIgJy5hc3NldFVybCcpXG4gIGV4dHJhY3RQYXRoPSQoZWNobyBcIiRkZWNvZGVkXCIgfCBqcSAtciAnLmV4dHJhY3RQYXRoJylcbiAgY29tbWFuZHM9JChlY2hvIFwiJGRlY29kZWRcIiB8IGpxIC1yICcuY29tbWFuZHMnKVxuXG4gICMgRG93bmxvYWQgdGhlIHppcCBmaWxlXG4gIGF3cyBzMyBjcCBcIiRhc3NldFVybFwiIHRlbXAuemlwXG5cbiAgIyBFeHRyYWN0IHRoZSB6aXAgZmlsZSB0byB0aGUgZXh0cmFjdFBhdGggZGlyZWN0b3J5XG4gIG1rZGlyIC1wIFwiJGV4dHJhY3RQYXRoXCJcbiAgdW56aXAgdGVtcC56aXAgLWQgXCIkZXh0cmFjdFBhdGhcIlxuXG4gICMgUmVtb3ZlIHRoZSB6aXAgZmlsZVxuICBybSB0ZW1wLnppcFxuXG4gICMgUnVuIHRoZSBzcGVjaWZpZWQgY29tbWFuZHMgaW4gdGhlIGV4dHJhY3RQYXRoIGRpcmVjdG9yeVxuICBjZCBcIiRleHRyYWN0UGF0aFwiXG4gIGxzIC1sYVxuICBldmFsIFwiJGNvbW1hbmRzXCJcbiAgY2QgXCIkY3VycmVudF9kaXJcIlxuICBscyAtbGFcbmRvbmVcbiAgICAgICAgICAgICAgYCxcbiAgICAgICAgICAgICAgJ2xzIC1sYScsXG4gICAgICAgICAgICAgICdjZCBcIiR3b3JraW5nRGlyZWN0b3J5XCInLFxuICAgICAgICAgICAgICAnZXZhbCBcIiRidWlsZENvbW1hbmRzXCInLFxuICAgICAgICAgICAgICAnbHMgLWxhJyxcbiAgICAgICAgICAgICAgJ2NkIFwiJGN1cnJlbnRfZGlyXCInLFxuICAgICAgICAgICAgICAnY2QgXCIkb3V0cHV0U291cmNlRGlyZWN0b3J5XCInLFxuICAgICAgICAgICAgICAnYXdzIHMzIHN5bmMgLiBcInMzOi8vJGRlc3RpbmF0aW9uQnVja2V0TmFtZS8kZGVzdGluYXRpb25LZXlQcmVmaXhcIiAtLWRlbGV0ZScsXG4gICAgICAgICAgICAgIC8vIEludmFsaWRhdGUgQ2xvdWRGcm9udCBjYWNoZSBpZiBkaXN0cmlidXRpb24gaXMgc3BlY2lmaWVkXG4gICAgICAgICAgICAgIGBcbmlmIFtbIC1uIFwiJGRpc3RyaWJ1dGlvbklkXCIgXV1cbnRoZW5cbklOVkFMSURBVElPTl9PVVRQVVQ9JChhd3MgY2xvdWRmcm9udCBjcmVhdGUtaW52YWxpZGF0aW9uIC0tZGlzdHJpYnV0aW9uLWlkIFwiJGRpc3RyaWJ1dGlvbklkXCIgLS1wYXRocyBcIiRkaXN0cmlidXRpb25QYXRoXCIgLS1vdXRwdXQganNvbilcbklOVkFMSURBVElPTl9JRD0kKGVjaG8gXCIkSU5WQUxJREFUSU9OX09VVFBVVFwiIHwganEgLXIgJy5JbnZhbGlkYXRpb24uSWQnKVxuYXdzIGNsb3VkZnJvbnQgd2FpdCBpbnZhbGlkYXRpb24tY29tcGxldGVkIC0tZGlzdHJpYnV0aW9uLWlkIFwiJGRpc3RyaWJ1dGlvbklkXCIgLS1pZCBcIiRJTlZBTElEQVRJT05fSURcIlxuZmlcbmAsXG4gICAgICAgICAgICAgIC8vIFVwbG9hZCAuZW52IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgIGBcbmlmIFtbICRvdXRwdXRFbnZGaWxlID09IFwidHJ1ZVwiIF1dXG50aGVuXG4gICMgU3BsaXQgdGhlIGNvbW1hLXNlcGFyYXRlZCBzdHJpbmcgaW50byBhbiBhcnJheVxuICBmb3IgdmFyX25hbWUgaW4gXFwke2Vudk5hbWVzLy8sLyB9XG4gIGRvXG4gICAgICBlY2hvIFwiRWxlbWVudDogJHZhcl9uYW1lXCJcbiAgICAgIHZhcl92YWx1ZT1cIlxcJHshdmFyX25hbWV9XCJcbiAgICAgIGVjaG8gXCIkdmFyX25hbWU9JHZhcl92YWx1ZVwiID4+IHRtcC5lbnZcbiAgZG9uZVxuXG4gIGF3cyBzMyBjcCB0bXAuZW52IFwiczM6Ly8kYXNzZXRCdWNrZXROYW1lLyRlbnZGaWxlS2V5XCJcbmZpXG4gICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcG9zdF9idWlsZDoge1xuICAgICAgICAgICAgY29tbWFuZHM6IFtcbiAgICAgICAgICAgICAgJ2VjaG8gQnVpbGQgY29tcGxldGVkIG9uIGBkYXRlYCcsXG4gICAgICAgICAgICAgIGBcblNUQVRVUz0nU1VDQ0VTUydcbmlmIFsgJENPREVCVUlMRF9CVUlMRF9TVUNDRUVESU5HIC1uZSAxIF0gIyBUZXN0IGlmIHRoZSBidWlsZCBpcyBmYWlsaW5nXG50aGVuXG5TVEFUVVM9J0ZBSUxFRCdcblJFQVNPTj1cIk5vZGVqc0J1aWxkIGZhaWxlZC4gU2VlIENsb3VkV2F0Y2ggTG9nIHN0cmVhbSBmb3IgdGhlIGRldGFpbGVkIHJlYXNvbjogXG5odHRwczovLyRBV1NfUkVHSU9OLmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0kQVdTX1JFR0lPTiNsb2dzVjI6bG9nLWdyb3Vwcy9sb2ctZ3JvdXAvXFxcXCQyNTJGYXdzXFxcXCQyNTJGY29kZWJ1aWxkXFxcXCQyNTJGJHByb2plY3ROYW1lL2xvZy1ldmVudHMvJENPREVCVUlMRF9MT0dfUEFUSFwiXG5maVxuY2F0IDw8RU9GID4gcGF5bG9hZC5qc29uXG57XG4gIFwiU3RhY2tJZFwiOiBcIiRzdGFja0lkXCIsXG4gIFwiUmVxdWVzdElkXCI6IFwiJHJlcXVlc3RJZFwiLFxuICBcIkxvZ2ljYWxSZXNvdXJjZUlkXCI6XCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJQaHlzaWNhbFJlc291cmNlSWRcIjogXCIkbG9naWNhbFJlc291cmNlSWRcIixcbiAgXCJTdGF0dXNcIjogXCIkU1RBVFVTXCIsXG4gIFwiUmVhc29uXCI6IFwiJFJFQVNPTlwiLFxuICBcIkRhdGFcIjoge1xuICAgIFwiJHtlbnZGaWxlS2V5T3V0cHV0S2V5fVwiOiBcIiRlbnZGaWxlS2V5XCJcbiAgfVxufVxuRU9GXG5jdXJsIC1pIC1YIFBVVCAtSCAnQ29udGVudC1UeXBlOicgLWQgXCJAcGF5bG9hZC5qc29uXCIgXCIkcmVzcG9uc2VVUkxcIlxuICAgICAgICAgICAgICBgLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBoYW5kbGVyLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbJ2NvZGVidWlsZDpTdGFydEJ1aWxkJ10sXG4gICAgICAgIHJlc291cmNlczogW3Byb2plY3QucHJvamVjdEFybl0sXG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gcHJvamVjdC5ncmFudFByaW5jaXBhbDtcblxuICAgIHByb3BzLmRlc3RpbmF0aW9uQnVja2V0LmdyYW50UmVhZFdyaXRlKHByb2plY3QpO1xuICAgIGlmIChwcm9wcy5kaXN0cmlidXRpb24pIHtcbiAgICAgIHByb2plY3QuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbJ2Nsb3VkZnJvbnQ6R2V0SW52YWxpZGF0aW9uJywgJ2Nsb3VkZnJvbnQ6Q3JlYXRlSW52YWxpZGF0aW9uJ10sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbcHJvcHMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbkFybl0sXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbW1vbkV4Y2x1ZGUgPSBbJy5EU19TdG9yZScsICcuZ2l0JywgJ25vZGVfbW9kdWxlcyddO1xuICAgIGNvbnN0IGFzc2V0cyA9IHByb3BzLmFzc2V0cy5tYXAoKGFzc2V0UHJvcHMpID0+IHtcbiAgICAgIGNvbnN0IGFzc2V0ID0gbmV3IEFzc2V0KHRoaXMsIGBTb3VyY2UtJHthc3NldFByb3BzLnBhdGgucmVwbGFjZSgnLycsICcnKX1gLCB7XG4gICAgICAgIC4uLmFzc2V0UHJvcHMsXG4gICAgICAgIC4uLihwcm9wcy5leGNsdWRlQ29tbW9uRmlsZXMgPz8gdHJ1ZSA/IHsgZXhjbHVkZTogWy4uLmNvbW1vbkV4Y2x1ZGUsIC4uLihhc3NldFByb3BzLmV4Y2x1ZGUgPz8gW10pXSB9IDoge30pLFxuICAgICAgfSk7XG4gICAgICBhc3NldC5ncmFudFJlYWQocHJvamVjdCk7XG4gICAgICByZXR1cm4gYXNzZXQ7XG4gICAgfSk7XG5cbiAgICBjb25zdCBidWNrZXQgPSBhc3NldHNbMF0uYnVja2V0O1xuICAgIGlmIChvdXRwdXRFbnZGaWxlKSB7XG4gICAgICAvLyB1c2UgdGhlIGFzc2V0IGJ1Y2tldCB0aGF0IGFyZSBjcmVhdGVkIGJ5IENESyBib290c3RyYXAgdG8gc3RvcmUgLmVudiBmaWxlXG4gICAgICBidWNrZXQuZ3JhbnRXcml0ZShwcm9qZWN0KTtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2VzOiBOb2RlanNCdWlsZFJlc291cmNlUHJvcHNbJ3NvdXJjZXMnXSA9IHByb3BzLmFzc2V0cy5tYXAoKHMsIGkpID0+ICh7XG4gICAgICBzb3VyY2VCdWNrZXROYW1lOiBhc3NldHNbaV0uczNCdWNrZXROYW1lLFxuICAgICAgc291cmNlT2JqZWN0S2V5OiBhc3NldHNbaV0uczNPYmplY3RLZXksXG4gICAgICBleHRyYWN0UGF0aDogcy5leHRyYWN0UGF0aCA/PyBiYXNlbmFtZShzLnBhdGgpLFxuICAgICAgY29tbWFuZHM6IHMuY29tbWFuZHMsXG4gICAgfSkpO1xuXG4gICAgY29uc3Qgd29ya2luZ0RpcmVjdG9yeSA9IHByb3BzLndvcmtpbmdEaXJlY3RvcnkgPz8gc291cmNlc1swXS5leHRyYWN0UGF0aDtcbiAgICBjb25zdCBwcm9wZXJ0aWVzOiBOb2RlanNCdWlsZFJlc291cmNlUHJvcHMgPSB7XG4gICAgICB0eXBlOiAnTm9kZWpzQnVpbGQnLFxuICAgICAgc291cmNlcyxcbiAgICAgIGRlc3RpbmF0aW9uQnVja2V0TmFtZTogcHJvcHMuZGVzdGluYXRpb25CdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgIGRlc3RpbmF0aW9uS2V5UHJlZml4OiBwcm9wcy5kZXN0aW5hdGlvbktleVByZWZpeCA/PyAnLycsXG4gICAgICBkaXN0cmlidXRpb25JZDogcHJvcHMuZGlzdHJpYnV0aW9uPy5kaXN0cmlidXRpb25JZCxcbiAgICAgIGFzc2V0QnVja2V0TmFtZTogYnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICB3b3JraW5nRGlyZWN0b3J5LFxuICAgICAgLy8gam9pbiBwYXRocyBmb3IgQ29kZUJ1aWxkIChMaW51eCkgcGxhdGZvcm1cbiAgICAgIG91dHB1dFNvdXJjZURpcmVjdG9yeTogcG9zaXguam9pbih3b3JraW5nRGlyZWN0b3J5LCBwcm9wcy5vdXRwdXRTb3VyY2VEaXJlY3RvcnkpLFxuICAgICAgZW52aXJvbm1lbnQ6IHByb3BzLmJ1aWxkRW52aXJvbm1lbnQsXG4gICAgICBidWlsZENvbW1hbmRzOiBwcm9wcy5idWlsZENvbW1hbmRzID8/IFsnbnBtIHJ1biBidWlsZCddLFxuICAgICAgY29kZUJ1aWxkUHJvamVjdE5hbWU6IHByb2plY3QucHJvamVjdE5hbWUsXG4gICAgICBvdXRwdXRFbnZGaWxlLFxuICAgIH07XG5cbiAgICBjb25zdCBjdXN0b20gPSBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgc2VydmljZVRva2VuOiBoYW5kbGVyLmZ1bmN0aW9uQXJuLFxuICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpDREtOb2RlanNCdWlsZCcsXG4gICAgICBwcm9wZXJ0aWVzLFxuICAgIH0pO1xuICAgIGlmIChwcm9qZWN0LnJvbGUpIHtcbiAgICAgIGN1c3RvbS5ub2RlLmFkZERlcGVuZGVuY3kocHJvamVjdC5yb2xlKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMub3V0cHV0RW52RmlsZSkge1xuICAgICAgbmV3IENmbk91dHB1dCh0aGlzLCAnRG93bmxvYWRFbnZGaWxlJywgeyB2YWx1ZTogYGF3cyBzMyBjcCAke2J1Y2tldC5zM1VybEZvck9iamVjdChjdXN0b20uZ2V0QXR0U3RyaW5nKGVudkZpbGVLZXlPdXRwdXRLZXkpKX0gLmVudi5sb2NhbGAgfSk7XG4gICAgfVxuICB9XG59XG4iXX0=