UNPKG

projen

Version:

CDK for software projects

271 lines • 40.6 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 posixPath = require("node:path/posix"); 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"); 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 = (0, util_1.projectPathRelativeToRepoRoot)(this.project); 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: 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 ? posixPath.join(projectPathRelativeToRoot, this.artifactsDirectory) : this.artifactsDirectory, }, }), ]), ]; } } exports.BuildWorkflow = BuildWorkflow; _a = JSII_RTTI_SYMBOL_1; BuildWorkflow[_a] = { fqn: "projen.build.BuildWorkflow", version: "0.99.3" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtd29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYnVpbGQvYnVpbGQtd29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBNkM7QUFFN0MsNENBQXlDO0FBQ3pDLHNDQU1tQjtBQUNuQixtREFJNkI7QUFDN0IsaURBR2dDO0FBQ2hDLGlFQUE2RDtBQUM3RCwrREFPbUM7QUFDbkMsOENBQTRDO0FBRTVDLHNEQUE4RTtBQUM5RSw2Q0FTMEI7QUFDMUIsdUNBQXNEO0FBaUd0RCxNQUFhLGFBQWMsU0FBUSxxQkFBUztJQWdCMUMsWUFBWSxPQUFnQixFQUFFLE9BQTZCO1FBQ3pELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUhBLG1CQUFjLEdBQWEsRUFBRSxDQUFDO1FBSzdDLE1BQU0sTUFBTSxHQUFHLGVBQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksS0FBSyxDQUNiLCtEQUErRCxDQUNoRSxDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUM7UUFDakQsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQztRQUNuRCxJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxXQUFXLElBQUksdUNBQTJCLENBQUM7UUFDdEUsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1FBQ25DLElBQUksQ0FBQyxrQkFBa0I7WUFDckIsT0FBTyxDQUFDLGtCQUFrQixJQUFJLG9DQUEyQixDQUFDO1FBQzVELElBQUEsMEJBQW1CLEVBQUMsSUFBSSxDQUFDLGtCQUFr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QUNILENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCO3lCQUM1QjtxQkFDRixDQUFDO2lCQUNILENBQUM7U0FDUCxDQUFDO0lBQ0osQ0FBQzs7QUEvVEgsc0NBZ1VDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcG9zaXhQYXRoIGZyb20gXCJub2RlOnBhdGgvcG9zaXhcIjtcbmltcG9ydCB7IFRhc2sgfSBmcm9tIFwiLi5cIjtcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnRcIjtcbmltcG9ydCB7XG4gIEdpdEh1YixcbiAgR2l0aHViV29ya2Zsb3csXG4gIEdpdElkZW50aXR5LFxuICB3b3JrZmxvd3MsXG4gIFdvcmtmbG93U3RlcHMsXG59IGZyb20gXCIuLi9naXRodWJcIjtcbmltcG9ydCB7XG4gIEJVSUxEX0FSVElGQUNUX05BTUUsXG4gIERFRkFVTFRfR0lUSFVCX0FDVElPTlNfVVNFUixcbiAgUEVSTUlTU0lPTl9CQUNLVVBfRklMRSxcbn0gZnJvbSBcIi4uL2dpdGh1Yi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIGVuc3VyZU5vdEhpZGRlblBhdGgsXG4gIHByb2plY3RQYXRoUmVsYXRpdmVUb1JlcG9Sb290LFxufSBmcm9tIFwiLi4vZ2l0aHViL3ByaXZhdGUvdXRpbFwiO1xuaW1wb3J0IHsgV29ya2Zsb3dBY3Rpb25zIH0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvdy1hY3Rpb25zXCI7XG5pbXBvcnQge1xuICBKb2IsXG4gIEpvYlBlcm1pc3Npb24sXG4gIEpvYlBlcm1pc3Npb25zLFxuICBKb2JTdGVwLFxuICBUb29scyxcbiAgVHJpZ2dlcnMsXG59IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3dzLW1vZGVsXCI7XG5pbXBvcnQgeyBOb2RlUHJvamVjdCB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBQcm9qZWN0IH0gZnJvbSBcIi4uL3Byb2plY3RcIjtcbmltcG9ydCB7IEdyb3VwUnVubmVyT3B0aW9ucywgZmlsdGVyZWRSdW5zT25PcHRpb25zIH0gZnJvbSBcIi4uL3J1bm5lci1vcHRpb25zXCI7XG5pbXBvcnQge1xuICBCVUlMRF9KT0JJRCxcbiAgREVGQVVMVF9BUlRJRkFDVFNfRElSRUNUT1JZLFxuICBOT1RfRk9SSyxcbiAgUFVMTF9SRVFVRVNUX1JFRixcbiAgUFVMTF9SRVFVRVNUX1JFUE9TSVRPUlksXG4gIFNFTEZfTVVUQVRJT05fQ09ORElUSU9OLFxuICBTRUxGX01VVEFUSU9OX0hBUFBFTkVEX09VVFBVVCxcbiAgU0VMRl9NVVRBVElPTl9TVEVQLFxufSBmcm9tIFwiLi9wcml2YXRlL2NvbnN0c1wiO1xuaW1wb3J0IHsgd29ya2Zsb3dOYW1lRm9yUHJvamVjdCB9IGZyb20gXCIuLi91dGlsL25hbWVcIjtcblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZFdvcmtmbG93Q29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBidWlsZGZpbGUgKGUuZy4gXCJidWlsZFwiIGJlY29tZXMgXCJidWlsZC55bWxcIikuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiYnVpbGRcIlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogU3RlcHMgdG8gZXhlY3V0ZSBiZWZvcmUgdGhlIGJ1aWxkLlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcmVhZG9ubHkgcHJlQnVpbGRTdGVwcz86IEpvYlN0ZXBbXTtcblxuICAvKipcbiAgICogQnVpbGQgd29ya2Zsb3cgdHJpZ2dlcnNcbiAgICogQGRlZmF1bHQgXCJ7IHB1bGxSZXF1ZXN0OiB7fSwgd29ya2Zsb3dEaXNwYXRjaDoge30gfVwiXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd1RyaWdnZXJzPzogVHJpZ2dlcnM7XG5cbiAgLyoqXG4gICAqIFBlcm1pc3Npb25zIGdyYW50ZWQgdG8gdGhlIGJ1aWxkIGpvYlxuICAgKiBUbyBsaW1pdCBqb2IgcGVybWlzc2lvbnMgZm9yIGBjb250ZW50c2AsIHRoZSBkZXNpcmVkIHBlcm1pc3Npb25zIGhhdmUgdG8gYmUgZXhwbGljaXRseSBzZXQsIGUuZy46IGB7IGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLk5PTkUgfWBcbiAgICogQGRlZmF1bHQgYHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uV1JJVEUgfWBcbiAgICovXG4gIHJlYWRvbmx5IHBlcm1pc3Npb25zPzogSm9iUGVybWlzc2lvbnM7XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogQGRlZmF1bHQge31cbiAgICovXG4gIHJlYWRvbmx5IGVudj86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRXb3JrZmxvd09wdGlvbnMgZXh0ZW5kcyBCdWlsZFdvcmtmbG93Q29tbW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgdGFzayB0byBleGVjdXRlIGluIG9yZGVyIHRvIGJ1aWxkIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRUYXNrOiBUYXNrO1xuXG4gIC8qKlxuICAgKiBBIG5hbWUgb2YgYSBkaXJlY3RvcnkgdGhhdCBpbmNsdWRlcyBidWlsZCBhcnRpZmFjdHMuXG4gICAqIEBkZWZhdWx0IFwiZGlzdFwiXG4gICAqL1xuICByZWFkb25seSBhcnRpZmFjdHNEaXJlY3Rvcnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjb250YWluZXIgaW1hZ2UgdG8gdXNlIGZvciBidWlsZHMuXG4gICAqIEBkZWZhdWx0IC0gdGhlIGRlZmF1bHQgd29ya2Zsb3cgY29udGFpbmVyXG4gICAqL1xuICByZWFkb25seSBjb250YWluZXJJbWFnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQXV0b21hdGljYWxseSB1cGRhdGUgZmlsZXMgbW9kaWZpZWQgZHVyaW5nIGJ1aWxkcyB0byBwdWxsLXJlcXVlc3QgYnJhbmNoZXMuXG4gICAqIFRoaXMgbWVhbnMgdGhhdCBhbnkgZmlsZXMgc3ludGhlc2l6ZWQgYnkgcHJvamVuIG9yIGUuZy4gdGVzdCBzbmFwc2hvdHMgd2lsbFxuICAgKiBhbHdheXMgYmUgdXAtdG8tZGF0ZSBiZWZvcmUgYSBQUiBpcyBtZXJnZWQuXG4gICAqXG4gICAqIEltcGxpZXMgdGhhdCBQUiBidWlsZHMgZG8gbm90IGhhdmUgYW50aS10YW1wZXIgY2hlY2tzLlxuICAgKlxuICAgKiBUaGlzIGlzIGVuYWJsZWQgYnkgZGVmYXVsdCBvbmx5IGlmIGBnaXRodWJUb2tlblNlY3JldGAgaXMgc2V0LiBPdGhlcndpc2UgaXRcbiAgICogaXMgZGlzYWJsZWQsIHdoaWNoIGltcGxpZXMgdGhhdCBmaWxlIGNoYW5nZXMgdGhhdCBoYXBwZW4gZHVyaW5nIGJ1aWxkIHdpbGxcbiAgICogbm90IGJlIHB1c2hlZCBiYWNrIHRvIHRoZSBicmFuY2guXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IG11dGFibGVCdWlsZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFN0ZXBzIHRvIGV4ZWN1dGUgYWZ0ZXIgYnVpbGQuXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBwb3N0QnVpbGRTdGVwcz86IEpvYlN0ZXBbXTtcblxuICAvKipcbiAgICogR2l0IGlkZW50aXR5IHRvIHVzZSBmb3IgdGhlIHdvcmtmbG93LlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgR2l0SHViIEFjdGlvbnMgdXNlclxuICAgKi9cbiAgcmVhZG9ubHkgZ2l0SWRlbnRpdHk/OiBHaXRJZGVudGl0eTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBzZWxlY3Rpb24gbGFiZWxzXG4gICAqIEBkZWZhdWx0IFtcInVidW50dS1sYXRlc3RcIl1cbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIGJ5IGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBydW5zT24/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBHcm91cCBzZWxlY3Rpb24gb3B0aW9uc1xuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgR3JvdXAgYnkgbmFtZSBhbmQvb3IgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbkdyb3VwPzogR3JvdXBSdW5uZXJPcHRpb25zO1xufVxuXG5leHBvcnQgY2xhc3MgQnVpbGRXb3JrZmxvdyBleHRlbmRzIENvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIGdlbmVyYXRlZCBnaXRodWIgd29ya2Zsb3dcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwb3N0QnVpbGRTdGVwczogSm9iU3RlcFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHByZUJ1aWxkU3RlcHM6IEpvYlN0ZXBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBnaXRJZGVudGl0eTogR2l0SWRlbnRpdHk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVpbGRUYXNrOiBUYXNrO1xuICBwcml2YXRlIHJlYWRvbmx5IGdpdGh1YjogR2l0SHViO1xuICBwcml2YXRlIHJlYWRvbmx5IHdvcmtmbG93OiBHaXRodWJXb3JrZmxvdztcbiAgcHJpdmF0ZSByZWFkb25seSBhcnRpZmFjdHNEaXJlY3Rvcnk6IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IF9wb3N0QnVpbGRKb2JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IEJ1aWxkV29ya2Zsb3dPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICBjb25zdCBnaXRodWIgPSBHaXRIdWIub2YodGhpcy5wcm9qZWN0LnJvb3QpO1xuICAgIGlmICghZ2l0aHViKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQnVpbGRXb3JrZmxvdyBpcyBjdXJyZW50bHkgb25seSBzdXBwb3J0ZWQgZm9yIEdpdEh1YiBwcm9qZWN0c1wiXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuZ2l0aHViID0gZ2l0aHViO1xuICAgIHRoaXMucHJlQnVpbGRTdGVwcyA9IG9wdGlvbnMucHJlQnVpbGRTdGVwcyA/PyBbXTtcbiAgICB0aGlzLnBvc3RCdWlsZFN0ZXBzID0gb3B0aW9ucy5wb3N0QnVpbGRTdGVwcyA/PyBbXTtcbiAgICB0aGlzLmdpdElkZW50aXR5ID0gb3B0aW9ucy5naXRJZGVudGl0eSA/PyBERUZBVUxUX0dJVEhVQl9BQ1RJT05TX1VTRVI7XG4gICAgdGhpcy5idWlsZFRhc2sgPSBvcHRpb25zLmJ1aWxkVGFzaztcbiAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSA9XG4gICAgICBvcHRpb25zLmFydGlmYWN0c0RpcmVjdG9yeSA/PyBERUZBVUxUX0FSVElGQUNUU19ESVJFQ1RPUlk7XG4gICAgZW5zdXJlTm90SGlkZGVuUGF0aCh0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSwgXCJhcnRpZmFjdHNEaXJlY3RvcnlcIik7XG4gICAgdGhpcy5uYW1lID0gb3B0aW9ucy5uYW1lID8/IHdvcmtmbG93TmFtZUZvclByb2plY3QoXCJidWlsZFwiLCB0aGlzLnByb2plY3QpO1xuICAgIGNvbnN0IG11dGFibGVCdWlsZHMgPSBvcHRpb25zLm11dGFibGVCdWlsZCA/PyB0cnVlO1xuXG4gICAgdGhpcy53b3JrZmxvdyA9IG5ldyBHaXRodWJXb3JrZmxvdyhnaXRodWIsIHRoaXMubmFtZSk7XG4gICAgdGhpcy53b3JrZmxvdy5vbihcbiAgICAgIG9wdGlvbnMud29ya2Zsb3dUcmlnZ2VycyA/PyB7XG4gICAgICAgIHB1bGxSZXF1ZXN0OiB7fSxcbiAgICAgICAgd29ya2Zsb3dEaXNwYXRjaDoge30sIC8vIGFsbG93IG1hbnVhbCB0cmlnZ2VyaW5nXG4gICAgICB9XG4gICAgKTtcblxuICAgIHRoaXMuYWRkQnVpbGRKb2Iob3B0aW9ucyk7XG5cbiAgICBpZiAobXV0YWJsZUJ1aWxkcykge1xuICAgICAgdGhpcy5hZGRTZWxmTXV0YXRpb25Kb2Iob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYgKHByb2plY3QgaW5zdGFuY2VvZiBOb2RlUHJvamVjdCkge1xuICAgICAgcHJvamVjdC5hZGRQYWNrYWdlSWdub3JlKFBFUk1JU1NJT05fQkFDS1VQX0ZJTEUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYWRkQnVpbGRKb2Iob3B0aW9uczogQnVpbGRXb3JrZmxvd09wdGlvbnMpIHtcbiAgICBjb25zdCBwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290ID0gcHJvamVjdFBhdGhSZWxhdGl2ZVRvUmVwb1Jvb3QoXG4gICAgICB0aGlzLnByb2plY3RcbiAgICApO1xuICAgIGNvbnN0IGpvYkNvbmZpZzogd29ya2Zsb3dzLkpvYiA9IHtcbiAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyhvcHRpb25zLnJ1bnNPbiwgb3B0aW9ucy5ydW5zT25Hcm91cCksXG4gICAgICBjb250YWluZXI6IG9wdGlvbnMuY29udGFpbmVySW1hZ2VcbiAgICAgICAgPyB7IGltYWdlOiBvcHRpb25zLmNvbnRhaW5lckltYWdlIH1cbiAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBlbnY6IHtcbiAgICAgICAgQ0k6IFwidHJ1ZVwiLFxuICAgICAgICAuLi5vcHRpb25zLmVudixcbiAgICAgIH0sXG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgICAgLi4ub3B0aW9ucy5wZXJtaXNzaW9ucyxcbiAgICAgIH0sXG4gICAgICBkZWZhdWx0czogdGhpcy5wcm9qZWN0LnBhcmVudCAvLyBpcyBzdWJwcm9qZWN0LFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHJ1bjoge1xuICAgICAgICAgICAgICB3b3JraW5nRGlyZWN0b3J5OiBwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgc3RlcHM6ICgoKSA9PiB0aGlzLnJlbmRlckJ1aWxkU3RlcHMocHJvamVjdFBhdGhSZWxhdGl2ZVRvUm9vdCkpIGFzIGFueSxcbiAgICAgIG91dHB1dHM6IHtcbiAgICAgICAgW1NFTEZfTVVUQVRJT05fSEFQUEVORURfT1VUUFVUXToge1xuICAgICAgICAgIHN0ZXBJZDogU0VMRl9NVVRBVElPTl9TVEVQLFxuICAgICAgICAgIG91dHB1dE5hbWU6IFNFTEZfTVVUQVRJT05fSEFQUEVORURfT1VUUFVULFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgdGhpcy53b3JrZmxvdy5hZGRKb2IoQlVJTERfSk9CSUQsIGpvYkNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2Ygam9iIElEcyB0aGF0IGFyZSBwYXJ0IG9mIHRoZSBidWlsZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgYnVpbGRKb2JJZHMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbQlVJTERfSk9CSUQsIC4uLnRoaXMuX3Bvc3RCdWlsZEpvYnNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgc3RlcHMgdGhhdCBhcmUgZXhlY3V0ZWQgYWZ0ZXIgdGhlIGJ1aWxkLlxuICAgKiBAcGFyYW0gc3RlcHMgVGhlIGpvYiBzdGVwc1xuICAgKi9cbiAgcHVibGljIGFkZFBvc3RCdWlsZFN0ZXBzKC4uLnN0ZXBzOiBKb2JTdGVwW10pOiB2b2lkIHtcbiAgICB0aGlzLnBvc3RCdWlsZFN0ZXBzLnB1c2goLi4uc3RlcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW5vdGhlciBqb2IgdG8gdGhlIGJ1aWxkIHdvcmtmbG93IHdoaWNoIGlzIGV4ZWN1dGVkIGFmdGVyIHRoZSBidWlsZFxuICAgKiBqb2Igc3VjY2VlZGVkLlxuICAgKlxuICAgKiBKb2JzIGFyZSBleGVjdXRlZCBfb25seV8gaWYgdGhlIGJ1aWxkIGRpZCBOT1Qgc2VsZiBtdXRhdGUuIElmIHRoZSBidWlsZFxuICAgKiBzZWxmLW11dGF0ZSwgdGhlIGJyYW5jaCB3aWxsIGVpdGhlciBiZSB1cGRhdGVkIG9yIHRoZSBidWlsZCB3aWxsIGZhaWwgKGluXG4gICAqIGZvcmtzKSwgc28gdGhlcmUgaXMgbm8gcG9pbnQgaW4gZXhlY3V0aW5nIHRoZSBwb3N0LWJ1aWxkIGpvYi5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgbmV3IGpvYlxuICAgKiBAcGFyYW0gam9iIFRoZSBqb2Igc3BlY2lmaWNhdGlvblxuICAgKi9cbiAgcHVibGljIGFkZFBvc3RCdWlsZEpvYihpZDogc3RyaW5nLCBqb2I6IEpvYikge1xuICAgIGNvbnN0IHN0ZXBzID0gW107XG5cbiAgICBzdGVwcy5wdXNoKFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIkRvd25sb2FkIGJ1aWxkIGFydGlmYWN0c1wiLFxuICAgICAgICB1c2VzOiBcImFjdGlvbnMvZG93bmxvYWQtYXJ0aWZhY3RAdjVcIixcbiAgICAgICAgd2l0aDoge1xuICAgICAgICAgIG5hbWU6IEJVSUxEX0FSVElGQUNUX05BTUUsXG4gICAgICAgICAgcGF0aDogdGhpcy5hcnRpZmFjdHNEaXJlY3RvcnksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIlJlc3RvcmUgYnVpbGQgYXJ0aWZhY3QgcGVybWlzc2lvbnNcIixcbiAgICAgICAgY29udGludWVPbkVycm9yOiB0cnVlLFxuICAgICAgICBydW46IFtcbiAgICAgICAgICBgY2QgJHt0aGlzLmFydGlmYWN0c0RpcmVjdG9yeX0gJiYgc2V0ZmFjbCAtLXJlc3RvcmU9JHtQRVJNSVNTSU9OX0JBQ0tVUF9GSUxFfWAsXG4gICAgICAgIF0uam9pbihcIlxcblwiKSxcbiAgICAgIH1cbiAgICApO1xuXG4gICAgc3RlcHMucHVzaCguLi4oam9iLnN0ZXBzID8/IFtdKSk7XG5cbiAgICB0aGlzLndvcmtmbG93LmFkZEpvYihpZCwge1xuICAgICAgbmVlZHM6IFtCVUlMRF9KT0JJRF0sXG4gICAgICAvLyBvbmx5IHJ1biBpZiBidWlsZCBkaWQgbm90IHNlbGYtbXV0YXRlXG4gICAgICBpZjogYFxcJHt7ICEke1NFTEZfTVVUQVRJT05fQ09ORElUSU9OfSB9fWAsXG4gICAgICAuLi5qb2IsXG4gICAgICBzdGVwczogc3RlcHMsXG4gICAgfSk7XG5cbiAgICAvLyBhZGQgdG8gdGhlIGxpc3Qgb2YgYnVpbGQgam9iIElEc1xuICAgIHRoaXMuX3Bvc3RCdWlsZEpvYnMucHVzaChpZCk7XG4gIH1cblxuICAvKipcbiAgICogUnVuIGEgdGFzayBhcyBhIGpvYiB3aXRoaW4gdGhlIGJ1aWxkIHdvcmtmbG93IHdoaWNoIGlzIGV4ZWN1dGVkIGFmdGVyIHRoZVxuICAgKiBidWlsZCBqb2Igc3VjY2VlZGVkLlxuICAgKlxuICAgKiBUaGUgam9iIHdpbGwgaGF2ZSBhY2Nlc3MgdG8gYnVpbGQgYXJ0aWZhY3RzIGFuZCB3aWxsIGluc3RhbGwgcHJvamVjdFxuICAgKiBkZXBlbmRlbmNpZXMgaW4gb3JkZXIgdG8gYmUgYWJsZSB0byBydW4gYW55IGNvbW1hbmRzIHVzZWQgaW4gdGhlIHRhc2tzLlxuICAgKlxuICAgKiBKb2JzIGFyZSBleGVjdXRlZCBfb25seV8gaWYgdGhlIGJ1aWxkIGRpZCBOT1Qgc2VsZiBtdXRhdGUuIElmIHRoZSBidWlsZFxuICAgKiBzZWxmLW11dGF0ZSwgdGhlIGJyYW5jaCB3aWxsIGVpdGhlciBiZSB1cGRhdGVkIG9yIHRoZSBidWlsZCB3aWxsIGZhaWwgKGluXG4gICAqIGZvcmtzKSwgc28gdGhlcmUgaXMgbm8gcG9pbnQgaW4gZXhlY3V0aW5nIHRoZSBwb3N0LWJ1aWxkIGpvYi5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgU3BlY2lmeSB0b29scyBhbmQgb3RoZXIgb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGFkZFBvc3RCdWlsZEpvYlRhc2soXG4gICAgdGFzazogVGFzayxcbiAgICBvcHRpb25zOiBBZGRQb3N0QnVpbGRKb2JUYXNrT3B0aW9ucyA9IHt9XG4gICkge1xuICAgIHRoaXMuYWRkUG9zdEJ1aWxkSm9iQ29tbWFuZHMoXG4gICAgICBgcG9zdC1idWlsZC0ke3Rhc2submFtZX1gLFxuICAgICAgW2Ake3RoaXMucHJvamVjdC5wcm9qZW5Db21tYW5kfSAke3Rhc2submFtZX1gXSxcbiAgICAgIHtcbiAgICAgICAgY2hlY2tvdXRSZXBvOiB0cnVlLFxuICAgICAgICBpbnN0YWxsRGVwczogdHJ1ZSxcbiAgICAgICAgdG9vbHM6IG9wdGlvbnMudG9vbHMsXG4gICAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyhvcHRpb25zLnJ1bnNPbiwgb3B0aW9ucy5ydW5zT25Hcm91cCksXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gYSBzZXF1ZW5jZSBvZiBjb21tYW5kcyBhcyBhIGpvYiB3aXRoaW4gdGhlIGJ1aWxkIHdvcmtmbG93IHdoaWNoIGlzXG4gICAqIGV4ZWN1dGVkIGFmdGVyIHRoZSBidWlsZCBqb2Igc3VjY2VlZGVkLlxuICAgKlxuICAgKiBKb2JzIGFyZSBleGVjdXRlZCBfb25seV8gaWYgdGhlIGJ1aWxkIGRpZCBOT1Qgc2VsZiBtdXRhdGUuIElmIHRoZSBidWlsZFxuICAgKiBzZWxmLW11dGF0ZSwgdGhlIGJyYW5jaCB3aWxsIGVpdGhlciBiZSB1cGRhdGVkIG9yIHRoZSBidWlsZCB3aWxsIGZhaWwgKGluXG4gICAqIGZvcmtzKSwgc28gdGhlcmUgaXMgbm8gcG9pbnQgaW4gZXhlY3V0aW5nIHRoZSBwb3N0LWJ1aWxkIGpvYi5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgU3BlY2lmeSB0b29scyBhbmQgb3RoZXIgb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGFkZFBvc3RCdWlsZEpvYkNvbW1hbmRzKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgY29tbWFuZHM6IHN0cmluZ1tdLFxuICAgIG9wdGlvbnM/OiBBZGRQb3N0QnVpbGRKb2JDb21tYW5kc09wdGlvbnNcbiAgKSB7XG4gICAgY29uc3Qgc3RlcHMgPSBbXTtcblxuICAgIGlmIChvcHRpb25zPy5jaGVja291dFJlcG8pIHtcbiAgICAgIHN0ZXBzLnB1c2goXG4gICAgICAgIFdvcmtmbG93U3RlcHMuY2hlY2tvdXQoe1xuICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgIHJlZjogUFVMTF9SRVFVRVNUX1JFRixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IFBVTExfUkVRVUVTVF9SRVBPU0lUT1JZLFxuICAgICAgICAgICAgLi4uKHRoaXMuZ2l0aHViLmRvd25sb2FkTGZzID8geyBsZnM6IHRydWUgfSA6IHt9KSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBvcHRpb25zPy5jaGVja291dFJlcG8gJiZcbiAgICAgIG9wdGlvbnM/Lmluc3RhbGxEZXBzICYmXG4gICAgICB0aGlzLnByb2plY3QgaW5zdGFuY2VvZiBOb2RlUHJvamVjdFxuICAgICkge1xuICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgIG5hbWU6IFwiSW5zdGFsbCBkZXBlbmRlbmNpZXNcIixcbiAgICAgICAgcnVuOiBgJHt0aGlzLnByb2plY3QucGFja2FnZS5pbnN0YWxsQ29tbWFuZH1gLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3RlcHMucHVzaCh7IHJ1bjogY29tbWFuZHMuam9pbihcIlxcblwiKSB9KTtcblxuICAgIHRoaXMuYWRkUG9zdEJ1aWxkSm9iKGlkLCB7XG4gICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgfSxcbiAgICAgIHRvb2xzOiBvcHRpb25zPy50b29scyxcbiAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyhvcHRpb25zPy5ydW5zT24sIG9wdGlvbnM/LnJ1bnNPbkdyb3VwKSxcbiAgICAgIHN0ZXBzLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRTZWxmTXV0YXRpb25Kb2Iob3B0aW9uczogQnVpbGRXb3JrZmxvd09wdGlvbnMpIHtcbiAgICB0aGlzLndvcmtmbG93LmFkZEpvYihcInNlbGYtbXV0YXRpb25cIiwge1xuICAgICAgLi4uZmlsdGVyZWRSdW5zT25PcHRpb25zKG9wdGlvbnMucnVuc09uLCBvcHRpb25zLnJ1bnNPbkdyb3VwKSxcbiAgICAgIHBlcm1pc3Npb25zOiB7XG4gICAgICAgIGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgfSxcbiAgICAgIG5lZWRzOiBbQlVJTERfSk9CSURdLFxuICAgICAgaWY6IGBhbHdheXMoKSAmJiAke1NFTEZfTVVUQVRJT05fQ09ORElUSU9OfSAmJiAke05PVF9GT1JLfWAsXG4gICAgICBzdGVwczogW1xuICAgICAgICAuLi50aGlzLndvcmtmbG93LnByb2plbkNyZWRlbnRpYWxzLnNldHVwU3RlcHMsXG4gICAgICAgIC4uLldvcmtmbG93QWN0aW9ucy5jaGVja291dFdpdGhQYXRjaCh7XG4gICAgICAgICAgLy8gd2UgbmVlZCB0byB1c2UgYSBQQVQgc28gdGhhdCBvdXIgcHVzaCB3aWxsIHRyaWdnZXIgdGhlIGJ1aWxkIHdvcmtmbG93XG4gICAgICAgICAgdG9rZW46IHRoaXMud29ya2Zsb3cucHJvamVuQ3JlZGVudGlhbHMudG9rZW5SZWYsXG4gICAgICAgICAgcmVmOiBQVUxMX1JFUVVFU1RfUkVGLFxuICAgICAgICAgIHJlcG9zaXRvcnk6IFBVTExfUkVRVUVTVF9SRVBPU0lUT1JZLFxuICAgICAgICAgIGxmczogdGhpcy5naXRodWIuZG93bmxvYWRMZnMsXG4gICAgICAgIH0pLFxuICAgICAgICBXb3JrZmxvd1N0ZXBzLnNldHVwR2l0SWRlbnRpdHkoeyBnaXRJZGVudGl0eTogdGhpcy5naXRJZGVudGl0eSB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwiUHVzaCBjaGFuZ2VzXCIsXG4gICAgICAgICAgZW52OiB7XG4gICAgICAgICAgICBQVUxMX1JFUVVFU1RfUkVGLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcnVuOiBbXG4gICAgICAgICAgICBcImdpdCBhZGQgLlwiLFxuICAgICAgICAgICAgJ2dpdCBjb21taXQgLXMgLW0gXCJjaG9yZTogc2VsZiBtdXRhdGlvblwiJyxcbiAgICAgICAgICAgIGBnaXQgcHVzaCBvcmlnaW4gXCJIRUFEOiRQVUxMX1JFUVVFU1RfUkVGXCJgLFxuICAgICAgICAgIF0uam9pbihcIlxcblwiKSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIChsYXppbHkpIGR1cmluZyBzeW50aCB0byByZW5kZXIgdGhlIGJ1aWxkIGpvYiBzdGVwcy5cbiAgICovXG4gIHByaXZhdGUgcmVuZGVyQnVpbGRTdGVwcyhwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290OiBzdHJpbmcpOiBKb2JTdGVwW10ge1xuICAgIHJldHVybiBbXG4gICAgICBXb3JrZmxvd1N0ZXBzLmNoZWNrb3V0KHtcbiAgICAgICAgd2l0aDoge1xuICAgICAgICAgIHJlZjogUFVMTF9SRVFVRVNUX1JFRixcbiAgICAgICAgICByZXBvc2l0b3J5OiBQVUxMX1JFUVVFU1RfUkVQT1NJVE9SWSxcbiAgICAgICAgICAuLi4odGhpcy5naXRodWIuZG93bmxvYWRMZnMgPyB7IGxmczogdHJ1ZSB9IDoge30pLFxuICAgICAgICB9LFxuICAgICAgfSksXG5cbiAgICAgIC4uLnRoaXMucHJlQnVpbGRTdGVwcyxcblxuICAgICAge1xuICAgICAgICBuYW1lOiB0aGlzLmJ1aWxkVGFzay5uYW1lLFxuICAgICAgICBydW46IHRoaXMuZ2l0aHViLnByb2plY3QucnVuVGFza0NvbW1hbmQodGhpcy5idWlsZFRhc2spLFxuICAgICAgfSxcblxuICAgICAgLi4udGhpcy5wb3N0QnVpbGRTdGVwcyxcblxuICAgICAgLy8gY2hlY2sgZm9yIG11dGF0aW9ucyBhbmQgdXBsb2FkIGEgZ2l0IHBhdGNoIGZpbGUgYXMgYW4gYXJ0aWZhY3RcbiAgICAgIC4uLldvcmtmbG93QWN0aW9ucy51cGxvYWRHaXRQYXRjaCh7XG4gICAgICAgIHN0ZXBJZDogU0VMRl9NVVRBVElPTl9TVEVQLFxuICAgICAgICBvdXRwdXROYW1lOiBTRUxGX01VVEFUSU9OX0hBUFBFTkVEX09VVFBVVCxcbiAgICAgICAgbXV0YXRpb25FcnJvcjpcbiAgICAgICAgICBcIkZpbGVzIHdlcmUgY2hhbmdlZCBkdXJpbmcgYnVpbGQgKHNlZSBidWlsZCBsb2cpLiBJZiB0aGlzIHdhcyB0cmlnZ2VyZWQgZnJvbSBhIGZvcmssIHlvdSB3aWxsIG5lZWQgdG8gdXBkYXRlIHlvdXIgYnJhbmNoLlwiLFxuICAgICAgfSksXG5cbiAgICAgIC8vIHVwbG9hZCB0aGUgYnVpbGQgYXJ0aWZhY3Qgb25seSBpZiB3ZSBoYXZlIHBvc3QtYnVpbGQgam9icyAob3RoZXJ3aXNlLCB0aGVyZSdzIG5vIHBvaW50KVxuICAgICAgLi4uKHRoaXMuX3Bvc3RCdWlsZEpvYnMubGVuZ3RoID09IDBcbiAgICAgICAgPyBbXVxuICAgICAgICA6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbmFtZTogXCJCYWNrdXAgYXJ0aWZhY3QgcGVybWlzc2lvbnNcIixcbiAgICAgICAgICAgICAgY29udGludWVPbkVycm9yOiB0cnVlLFxuICAgICAgICAgICAgICBydW46IGBjZCAke3RoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5fSAmJiBnZXRmYWNsIC1SIC4gPiAke1BFUk1JU1NJT05fQkFDS1VQX0ZJTEV9YCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBXb3JrZmxvd1N0ZXBzLnVwbG9hZEFydGlmYWN0KHtcbiAgICAgICAgICAgICAgd2l0aDoge1xuICAgICAgICAgICAgICAgIG5hbWU6IEJVSUxEX0FSVElGQUNUX05BTUUsXG4gICAgICAgICAgICAgICAgcGF0aDogdGhpcy5wcm9qZWN0LnBhcmVudFxuICAgICAgICAgICAgICAgICAgPyBwb3NpeFBhdGguam9pbihcbiAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290LFxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5XG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgIDogdGhpcy5hcnRpZmFjdHNEaXJlY3RvcnksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdKSxcbiAgICBdO1xuICB9XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYEJ1aWxkV29ya2Zsb3cuYWRkUG9zdEJ1aWxkSm9iVGFza2BcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRQb3N0QnVpbGRKb2JUYXNrT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUb29scyB0aGF0IHNob3VsZCBiZSBpbnN0YWxsZWQgYmVmb3JlIHRoZSB0YXNrIGlzIHJ1bi5cbiAgICovXG4gIHJlYWRvbmx5IHRvb2xzPzogVG9vbHM7XG5cbiAgLyoqXG4gICAqIEdpdGh1YiBSdW5uZXIgc2VsZWN0aW9uIGxhYmVsc1xuICAgKiBAZGVmYXVsdCBbXCJ1YnVudHUtbGF0ZXN0XCJdXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIGEgdGFyZ2V0IFJ1bm5lciBieSBsYWJlbHNcbiAgICogQHRocm93cyB7RXJyb3J9IGlmIGJvdGggYHJ1bnNPbmAgYW5kIGBydW5zT25Hcm91cGAgYXJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgcnVuc09uPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEdpdGh1YiBSdW5uZXIgR3JvdXAgc2VsZWN0aW9uIG9wdGlvbnNcbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIEdyb3VwIGJ5IG5hbWUgYW5kL29yIGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBydW5zT25Hcm91cD86IEdyb3VwUnVubmVyT3B0aW9ucztcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgQnVpbGRXb3JrZmxvdy5hZGRQb3N0QnVpbGRKb2JDb21tYW5kc2BcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRQb3N0QnVpbGRKb2JDb21tYW5kc09wdGlvbnMge1xuICAvKipcbiAgICogVG9vbHMgdGhhdCBzaG91bGQgYmUgaW5zdGFsbGVkIGJlZm9yZSB0aGUgY29tbWFuZHMgYXJlIHJ1bi5cbiAgICovXG4gIHJlYWRvbmx5IHRvb2xzPzogVG9vbHM7XG5cbiAgLyoqXG4gICAqIENoZWNrIG91dCB0aGUgcmVwb3NpdG9yeSBhdCB0aGUgcHVsbCByZXF1ZXN0IGJyYW5jaCBiZWZvcmUgY29tbWFuZHMgYXJlXG4gICAqIHJ1bi5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNoZWNrb3V0UmVwbz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluc3RhbGwgcHJvamVjdCBkZXBlbmRlbmNpZXMgYmVmb3JlIHJ1bm5pbmcgY29tbWFuZHMuIGBjaGVja291dFJlcG9gIG11c3RcbiAgICogYWxzbyBiZSBzZXQgdG8gdHJ1ZS5cbiAgICpcbiAgICogQ3VycmVudGx5IG9ubHkgc3VwcG9ydGVkIGZvciBgTm9kZVByb2plY3RgLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFsbERlcHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIHNlbGVjdGlvbiBsYWJlbHNcbiAgICogQGRlZmF1bHQgW1widWJ1bnR1LWxhdGVzdFwiXVxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgYnkgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIEdyb3VwIHNlbGVjdGlvbiBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIGEgdGFyZ2V0IFJ1bm5lciBHcm91cCBieSBuYW1lIGFuZC9vciBsYWJlbHNcbiAgICogQHRocm93cyB7RXJyb3J9IGlmIGJvdGggYHJ1bnNPbmAgYW5kIGBydW5zT25Hcm91cGAgYXJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgcnVuc09uR3JvdXA/OiBHcm91cFJ1bm5lck9wdGlvbnM7XG59XG4iXX0=