UNPKG

projen

Version:

CDK for software projects

272 lines • 40.8 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.BuildWorkflow = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const component_1 = require("../component"); const github_1 = require("../github"); const constants_1 = require("../github/constants"); const util_1 = require("../github/private/util"); const workflow_actions_1 = require("../github/workflow-actions"); const workflows_model_1 = require("../github/workflows-model"); const javascript_1 = require("../javascript"); const runner_options_1 = require("../runner-options"); const consts_1 = require("./private/consts"); const name_1 = require("../util/name"); const path_1 = require("../util/path"); class BuildWorkflow extends component_1.Component { constructor(project, options) { super(project); this._postBuildJobs = []; const github = github_1.GitHub.of(this.project.root); if (!github) { throw new Error("BuildWorkflow is currently only supported for GitHub projects"); } this.github = github; this.preBuildSteps = options.preBuildSteps ?? []; this.postBuildSteps = options.postBuildSteps ?? []; this.gitIdentity = options.gitIdentity ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER; this.buildTask = options.buildTask; this.artifactsDirectory = options.artifactsDirectory ?? consts_1.DEFAULT_ARTIFACTS_DIRECTORY; (0, util_1.ensureNotHiddenPath)(this.artifactsDirectory, "artifactsDirectory"); this.name = options.name ?? (0, name_1.workflowNameForProject)("build", this.project); const mutableBuilds = options.mutableBuild ?? true; this.workflow = new github_1.GithubWorkflow(github, this.name); this.workflow.on(options.workflowTriggers ?? { pullRequest: {}, workflowDispatch: {}, // allow manual triggering }); this.addBuildJob(options); if (mutableBuilds) { this.addSelfMutationJob(options); } if (project instanceof javascript_1.NodeProject) { project.addPackageIgnore(constants_1.PERMISSION_BACKUP_FILE); } } addBuildJob(options) { const projectPathRelativeToRoot = path.relative(this.project.root.outdir, this.project.outdir); const jobConfig = { ...(0, runner_options_1.filteredRunsOnOptions)(options.runsOn, options.runsOnGroup), container: options.containerImage ? { image: options.containerImage } : undefined, env: { CI: "true", ...options.env, }, permissions: { contents: workflows_model_1.JobPermission.WRITE, ...options.permissions, }, defaults: this.project.parent // is subproject, ? { run: { workingDirectory: (0, path_1.ensureRelativePathStartsWithDot)(projectPathRelativeToRoot), }, } : undefined, steps: (() => this.renderBuildSteps(projectPathRelativeToRoot)), outputs: { [consts_1.SELF_MUTATION_HAPPENED_OUTPUT]: { stepId: consts_1.SELF_MUTATION_STEP, outputName: consts_1.SELF_MUTATION_HAPPENED_OUTPUT, }, }, }; this.workflow.addJob(consts_1.BUILD_JOBID, jobConfig); } /** * Returns a list of job IDs that are part of the build. */ get buildJobIds() { return [consts_1.BUILD_JOBID, ...this._postBuildJobs]; } /** * Adds steps that are executed after the build. * @param steps The job steps */ addPostBuildSteps(...steps) { this.postBuildSteps.push(...steps); } /** * Adds another job to the build workflow which is executed after the build * job succeeded. * * Jobs are executed _only_ if the build did NOT self mutate. If the build * self-mutate, the branch will either be updated or the build will fail (in * forks), so there is no point in executing the post-build job. * * @param id The id of the new job * @param job The job specification */ addPostBuildJob(id, job) { const steps = []; steps.push({ name: "Download build artifacts", uses: "actions/download-artifact@v5", with: { name: constants_1.BUILD_ARTIFACT_NAME, path: this.artifactsDirectory, }, }, { name: "Restore build artifact permissions", continueOnError: true, run: [ `cd ${this.artifactsDirectory} && setfacl --restore=${constants_1.PERMISSION_BACKUP_FILE}`, ].join("\n"), }); steps.push(...(job.steps ?? [])); this.workflow.addJob(id, { needs: [consts_1.BUILD_JOBID], // only run if build did not self-mutate if: `\${{ !${consts_1.SELF_MUTATION_CONDITION} }}`, ...job, steps: steps, }); // add to the list of build job IDs this._postBuildJobs.push(id); } /** * Run a task as a job within the build workflow which is executed after the * build job succeeded. * * The job will have access to build artifacts and will install project * dependencies in order to be able to run any commands used in the tasks. * * Jobs are executed _only_ if the build did NOT self mutate. If the build * self-mutate, the branch will either be updated or the build will fail (in * forks), so there is no point in executing the post-build job. * * @param options Specify tools and other options */ addPostBuildJobTask(task, options = {}) { this.addPostBuildJobCommands(`post-build-${task.name}`, [`${this.project.projenCommand} ${task.name}`], { checkoutRepo: true, installDeps: true, tools: options.tools, ...(0, runner_options_1.filteredRunsOnOptions)(options.runsOn, options.runsOnGroup), }); } /** * Run a sequence of commands as a job within the build workflow which is * executed after the build job succeeded. * * Jobs are executed _only_ if the build did NOT self mutate. If the build * self-mutate, the branch will either be updated or the build will fail (in * forks), so there is no point in executing the post-build job. * * @param options Specify tools and other options */ addPostBuildJobCommands(id, commands, options) { const steps = []; if (options?.checkoutRepo) { steps.push(github_1.WorkflowSteps.checkout({ with: { ref: consts_1.PULL_REQUEST_REF, repository: consts_1.PULL_REQUEST_REPOSITORY, ...(this.github.downloadLfs ? { lfs: true } : {}), }, })); } if (options?.checkoutRepo && options?.installDeps && this.project instanceof javascript_1.NodeProject) { steps.push({ name: "Install dependencies", run: `${this.project.package.installCommand}`, }); } steps.push({ run: commands.join("\n") }); this.addPostBuildJob(id, { permissions: { contents: workflows_model_1.JobPermission.READ, }, tools: options?.tools, ...(0, runner_options_1.filteredRunsOnOptions)(options?.runsOn, options?.runsOnGroup), steps, }); } addSelfMutationJob(options) { this.workflow.addJob("self-mutation", { ...(0, runner_options_1.filteredRunsOnOptions)(options.runsOn, options.runsOnGroup), permissions: { contents: workflows_model_1.JobPermission.WRITE, }, needs: [consts_1.BUILD_JOBID], if: `always() && ${consts_1.SELF_MUTATION_CONDITION} && ${consts_1.NOT_FORK}`, steps: [ ...this.workflow.projenCredentials.setupSteps, ...workflow_actions_1.WorkflowActions.checkoutWithPatch({ // we need to use a PAT so that our push will trigger the build workflow token: this.workflow.projenCredentials.tokenRef, ref: consts_1.PULL_REQUEST_REF, repository: consts_1.PULL_REQUEST_REPOSITORY, lfs: this.github.downloadLfs, }), github_1.WorkflowSteps.setupGitIdentity({ gitIdentity: this.gitIdentity }), { name: "Push changes", env: { PULL_REQUEST_REF: consts_1.PULL_REQUEST_REF, }, run: [ "git add .", 'git commit -s -m "chore: self mutation"', `git push origin "HEAD:$PULL_REQUEST_REF"`, ].join("\n"), }, ], }); } /** * Called (lazily) during synth to render the build job steps. */ renderBuildSteps(projectPathRelativeToRoot) { return [ github_1.WorkflowSteps.checkout({ with: { ref: consts_1.PULL_REQUEST_REF, repository: consts_1.PULL_REQUEST_REPOSITORY, ...(this.github.downloadLfs ? { lfs: true } : {}), }, }), ...this.preBuildSteps, { name: this.buildTask.name, run: this.github.project.runTaskCommand(this.buildTask), }, ...this.postBuildSteps, // check for mutations and upload a git patch file as an artifact ...workflow_actions_1.WorkflowActions.uploadGitPatch({ stepId: consts_1.SELF_MUTATION_STEP, outputName: consts_1.SELF_MUTATION_HAPPENED_OUTPUT, mutationError: "Files were changed during build (see build log). If this was triggered from a fork, you will need to update your branch.", }), // upload the build artifact only if we have post-build jobs (otherwise, there's no point) ...(this._postBuildJobs.length == 0 ? [] : [ { name: "Backup artifact permissions", continueOnError: true, run: `cd ${this.artifactsDirectory} && getfacl -R . > ${constants_1.PERMISSION_BACKUP_FILE}`, }, github_1.WorkflowSteps.uploadArtifact({ with: { name: constants_1.BUILD_ARTIFACT_NAME, path: this.project.parent ? `${projectPathRelativeToRoot}/${this.artifactsDirectory}` : this.artifactsDirectory, }, }), ]), ]; } } exports.BuildWorkflow = BuildWorkflow; _a = JSII_RTTI_SYMBOL_1; BuildWorkflow[_a] = { fqn: "projen.build.BuildWorkflow", version: "0.98.32" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtd29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYnVpbGQvYnVpbGQtd29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFFN0IsNENBQXlDO0FBQ3pDLHNDQU1tQjtBQUNuQixtREFJNkI7QUFDN0IsaURBQTZEO0FBQzdELGlFQUE2RDtBQUM3RCwrREFPbUM7QUFDbkMsOENBQTRDO0FBRTVDLHNEQUE4RTtBQUM5RSw2Q0FTMEI7QUFDMUIsdUNBQXNEO0FBQ3RELHVDQUErRDtBQWlHL0QsTUFBYSxhQUFjLFNBQVEscUJBQVM7SUFnQjFDLFlBQVksT0FBZ0IsRUFBRSxPQUE2QjtRQUN6RCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFIQSxtQkFBYyxHQUFhLEVBQUUsQ0FBQztRQUs3QyxNQUFNLE1BQU0sR0FBRyxlQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FDYiwrREFBK0QsQ0FDaEUsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLElBQUksRUFBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUM7UUFDbkQsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxJQUFJLHVDQUEyQixDQUFDO1FBQ3RFLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztRQUNuQyxJQUFJLENBQUMsa0JBQWtCO1lBQ3JCLE9BQU8sQ0FBQyxrQkFBa0IsSUFBSSxvQ0FBMkIsQ0FBQztRQUM1RCxJQUFBLDBCQUFtQixFQUFDLElB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LE9BQU8sQ0FBQyxNQUFNO2dDQUN2QixDQUFDLENBQUMsR0FBRyx5QkFBeUIsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7Z0NBQzNELENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCO3lCQUM1QjtxQkFDRixDQUFDO2lCQUNILENBQUM7U0FDUCxDQUFDO0lBQ0osQ0FBQzs7QUEvVEgsc0NBZ1VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgVGFzayB9IGZyb20gXCIuLlwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHtcbiAgR2l0SHViLFxuICBHaXRodWJXb3JrZmxvdyxcbiAgR2l0SWRlbnRpdHksXG4gIHdvcmtmbG93cyxcbiAgV29ya2Zsb3dTdGVwcyxcbn0gZnJvbSBcIi4uL2dpdGh1YlwiO1xuaW1wb3J0IHtcbiAgQlVJTERfQVJUSUZBQ1RfTkFNRSxcbiAgREVGQVVMVF9HSVRIVUJfQUNUSU9OU19VU0VSLFxuICBQRVJNSVNTSU9OX0JBQ0tVUF9GSUxFLFxufSBmcm9tIFwiLi4vZ2l0aHViL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZW5zdXJlTm90SGlkZGVuUGF0aCB9IGZyb20gXCIuLi9naXRodWIvcHJpdmF0ZS91dGlsXCI7XG5pbXBvcnQgeyBXb3JrZmxvd0FjdGlvbnMgfSBmcm9tIFwiLi4vZ2l0aHViL3dvcmtmbG93LWFjdGlvbnNcIjtcbmltcG9ydCB7XG4gIEpvYixcbiAgSm9iUGVybWlzc2lvbixcbiAgSm9iUGVybWlzc2lvbnMsXG4gIEpvYlN0ZXAsXG4gIFRvb2xzLFxuICBUcmlnZ2Vycyxcbn0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWxcIjtcbmltcG9ydCB7IE5vZGVQcm9qZWN0IH0gZnJvbSBcIi4uL2phdmFzY3JpcHRcIjtcbmltcG9ydCB7IFByb2plY3QgfSBmcm9tIFwiLi4vcHJvamVjdFwiO1xuaW1wb3J0IHsgR3JvdXBSdW5uZXJPcHRpb25zLCBmaWx0ZXJlZFJ1bnNPbk9wdGlvbnMgfSBmcm9tIFwiLi4vcnVubmVyLW9wdGlvbnNcIjtcbmltcG9ydCB7XG4gIEJVSUxEX0pPQklELFxuICBERUZBVUxUX0FSVElGQUNUU19ESVJFQ1RPUlksXG4gIE5PVF9GT1JLLFxuICBQVUxMX1JFUVVFU1RfUkVGLFxuICBQVUxMX1JFUVVFU1RfUkVQT1NJVE9SWSxcbiAgU0VMRl9NVVRBVElPTl9DT05ESVRJT04sXG4gIFNFTEZfTVVUQVRJT05fSEFQUEVORURfT1VUUFVULFxuICBTRUxGX01VVEFUSU9OX1NURVAsXG59IGZyb20gXCIuL3ByaXZhdGUvY29uc3RzXCI7XG5pbXBvcnQgeyB3b3JrZmxvd05hbWVGb3JQcm9qZWN0IH0gZnJvbSBcIi4uL3V0aWwvbmFtZVwiO1xuaW1wb3J0IHsgZW5zdXJlUmVsYXRpdmVQYXRoU3RhcnRzV2l0aERvdCB9IGZyb20gXCIuLi91dGlsL3BhdGhcIjtcblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZFdvcmtmbG93Q29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBidWlsZGZpbGUgKGUuZy4gXCJidWlsZFwiIGJlY29tZXMgXCJidWlsZC55bWxcIikuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiYnVpbGRcIlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogU3RlcHMgdG8gZXhlY3V0ZSBiZWZvcmUgdGhlIGJ1aWxkLlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcmVhZG9ubHkgcHJlQnVpbGRTdGVwcz86IEpvYlN0ZXBbXTtcblxuICAvKipcbiAgICogQnVpbGQgd29ya2Zsb3cgdHJpZ2dlcnNcbiAgICogQGRlZmF1bHQgXCJ7IHB1bGxSZXF1ZXN0OiB7fSwgd29ya2Zsb3dEaXNwYXRjaDoge30gfVwiXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd1RyaWdnZXJzPzogVHJpZ2dlcnM7XG5cbiAgLyoqXG4gICAqIFBlcm1pc3Npb25zIGdyYW50ZWQgdG8gdGhlIGJ1aWxkIGpvYlxuICAgKiBUbyBsaW1pdCBqb2IgcGVybWlzc2lvbnMgZm9yIGBjb250ZW50c2AsIHRoZSBkZXNpcmVkIHBlcm1pc3Npb25zIGhhdmUgdG8gYmUgZXhwbGljaXRseSBzZXQsIGUuZy46IGB7IGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLk5PTkUgfWBcbiAgICogQGRlZmF1bHQgYHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uV1JJVEUgfWBcbiAgICovXG4gIHJlYWRvbmx5IHBlcm1pc3Npb25zPzogSm9iUGVybWlzc2lvbnM7XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogQGRlZmF1bHQge31cbiAgICovXG4gIHJlYWRvbmx5IGVudj86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRXb3JrZmxvd09wdGlvbnMgZXh0ZW5kcyBCdWlsZFdvcmtmbG93Q29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgdGFzayB0byBleGVjdXRlIGluIG9yZGVyIHRvIGJ1aWxkIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRUYXNrOiBUYXNrO1xuXG4gIC8qKlxuICAgKiBBIG5hbWUgb2YgYSBkaXJlY3RvcnkgdGhhdCBpbmNsdWRlcyBidWlsZCBhcnRpZmFjdHMuXG4gICAqIEBkZWZhdWx0IFwiZGlzdFwiXG4gICAqL1xuICByZWFkb25seSBhcnRpZmFjdHNEaXJlY3Rvcnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjb250YWluZXIgaW1hZ2UgdG8gdXNlIGZvciBidWlsZHMuXG4gICAqIEBkZWZhdWx0IC0gdGhlIGRlZmF1bHQgd29ya2Zsb3cgY29udGFpbmVyXG4gICAqL1xuICByZWFkb25seSBjb250YWluZXJJbWFnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQXV0b21hdGljYWxseSB1cGRhdGUgZmlsZXMgbW9kaWZpZWQgZHVyaW5nIGJ1aWxkcyB0byBwdWxsLXJlcXVlc3QgYnJhbmNoZXMuXG4gICAqIFRoaXMgbWVhbnMgdGhhdCBhbnkgZmlsZXMgc3ludGhlc2l6ZWQgYnkgcHJvamVuIG9yIGUuZy4gdGVzdCBzbmFwc2hvdHMgd2lsbFxuICAgKiBhbHdheXMgYmUgdXAtdG8tZGF0ZSBiZWZvcmUgYSBQUiBpcyBtZXJnZWQuXG4gICAqXG4gICAqIEltcGxpZXMgdGhhdCBQUiBidWlsZHMgZG8gbm90IGhhdmUgYW50aS10YW1wZXIgY2hlY2tzLlxuICAgKlxuICAgKiBUaGlzIGlzIGVuYWJsZWQgYnkgZGVmYXVsdCBvbmx5IGlmIGBnaXRodWJUb2tlblNlY3JldGAgaXMgc2V0LiBPdGhlcndpc2UgaXRcbiAgICogaXMgZGlzYWJsZWQsIHdoaWNoIGltcGxpZXMgdGhhdCBmaWxlIGNoYW5nZXMgdGhhdCBoYXBwZW4gZHVyaW5nIGJ1aWxkIHdpbGxcbiAgICogbm90IGJlIHB1c2hlZCBiYWNrIHRvIHRoZSBicmFuY2guXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IG11dGFibGVCdWlsZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFN0ZXBzIHRvIGV4ZWN1dGUgYWZ0ZXIgYnVpbGQuXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBwb3N0QnVpbGRTdGVwcz86IEpvYlN0ZXBbXTtcblxuICAvKipcbiAgICogR2l0IGlkZW50aXR5IHRvIHVzZSBmb3IgdGhlIHdvcmtmbG93LlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgR2l0SHViIEFjdGlvbnMgdXNlclxuICAgKi9cbiAgcmVhZG9ubHkgZ2l0SWRlbnRpdHk/OiBHaXRJZGVudGl0eTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBzZWxlY3Rpb24gbGFiZWxzXG4gICAqIEBkZWZhdWx0IFtcInVidW50dS1sYXRlc3RcIl1cbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIGJ5IGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBydW5zT24/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBHcm91cCBzZWxlY3Rpb24gb3B0aW9uc1xuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgR3JvdXAgYnkgbmFtZSBhbmQvb3IgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbkdyb3VwPzogR3JvdXBSdW5uZXJPcHRpb25zO1xufVxuXG5leHBvcnQgY2xhc3MgQnVpbGRXb3JrZmxvdyBleHRlbmRzIENvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIGdlbmVyYXRlZCBnaXRodWIgd29ya2Zsb3dcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwb3N0QnVpbGRTdGVwczogSm9iU3RlcFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHByZUJ1aWxkU3RlcHM6IEpvYlN0ZXBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBnaXRJZGVudGl0eTogR2l0SWRlbnRpdHk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVpbGRUYXNrOiBUYXNrO1xuICBwcml2YXRlIHJlYWRvbmx5IGdpdGh1YjogR2l0SHViO1xuICBwcml2YXRlIHJlYWRvbmx5IHdvcmtmbG93OiBHaXRodWJXb3JrZmxvdztcbiAgcHJpdmF0ZSByZWFkb25seSBhcnRpZmFjdHNEaXJlY3Rvcnk6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IF9wb3N0QnVpbGRKb2JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IEJ1aWxkV29ya2Zsb3dPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICBjb25zdCBnaXRodWIgPSBHaXRIdWIub2YodGhpcy5wcm9qZWN0LnJvb3QpO1xuICAgIGlmICghZ2l0aHViKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQnVpbGRXb3JrZmxvdyBpcyBjdXJyZW50bHkgb25seSBzdXBwb3J0ZWQgZm9yIEdpdEh1YiBwcm9qZWN0c1wiXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuZ2l0aHViID0gZ2l0aHViO1xuICAgIHRoaXMucHJlQnVpbGRTdGVwcyA9IG9wdGlvbnMucHJlQnVpbGRTdGVwcyA/PyBbXTtcbiAgICB0aGlzLnBvc3RCdWlsZFN0ZXBzID0gb3B0aW9ucy5wb3N0QnVpbGRTdGVwcyA/PyBbXTtcbiAgICB0aGlzLmdpdElkZW50aXR5ID0gb3B0aW9ucy5naXRJZGVudGl0eSA/PyBERUZBVUxUX0dJVEhVQl9BQ1RJT05TX1VTRVI7XG4gICAgdGhpcy5idWlsZFRhc2sgPSBvcHRpb25zLmJ1aWxkVGFzaztcbiAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSA9XG4gICAgICBvcHRpb25zLmFydGlmYWN0c0RpcmVjdG9yeSA/PyBERUZBVUxUX0FSVElGQUNUU19ESVJFQ1RPUlk7XG4gICAgZW5zdXJlTm90SGlkZGVuUGF0aCh0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSwgXCJhcnRpZmFjdHNEaXJlY3RvcnlcIik7XG4gICAgdGhpcy5uYW1lID0gb3B0aW9ucy5uYW1lID8/IHdvcmtmbG93TmFtZUZvclByb2plY3QoXCJidWlsZFwiLCB0aGlzLnByb2plY3QpO1xuICAgIGNvbnN0IG11dGFibGVCdWlsZHMgPSBvcHRpb25zLm11dGFibGVCdWlsZCA/PyB0cnVlO1xuXG4gICAgdGhpcy53b3JrZmxvdyA9IG5ldyBHaXRodWJXb3JrZmxvdyhnaXRodWIsIHRoaXMubmFtZSk7XG4gICAgdGhpcy53b3JrZmxvdy5vbihcbiAgICAgIG9wdGlvbnMud29ya2Zsb3dUcmlnZ2VycyA/PyB7XG4gICAgICAgIHB1bGxSZXF1ZXN0OiB7fSxcbiAgICAgICAgd29ya2Zsb3dEaXNwYXRjaDoge30sIC8vIGFsbG93IG1hbnVhbCB0cmlnZ2VyaW5nXG4gICAgICB9XG4gICAgKTtcblxuICAgIHRoaXMuYWRkQnVpbGRKb2Iob3B0aW9ucyk7XG5cbiAgICBpZiAobXV0YWJsZUJ1aWxkcykge1xuICAgICAgdGhpcy5hZGRTZWxmTXV0YXRpb25Kb2Iob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKHByb2plY3QgaW5zdGFuY2VvZiBOb2RlUHJvamVjdCkge1xuICAgICAgcHJvamVjdC5hZGRQYWNrYWdlSWdub3JlKFBFUk1JU1NJT05fQkFDS1VQX0ZJTEUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYWRkQnVpbGRKb2Iob3B0aW9uczogQnVpbGRXb3JrZmxvd09wdGlvbnMpIHtcbiAgICBjb25zdCBwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290ID0gcGF0aC5yZWxhdGl2ZShcbiAgICAgIHRoaXMucHJvamVjdC5yb290Lm91dGRpcixcbiAgICAgIHRoaXMucHJvamVjdC5vdXRkaXJcbiAgICApO1xuICAgIGNvbnN0IGpvYkNvbmZpZzogd29ya2Zsb3dzLkpvYiA9IHtcbiAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyhvcHRpb25zLnJ1bnNPbiwgb3B0aW9ucy5ydW5zT25Hcm91cCksXG4gICAgICBjb250YWluZXI6IG9wdGlvbnMuY29udGFpbmVySW1hZ2VcbiAgICAgICAgPyB7IGltYWdlOiBvcHRpb25zLmNvbnRhaW5lckltYWdlIH1cbiAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBlbnY6IHtcbiAgICAgICAgQ0k6IFwidHJ1ZVwiLFxuICAgICAgICAuLi5vcHRpb25zLmVudixcbiAgICAgIH0sXG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgICAgLi4ub3B0aW9ucy5wZXJtaXNzaW9ucyxcbiAgICAgIH0sXG4gICAgICBkZWZhdWx0czogdGhpcy5wcm9qZWN0LnBhcmVudCAvLyBpcyBzdWJwcm9qZWN0LFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHJ1bjoge1xuICAgICAgICAgICAgICB3b3JraW5nRGlyZWN0b3J5OiBlbnN1cmVSZWxhdGl2ZVBhdGhTdGFydHNXaXRoRG90KFxuICAgICAgICAgICAgICAgIHByb2plY3RQYXRoUmVsYXRpdmVUb1Jvb3RcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIHN0ZXBzOiAoKCkgPT4gdGhpcy5yZW5kZXJCdWlsZFN0ZXBzKHByb2plY3RQYXRoUmVsYXRpdmVUb1Jvb3QpKSBhcyBhbnksXG4gICAgICBvdXRwdXRzOiB7XG4gICAgICAgIFtTRUxGX01VVEFUSU9OX0hBUFBFTkVEX09VVFBVVF06IHtcbiAgICAgICAgICBzdGVwSWQ6IFNFTEZfTVVUQVRJT05fU1RFUCxcbiAgICAgICAgICBvdXRwdXROYW1lOiBTRUxGX01VVEFUSU9OX0hBUFBFTkVEX09VVFBVVCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIHRoaXMud29ya2Zsb3cuYWRkSm9iKEJVSUxEX0pPQklELCBqb2JDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGpvYiBJRHMgdGhhdCBhcmUgcGFydCBvZiB0aGUgYnVpbGQuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGJ1aWxkSm9iSWRzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW0JVSUxEX0pPQklELCAuLi50aGlzLl9wb3N0QnVpbGRKb2JzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHN0ZXBzIHRoYXQgYXJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBidWlsZC5cbiAgICogQHBhcmFtIHN0ZXBzIFRoZSBqb2Igc3RlcHNcbiAgICovXG4gIHB1YmxpYyBhZGRQb3N0QnVpbGRTdGVwcyguLi5zdGVwczogSm9iU3RlcFtdKTogdm9pZCB7XG4gICAgdGhpcy5wb3N0QnVpbGRTdGVwcy5wdXNoKC4uLnN0ZXBzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFub3RoZXIgam9iIHRvIHRoZSBidWlsZCB3b3JrZmxvdyB3aGljaCBpcyBleGVjdXRlZCBhZnRlciB0aGUgYnVpbGRcbiAgICogam9iIHN1Y2NlZWRlZC5cbiAgICpcbiAgICogSm9icyBhcmUgZXhlY3V0ZWQgX29ubHlfIGlmIHRoZSBidWlsZCBkaWQgTk9UIHNlbGYgbXV0YXRlLiBJZiB0aGUgYnVpbGRcbiAgICogc2VsZi1tdXRhdGUsIHRoZSBicmFuY2ggd2lsbCBlaXRoZXIgYmUgdXBkYXRlZCBvciB0aGUgYnVpbGQgd2lsbCBmYWlsIChpblxuICAgKiBmb3JrcyksIHNvIHRoZXJlIGlzIG5vIHBvaW50IGluIGV4ZWN1dGluZyB0aGUgcG9zdC1idWlsZCBqb2IuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIG5ldyBqb2JcbiAgICogQHBhcmFtIGpvYiBUaGUgam9iIHNwZWNpZmljYXRpb25cbiAgICovXG4gIHB1YmxpYyBhZGRQb3N0QnVpbGRKb2IoaWQ6IHN0cmluZywgam9iOiBKb2IpIHtcbiAgICBjb25zdCBzdGVwcyA9IFtdO1xuXG4gICAgc3RlcHMucHVzaChcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJEb3dubG9hZCBidWlsZCBhcnRpZmFjdHNcIixcbiAgICAgICAgdXNlczogXCJhY3Rpb25zL2Rvd25sb2FkLWFydGlmYWN0QHY1XCIsXG4gICAgICAgIHdpdGg6IHtcbiAgICAgICAgICBuYW1lOiBCVUlMRF9BUlRJRkFDVF9OQU1FLFxuICAgICAgICAgIHBhdGg6IHRoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJSZXN0b3JlIGJ1aWxkIGFydGlmYWN0IHBlcm1pc3Npb25zXCIsXG4gICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSxcbiAgICAgICAgcnVuOiBbXG4gICAgICAgICAgYGNkICR7dGhpcy5hcnRpZmFjdHNEaXJlY3Rvcnl9ICYmIHNldGZhY2wgLS1yZXN0b3JlPSR7UEVSTUlTU0lPTl9CQUNLVVBfRklMRX1gLFxuICAgICAgICBdLmpvaW4oXCJcXG5cIiksXG4gICAgICB9XG4gICAgKTtcblxuICAgIHN0ZXBzLnB1c2goLi4uKGpvYi5zdGVwcyA/PyBbXSkpO1xuXG4gICAgdGhpcy53b3JrZmxvdy5hZGRKb2IoaWQsIHtcbiAgICAgIG5lZWRzOiBbQlVJTERfSk9CSURdLFxuICAgICAgLy8gb25seSBydW4gaWYgYnVpbGQgZGlkIG5vdCBzZWxmLW11dGF0ZVxuICAgICAgaWY6IGBcXCR7eyAhJHtTRUxGX01VVEFUSU9OX0NPTkRJVElPTn0gfX1gLFxuICAgICAgLi4uam9iLFxuICAgICAgc3RlcHM6IHN0ZXBzLFxuICAgIH0pO1xuXG4gICAgLy8gYWRkIHRvIHRoZSBsaXN0IG9mIGJ1aWxkIGpvYiBJRHNcbiAgICB0aGlzLl9wb3N0QnVpbGRKb2JzLnB1c2goaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1biBhIHRhc2sgYXMgYSBqb2Igd2l0aGluIHRoZSBidWlsZCB3b3JrZmxvdyB3aGljaCBpcyBleGVjdXRlZCBhZnRlciB0aGVcbiAgICogYnVpbGQgam9iIHN1Y2NlZWRlZC5cbiAgICpcbiAgICogVGhlIGpvYiB3aWxsIGhhdmUgYWNjZXNzIHRvIGJ1aWxkIGFydGlmYWN0cyBhbmQgd2lsbCBpbnN0YWxsIHByb2plY3RcbiAgICogZGVwZW5kZW5jaWVzIGluIG9yZGVyIHRvIGJlIGFibGUgdG8gcnVuIGFueSBjb21tYW5kcyB1c2VkIGluIHRoZSB0YXNrcy5cbiAgICpcbiAgICogSm9icyBhcmUgZXhlY3V0ZWQgX29ubHlfIGlmIHRoZSBidWlsZCBkaWQgTk9UIHNlbGYgbXV0YXRlLiBJZiB0aGUgYnVpbGRcbiAgICogc2VsZi1tdXRhdGUsIHRoZSBicmFuY2ggd2lsbCBlaXRoZXIgYmUgdXBkYXRlZCBvciB0aGUgYnVpbGQgd2lsbCBmYWlsIChpblxuICAgKiBmb3JrcyksIHNvIHRoZXJlIGlzIG5vIHBvaW50IGluIGV4ZWN1dGluZyB0aGUgcG9zdC1idWlsZCBqb2IuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIFNwZWNpZnkgdG9vbHMgYW5kIG90aGVyIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhZGRQb3N0QnVpbGRKb2JUYXNrKFxuICAgIHRhc2s6IFRhc2ssXG4gICAgb3B0aW9uczogQWRkUG9zdEJ1aWxkSm9iVGFza09wdGlvbnMgPSB7fVxuICApIHtcbiAgICB0aGlzLmFkZFBvc3RCdWlsZEpvYkNvbW1hbmRzKFxuICAgICAgYHBvc3QtYnVpbGQtJHt0YXNrLm5hbWV9YCxcbiAgICAgIFtgJHt0aGlzLnByb2plY3QucHJvamVuQ29tbWFuZH0gJHt0YXNrLm5hbWV9YF0sXG4gICAgICB7XG4gICAgICAgIGNoZWNrb3V0UmVwbzogdHJ1ZSxcbiAgICAgICAgaW5zdGFsbERlcHM6IHRydWUsXG4gICAgICAgIHRvb2xzOiBvcHRpb25zLnRvb2xzLFxuICAgICAgICAuLi5maWx0ZXJlZFJ1bnNPbk9wdGlvbnMob3B0aW9ucy5ydW5zT24sIG9wdGlvbnMucnVuc09uR3JvdXApLFxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUnVuIGEgc2VxdWVuY2Ugb2YgY29tbWFuZHMgYXMgYSBqb2Igd2l0aGluIHRoZSBidWlsZCB3b3JrZmxvdyB3aGljaCBpc1xuICAgKiBleGVjdXRlZCBhZnRlciB0aGUgYnVpbGQgam9iIHN1Y2NlZWRlZC5cbiAgICpcbiAgICogSm9icyBhcmUgZXhlY3V0ZWQgX29ubHlfIGlmIHRoZSBidWlsZCBkaWQgTk9UIHNlbGYgbXV0YXRlLiBJZiB0aGUgYnVpbGRcbiAgICogc2VsZi1tdXRhdGUsIHRoZSBicmFuY2ggd2lsbCBlaXRoZXIgYmUgdXBkYXRlZCBvciB0aGUgYnVpbGQgd2lsbCBmYWlsIChpblxuICAgKiBmb3JrcyksIHNvIHRoZXJlIGlzIG5vIHBvaW50IGluIGV4ZWN1dGluZyB0aGUgcG9zdC1idWlsZCBqb2IuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIFNwZWNpZnkgdG9vbHMgYW5kIG90aGVyIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhZGRQb3N0QnVpbGRKb2JDb21tYW5kcyhcbiAgICBpZDogc3RyaW5nLFxuICAgIGNvbW1hbmRzOiBzdHJpbmdbXSxcbiAgICBvcHRpb25zPzogQWRkUG9zdEJ1aWxkSm9iQ29tbWFuZHNPcHRpb25zXG4gICkge1xuICAgIGNvbnN0IHN0ZXBzID0gW107XG5cbiAgICBpZiAob3B0aW9ucz8uY2hlY2tvdXRSZXBvKSB7XG4gICAgICBzdGVwcy5wdXNoKFxuICAgICAgICBXb3JrZmxvd1N0ZXBzLmNoZWNrb3V0KHtcbiAgICAgICAgICB3aXRoOiB7XG4gICAgICAgICAgICByZWY6IFBVTExfUkVRVUVTVF9SRUYsXG4gICAgICAgICAgICByZXBvc2l0b3J5OiBQVUxMX1JFUVVFU1RfUkVQT1NJVE9SWSxcbiAgICAgICAgICAgIC4uLih0aGlzLmdpdGh1Yi5kb3dubG9hZExmcyA/IHsgbGZzOiB0cnVlIH0gOiB7fSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgb3B0aW9ucz8uY2hlY2tvdXRSZXBvICYmXG4gICAgICBvcHRpb25zPy5pbnN0YWxsRGVwcyAmJlxuICAgICAgdGhpcy5wcm9qZWN0IGluc3RhbmNlb2YgTm9kZVByb2plY3RcbiAgICApIHtcbiAgICAgIHN0ZXBzLnB1c2goe1xuICAgICAgICBuYW1lOiBcIkluc3RhbGwgZGVwZW5kZW5jaWVzXCIsXG4gICAgICAgIHJ1bjogYCR7dGhpcy5wcm9qZWN0LnBhY2thZ2UuaW5zdGFsbENvbW1hbmR9YCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN0ZXBzLnB1c2goeyBydW46IGNvbW1hbmRzLmpvaW4oXCJcXG5cIikgfSk7XG5cbiAgICB0aGlzLmFkZFBvc3RCdWlsZEpvYihpZCwge1xuICAgICAgcGVybWlzc2lvbnM6IHtcbiAgICAgICAgY29udGVudHM6IEpvYlBlcm1pc3Npb24uUkVBRCxcbiAgICAgIH0sXG4gICAgICB0b29sczogb3B0aW9ucz8udG9vbHMsXG4gICAgICAuLi5maWx0ZXJlZFJ1bnNPbk9wdGlvbnMob3B0aW9ucz8ucnVuc09uLCBvcHRpb25zPy5ydW5zT25Hcm91cCksXG4gICAgICBzdGVwcyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkU2VsZk11dGF0aW9uSm9iKG9wdGlvbnM6IEJ1aWxkV29ya2Zsb3dPcHRpb25zKSB7XG4gICAgdGhpcy53b3JrZmxvdy5hZGRKb2IoXCJzZWxmLW11dGF0aW9uXCIsIHtcbiAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyhvcHRpb25zLnJ1bnNPbiwgb3B0aW9ucy5ydW5zT25Hcm91cCksXG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgIH0sXG4gICAgICBuZWVkczogW0JVSUxEX0pPQklEXSxcbiAgICAgIGlmOiBgYWx3YXlzKCkgJiYgJHtTRUxGX01VVEFUSU9OX0NPTkRJVElPTn0gJiYgJHtOT1RfRk9SS31gLFxuICAgICAgc3RlcHM6IFtcbiAgICAgICAgLi4udGhpcy53b3JrZmxvdy5wcm9qZW5DcmVkZW50aWFscy5zZXR1cFN0ZXBzLFxuICAgICAgICAuLi5Xb3JrZmxvd0FjdGlvbnMuY2hlY2tvdXRXaXRoUGF0Y2goe1xuICAgICAgICAgIC8vIHdlIG5lZWQgdG8gdXNlIGEgUEFUIHNvIHRoYXQgb3VyIHB1c2ggd2lsbCB0cmlnZ2VyIHRoZSBidWlsZCB3b3JrZmxvd1xuICAgICAgICAgIHRva2VuOiB0aGlzLndvcmtmbG93LnByb2plbkNyZWRlbnRpYWxzLnRva2VuUmVmLFxuICAgICAgICAgIHJlZjogUFVMTF9SRVFVRVNUX1JFRixcbiAgICAgICAgICByZXBvc2l0b3J5OiBQVUxMX1JFUVVFU1RfUkVQT1NJVE9SWSxcbiAgICAgICAgICBsZnM6IHRoaXMuZ2l0aHViLmRvd25sb2FkTGZzLFxuICAgICAgICB9KSxcbiAgICAgICAgV29ya2Zsb3dTdGVwcy5zZXR1cEdpdElkZW50aXR5KHsgZ2l0SWRlbnRpdHk6IHRoaXMuZ2l0SWRlbnRpdHkgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcIlB1c2ggY2hhbmdlc1wiLFxuICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgUFVMTF9SRVFVRVNUX1JFRixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgXCJnaXQgYWRkIC5cIixcbiAgICAgICAgICAgICdnaXQgY29tbWl0IC1zIC1tIFwiY2hvcmU6IHNlbGYgbXV0YXRpb25cIicsXG4gICAgICAgICAgICBgZ2l0IHB1c2ggb3JpZ2luIFwiSEVBRDokUFVMTF9SRVFVRVNUX1JFRlwiYCxcbiAgICAgICAgICBdLmpvaW4oXCJcXG5cIiksXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCAobGF6aWx5KSBkdXJpbmcgc3ludGggdG8gcmVuZGVyIHRoZSBidWlsZCBqb2Igc3RlcHMuXG4gICAqL1xuICBwcml2YXRlIHJlbmRlckJ1aWxkU3RlcHMocHJvamVjdFBhdGhSZWxhdGl2ZVRvUm9vdDogc3RyaW5nKTogSm9iU3RlcFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgV29ya2Zsb3dTdGVwcy5jaGVja291dCh7XG4gICAgICAgIHdpdGg6IHtcbiAgICAgICAgICByZWY6IFBVTExfUkVRVUVTVF9SRUYsXG4gICAgICAgICAgcmVwb3NpdG9yeTogUFVMTF9SRVFVRVNUX1JFUE9TSVRPUlksXG4gICAgICAgICAgLi4uKHRoaXMuZ2l0aHViLmRvd25sb2FkTGZzID8geyBsZnM6IHRydWUgfSA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuXG4gICAgICAuLi50aGlzLnByZUJ1aWxkU3RlcHMsXG5cbiAgICAgIHtcbiAgICAgICAgbmFtZTogdGhpcy5idWlsZFRhc2submFtZSxcbiAgICAgICAgcnVuOiB0aGlzLmdpdGh1Yi5wcm9qZWN0LnJ1blRhc2tDb21tYW5kKHRoaXMuYnVpbGRUYXNrKSxcbiAgICAgIH0sXG5cbiAgICAgIC4uLnRoaXMucG9zdEJ1aWxkU3RlcHMsXG5cbiAgICAgIC8vIGNoZWNrIGZvciBtdXRhdGlvbnMgYW5kIHVwbG9hZCBhIGdpdCBwYXRjaCBmaWxlIGFzIGFuIGFydGlmYWN0XG4gICAgICAuLi5Xb3JrZmxvd0FjdGlvbnMudXBsb2FkR2l0UGF0Y2goe1xuICAgICAgICBzdGVwSWQ6IFNFTEZfTVVUQVRJT05fU1RFUCxcbiAgICAgICAgb3V0cHV0TmFtZTogU0VMRl9NVVRBVElPTl9IQVBQRU5FRF9PVVRQVVQsXG4gICAgICAgIG11dGF0aW9uRXJyb3I6XG4gICAgICAgICAgXCJGaWxlcyB3ZXJlIGNoYW5nZWQgZHVyaW5nIGJ1aWxkIChzZWUgYnVpbGQgbG9nKS4gSWYgdGhpcyB3YXMgdHJpZ2dlcmVkIGZyb20gYSBmb3JrLCB5b3Ugd2lsbCBuZWVkIHRvIHVwZGF0ZSB5b3VyIGJyYW5jaC5cIixcbiAgICAgIH0pLFxuXG4gICAgICAvLyB1cGxvYWQgdGhlIGJ1aWxkIGFydGlmYWN0IG9ubHkgaWYgd2UgaGF2ZSBwb3N0LWJ1aWxkIGpvYnMgKG90aGVyd2lzZSwgdGhlcmUncyBubyBwb2ludClcbiAgICAgIC4uLih0aGlzLl9wb3N0QnVpbGRKb2JzLmxlbmd0aCA9PSAwXG4gICAgICAgID8gW11cbiAgICAgICAgOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG5hbWU6IFwiQmFja3VwIGFydGlmYWN0IHBlcm1pc3Npb25zXCIsXG4gICAgICAgICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSxcbiAgICAgICAgICAgICAgcnVuOiBgY2QgJHt0aGlzLmFydGlmYWN0c0RpcmVjdG9yeX0gJiYgZ2V0ZmFjbCAtUiAuID4gJHtQRVJNSVNTSU9OX0JBQ0tVUF9GSUxFfWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgV29ya2Zsb3dTdGVwcy51cGxvYWRBcnRpZmFjdCh7XG4gICAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiBCVUlMRF9BUlRJRkFDVF9OQU1FLFxuICAgICAgICAgICAgICAgIHBhdGg6IHRoaXMucHJvamVjdC5wYXJlbnRcbiAgICAgICAgICAgICAgICAgID8gYCR7cHJvamVjdFBhdGhSZWxhdGl2ZVRvUm9vdH0vJHt0aGlzLmFydGlmYWN0c0RpcmVjdG9yeX1gXG4gICAgICAgICAgICAgICAgICA6IHRoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgXSksXG4gICAgXTtcbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBCdWlsZFdvcmtmbG93LmFkZFBvc3RCdWlsZEpvYlRhc2tgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkUG9zdEJ1aWxkSm9iVGFza09wdGlvbnMge1xuICAvKipcbiAgICogVG9vbHMgdGhhdCBzaG91bGQgYmUgaW5zdGFsbGVkIGJlZm9yZSB0aGUgdGFzayBpcyBydW4uXG4gICAqL1xuICByZWFkb25seSB0b29scz86IFRvb2xzO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIHNlbGVjdGlvbiBsYWJlbHNcbiAgICogQGRlZmF1bHQgW1widWJ1bnR1LWxhdGVzdFwiXVxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgYnkgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIEdyb3VwIHNlbGVjdGlvbiBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIGEgdGFyZ2V0IFJ1bm5lciBHcm91cCBieSBuYW1lIGFuZC9vciBsYWJlbHNcbiAgICogQHRocm93cyB7RXJyb3J9IGlmIGJvdGggYHJ1bnNPbmAgYW5kIGBydW5zT25Hcm91cGAgYXJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgcnVuc09uR3JvdXA/OiBHcm91cFJ1bm5lck9wdGlvbnM7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYEJ1aWxkV29ya2Zsb3cuYWRkUG9zdEJ1aWxkSm9iQ29tbWFuZHNgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkUG9zdEJ1aWxkSm9iQ29tbWFuZHNPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRvb2xzIHRoYXQgc2hvdWxkIGJlIGluc3RhbGxlZCBiZWZvcmUgdGhlIGNvbW1hbmRzIGFyZSBydW4uXG4gICAqL1xuICByZWFkb25seSB0b29scz86IFRvb2xzO1xuXG4gIC8qKlxuICAgKiBDaGVjayBvdXQgdGhlIHJlcG9zaXRvcnkgYXQgdGhlIHB1bGwgcmVxdWVzdCBicmFuY2ggYmVmb3JlIGNvbW1hbmRzIGFyZVxuICAgKiBydW4uXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjaGVja291dFJlcG8/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbnN0YWxsIHByb2plY3QgZGVwZW5kZW5jaWVzIGJlZm9yZSBydW5uaW5nIGNvbW1hbmRzLiBgY2hlY2tvdXRSZXBvYCBtdXN0XG4gICAqIGFsc28gYmUgc2V0IHRvIHRydWUuXG4gICAqXG4gICAqIEN1cnJlbnRseSBvbmx5IHN1cHBvcnRlZCBmb3IgYE5vZGVQcm9qZWN0YC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGluc3RhbGxEZXBzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBzZWxlY3Rpb24gbGFiZWxzXG4gICAqIEBkZWZhdWx0IFtcInVidW50dS1sYXRlc3RcIl1cbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIGJ5IGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBydW5zT24/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBHcm91cCBzZWxlY3Rpb24gb3B0aW9uc1xuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgR3JvdXAgYnkgbmFtZSBhbmQvb3IgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbkdyb3VwPzogR3JvdXBSdW5uZXJPcHRpb25zO1xufVxuIl19