@jjrawlins/cdk-diff-pr-github-action 0.0.8-beta → 0.0.9-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +6 -11
- package/README.md +2 -2
- package/lib/CdkDriftDetectionWorkflow.d.ts +1 -1
- package/lib/CdkDriftDetectionWorkflow.js +3 -2
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -3548,7 +3548,7 @@
|
|
|
3548
3548
|
},
|
|
3549
3549
|
"name": "@jjrawlins/cdk-diff-pr-github-action",
|
|
3550
3550
|
"readme": {
|
|
3551
|
-
"markdown": "# cdk-diff-pr-github-action\n\nA small Projen-based helper library that wires GitHub workflows for:\n- Creating CloudFormation Change Sets for your CDK stacks on pull requests and commenting a formatted diff back on the PR.\n- Detecting CloudFormation drift on a schedule or manual trigger and producing a consolidated summary (optionally creating an issue).\n\nIt also provides ready‑to‑deploy IAM templates with the minimal permissions required for each workflow.\n\nThis package exposes four constructs:\n\n- `CdkDiffStackWorkflow` — Generates one GitHub Actions workflow per stack to create a change set and render the diff back to the PR and Step Summary.\n- `CdkDiffIamTemplate` — Emits a CloudFormation template file with minimal permissions for the Change Set workflow.\n- `CdkDriftDetectionWorkflow` — Generates a GitHub Actions workflow to detect CloudFormation drift per stack, upload machine‑readable results, and aggregate a summary.\n- `CdkDriftIamTemplate` — Emits a CloudFormation template file with minimal permissions for the Drift Detection workflow.\n\n## Quick start\n\n1) Add the constructs to your Projen project (in `.projenrc.ts`).\n2) Synthesize with `npx projen`.\n3) Commit the generated files.\n4) Open a pull request or run the drift detection workflow.\n\n## Usage: CdkDiffStackWorkflow\n\n`CdkDiffStackWorkflow` renders a workflow per stack named `diff-<StackName>.yml` under `.github/workflows/`. It also generates a helper script at `.github/workflows/scripts/describe-cfn-changeset.ts` that formats the change set output and takes care of posting the PR comment and Step Summary.\n\nExample `.projenrc.ts`:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDiffStackWorkflow } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ... your usual settings ...\n workflowName: 'my-lib',\n defaultReleaseBranch: 'main',\n cdkVersion: '2.85.0',\n github: true,\n});\n\nnew CdkDiffStackWorkflow({\n project,\n stacks: [\n {\n stackName: 'MyAppStack',\n changesetRoleToAssumeArn: 'arn:aws:iam::123456789012:role/cdk-diff-role',\n changesetRoleToAssumeRegion: 'us-east-1',\n // Optional per‑stack OIDC override (if not using the defaults below)\n // oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n // oidcRegion: 'us-east-1',\n },\n ],\n // Default OIDC role/region used by all stacks unless overridden per‑stack\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: Node version used in the workflow (default: '24.x')\n // nodeVersion: '24.x',\n // Optional: Yarn command to run CDK (default: 'cdk')\n // cdkYarnCommand: 'cdk',\n // Optional: Where to place the helper script (default: '.github/workflows/scripts/describe-cfn-changeset.ts')\n // scriptOutputPath: '.github/workflows/scripts/describe-cfn-changeset.ts',\n});\n\nproject.synth();\n```\n\n### CdkDiffStackWorkflow props\n- `project` (required) — Your Projen project instance.\n- `stacks` (required) — Array of stack entries.\n- `oidcRoleArn` (required unless provided per‑stack) — Default OIDC role ARN.\n- `oidcRegion` (required unless provided per‑stack) — Default OIDC region.\n- `nodeVersion` (optional, default `'24.x'`) — Node.js version for the workflow runner.\n- `cdkYarnCommand` (optional, default `'cdk'`) — Yarn script/command to invoke CDK.\n- `scriptOutputPath` (optional, default `'.github/workflows/scripts/describe-cfn-changeset.ts'`) — Where to write the helper script.\n\nIf neither top‑level OIDC defaults nor all per‑stack values are supplied, the construct throws a helpful error.\n\n### Stack item fields\n- `stackName` (required) — The CDK stack name to create the change set for.\n- `changesetRoleToAssumeArn` (required) — The ARN of the role used to create the change set (role chaining after OIDC).\n- `changesetRoleToAssumeRegion` (required) — The region for that role.\n- `oidcRoleArn` (optional) — Per‑stack override for the OIDC role.\n- `oidcRegion` (optional) — Per‑stack override for the OIDC region.\n\n### What gets generated\n- `.github/workflows/diff-<StackName>.yml` — One workflow per stack, triggered on PR open/sync/reopen.\n- `.github/workflows/scripts/describe-cfn-changeset.ts` — A helper script that:\n - Polls `DescribeChangeSet` until terminal\n - Filters out ignorable logical IDs or resource types using environment variables `IGNORE_LOGICAL_IDS` and `IGNORE_RESOURCE_TYPES`\n - Renders an HTML table with actions, logical IDs, types, replacements, and changed properties\n - Prints the HTML, appends to the GitHub Step Summary, and (if `GITHUB_TOKEN` and `GITHUB_COMMENT_URL` are present) posts a PR comment\n\n### Environment variables used by the change set script\n- `STACK_NAME` (required) — Stack name to describe.\n- `CHANGE_SET_NAME` (default: same as `STACK_NAME`).\n- `AWS_REGION` — Region for CloudFormation API calls. The workflow sets this via the credentials action(s).\n- `GITHUB_TOKEN` (optional) — If set with `GITHUB_COMMENT_URL`, posts a PR comment.\n- `GITHUB_COMMENT_URL` (optional) — PR comments URL.\n- `GITHUB_STEP_SUMMARY` (optional) — When present, appends the HTML to the step summary file.\n- `IGNORE_LOGICAL_IDS` (optional) — Comma‑separated logical IDs to ignore (default includes `CDKMetadata`).\n- `IGNORE_RESOURCE_TYPES` (optional) — Comma‑separated resource types to ignore (e.g., `AWS::CDK::Metadata`).\n\n## Usage: CdkDiffIamTemplate\n\nEmit an example IAM template you can deploy in your account for the Change Set workflow:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDiffIamTemplate } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ...\n});\n\nnew CdkDiffIamTemplate({\n project,\n roleName: 'cdk-diff-role',\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: custom output path (default: 'cdk-diff-workflow-iam-template.yaml')\n // outputPath: 'infra/cdk-diff-iam.yaml',\n});\n\nproject.synth();\n```\n\nThis writes `cdk-diff-workflow-iam-template.yaml` at the project root (or your chosen `outputPath`). The template defines:\n- Parameter `GitHubOIDCRoleArn` with a default from `oidcRoleArn` — the ARN of your existing GitHub OIDC role allowed to assume the change set role.\n- IAM role `CdkChangesetRole` with minimal permissions for:\n - CloudFormation Change Set operations\n - Access to common CDK bootstrap S3 buckets and SSM parameters\n - `iam:PassRole` to `cloudformation.amazonaws.com`\n- Outputs exporting the role name and ARN.\n\nA Projen task is also added:\n\n```bash\nnpx projen deploy-cdkdiff-iam-template -- --parameter-overrides GitHubOIDCRoleArn=... # plus any extra AWS CLI args\n```\n\nUse the created role ARN as `changesetRoleToAssumeArn` in `CdkDiffStackWorkflow`.\n\n---\n\n## Usage: CdkDriftDetectionWorkflow\n\n`CdkDriftDetectionWorkflow` creates a single workflow file (default `drift-detection.yml`) that can run on a schedule and via manual dispatch. It generates a helper script at `.github/workflows/scripts/detect-drift.ts` (by default) that uses AWS SDK v3 to run drift detection, write optional machine‑readable JSON, and print an HTML report for the Step Summary.\n\nExample `.projenrc.ts`:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDriftDetectionWorkflow } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({ github: true, /* ... */ });\n\nnew CdkDriftDetectionWorkflow({\n project,\n workflowName: 'Drift Detection', // optional; file name derived as 'drift-detection.yml'\n schedule: '0 1 * * *', // optional cron\n createIssues: true, // default true; create/update issue when drift detected on schedule\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: Node version (default '24.x')\n // nodeVersion: '24.x',\n // Optional: Where to place the helper script (default '.github/workflows/scripts/detect-drift.ts')\n // scriptOutputPath: '.github/workflows/scripts/detect-drift.ts',\n stacks: [\n {\n stackName: 'MyAppStack-Prod',\n driftDetectionRoleToAssumeArn: 'arn:aws:iam::123456789012:role/cdk-drift-role',\n driftDetectionRoleToAssumeRegion: 'us-east-1',\n // failOnDrift: true, // optional (default true)\n },\n ],\n});\n\nproject.synth();\n```\n\n### CdkDriftDetectionWorkflow props\n- `project` (required) — Your Projen project instance.\n- `stacks` (required) — Array of stacks to check.\n- `oidcRoleArn` (required) — Default OIDC role ARN used before chaining into per‑stack drift roles.\n- `oidcRegion` (required) — Default OIDC region.\n- `workflowName` (optional, default `'drift-detection'`) — Human‑friendly workflow name; the file name is derived in kebab‑case.\n- `schedule` (optional) — Cron expression for automatic runs.\n- `createIssues` (optional, default `true`) — When true, scheduled runs will create/update a GitHub issue if drift is detected.\n- `nodeVersion` (optional, default `'24.x'`) — Node.js version for the runner.\n- `scriptOutputPath` (optional, default `'.github/workflows/scripts/detect-drift.ts'`) — Where to write the helper script.\n\n### Per‑stack fields\n- `stackName` (required) — The full CloudFormation stack name.\n- `driftDetectionRoleToAssumeArn` (required) — Role to assume (after OIDC) for making drift API calls.\n- `driftDetectionRoleToAssumeRegion` (required) — Region for that role and API calls.\n- `failOnDrift` (optional, default `true`) — Intended to fail the detection step on drift. The provided script exits with non‑zero when drift is found; the job continues to allow artifact upload and issue creation.\n\n### What gets generated\n- `.github/workflows/<kebab(workflowName)>.yml` — A workflow with one job per stack plus a final summary job.\n- `.github/workflows/scripts/detect-drift.ts` — Helper script that:\n - Starts drift detection and polls until completion\n - Lists non‑`IN_SYNC` resources and builds an HTML report\n - Writes optional JSON to `DRIFT_DETECTION_OUTPUT` when set\n - Prints to stdout and appends to the GitHub Step Summary when available\n\n### Artifacts and summary\n- Each stack job uploads `drift-results-<stack>.json` (if produced).\n- A final `Drift Detection Summary` job downloads all artifacts and prints a consolidated summary.\n\nNote: The default workflow does not post PR comments for drift. It can create/update an Issue on scheduled runs when `createIssues` is `true`.\n\n### Post-notification steps (e.g., Slack)\n\nYou can add your own GitHub Action steps to run after the drift detection step for each stack using `postGitHubSteps`.\nThese steps receive a prepared Slack-compatible JSON payload via `${{ steps.notify.outputs.result }}` from an earlier step.\n\nExample: Send Slack notification (only when drift occurs) using slackapi/slack-github-action@v1\n\n```ts\nnew CdkDriftDetectionWorkflow({\n project,\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n stacks: [/* ... */],\n postGitHubSteps: ({ stack }) => {\n // Build a descriptive name per stack\n const name = `Notify Slack (${stack} post-drift)`;\n const step = {\n name,\n uses: 'slackapi/slack-github-action@v1',\n // by default, post steps run only when drift is detected; you can override `if`\n if: \"always() && steps.drift.outcome == 'failure'\",\n with: {\n payload: '${{ steps.notify.outputs.result }}',\n },\n env: {\n SLACK_WEBHOOK_URL: '${{ secrets.CDK_NOTIFICATIONS_SLACK_WEBHOOK }}',\n SLACK_WEBHOOK_TYPE: 'INCOMING_WEBHOOK',\n },\n };\n return [step];\n },\n});\n```\n\nDetails:\n- `postGitHubSteps` can be:\n - an array of step objects, or\n - a factory function `({ stack, stack, resultsFile }) => step | step[]`.\n- Each step you provide is inserted after the results are uploaded and after a `Prepare notification payload` step.\n- The prepared payload is a Slack Block Kit JSON string summarizing results for that stack/stack.\n- Default condition: if you do not set `if` on your step, it will default to `always() && steps.drift.outcome == 'failure'`.\n- Available context/env you can use:\n - `${{ env.STAGE_NAME }}`, `${{ env.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`\n - `${{ steps.notify.outputs.result }}` — Slack payload JSON\n```\n\n## Usage: CdkDriftIamTemplate\n\nEmit an example IAM template you can deploy in your account for the Drift Detection workflow:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDriftIamTemplate } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ...\n});\n\nnew CdkDriftIamTemplate({\n project,\n roleName: 'cdk-drift-role',\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: custom output path (default: 'cdk-drift-workflow-iam-template.yaml')\n // outputPath: 'infra/cdk-drift-iam.yaml',\n});\n\nproject.synth();\n```\n\nThis writes `cdk-drift-workflow-iam-template.yaml` at the project root (or your chosen `outputPath`). The template defines:\n- Parameter `GitHubOIDCRoleArn` with a default from `oidcRoleArn` — the ARN of your existing GitHub OIDC role allowed to assume this drift role.\n- IAM role `CdkDriftRole` with minimal permissions for CloudFormation drift detection operations.\n- Outputs exporting the role name and ARN.\n\nA Projen task is also added:\n\n```bash\nnpx projen deploy-cdkdrift-iam-template -- --parameter-overrides GitHubOIDCRoleArn=... # plus any extra AWS CLI args\n```\n\n## Testing\n\nThis repository includes Jest tests that snapshot the synthesized outputs from Projen and assert that:\n- Diff workflows are created per stack and contain all expected steps.\n- Drift detection workflow produces one job per stack and a summary job.\n- Only one helper script file is generated per workflow type.\n- Per‑stack OIDC overrides (where supported) are respected.\n- Helpful validation errors are thrown for missing OIDC settings.\n- The IAM template files contain the expected resources and outputs.\n\nRun tests with:\n\n```bash\nyarn test\n```\n\n## Notes\n- This package assumes your repository is configured with GitHub Actions and that you have a GitHub OIDC role configured in AWS.\n- The generated scripts use the AWS SDK v3 for CloudFormation and, where applicable, the GitHub REST API.\n"
|
|
3551
|
+
"markdown": "# cdk-diff-pr-github-action\n\nA small Projen-based helper library that wires GitHub workflows for:\n- Creating CloudFormation Change Sets for your CDK stacks on pull requests and commenting a formatted diff back on the PR.\n- Detecting CloudFormation drift on a schedule or manual trigger and producing a consolidated summary (optionally creating an issue).\n\nIt also provides ready‑to‑deploy IAM templates with the minimal permissions required for each workflow.\n\nThis package exposes four constructs:\n\n- `CdkDiffStackWorkflow` — Generates one GitHub Actions workflow per stack to create a change set and render the diff back to the PR and Step Summary.\n- `CdkDiffIamTemplate` — Emits a CloudFormation template file with minimal permissions for the Change Set workflow.\n- `CdkDriftDetectionWorkflow` — Generates a GitHub Actions workflow to detect CloudFormation drift per stack, upload machine‑readable results, and aggregate a summary.\n- `CdkDriftIamTemplate` — Emits a CloudFormation template file with minimal permissions for the Drift Detection workflow.\n\n## Quick start\n\n1) Add the constructs to your Projen project (in `.projenrc.ts`).\n2) Synthesize with `npx projen`.\n3) Commit the generated files.\n4) Open a pull request or run the drift detection workflow.\n\n## Usage: CdkDiffStackWorkflow\n\n`CdkDiffStackWorkflow` renders a workflow per stack named `diff-<StackName>.yml` under `.github/workflows/`. It also generates a helper script at `.github/workflows/scripts/describe-cfn-changeset.ts` that formats the change set output and takes care of posting the PR comment and Step Summary.\n\nExample `.projenrc.ts`:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDiffStackWorkflow } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ... your usual settings ...\n workflowName: 'my-lib',\n defaultReleaseBranch: 'main',\n cdkVersion: '2.85.0',\n github: true,\n});\n\nnew CdkDiffStackWorkflow({\n project,\n stacks: [\n {\n stackName: 'MyAppStack',\n changesetRoleToAssumeArn: 'arn:aws:iam::123456789012:role/cdk-diff-role',\n changesetRoleToAssumeRegion: 'us-east-1',\n // Optional per‑stack OIDC override (if not using the defaults below)\n // oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n // oidcRegion: 'us-east-1',\n },\n ],\n // Default OIDC role/region used by all stacks unless overridden per‑stack\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: Node version used in the workflow (default: '24.x')\n // nodeVersion: '24.x',\n // Optional: Yarn command to run CDK (default: 'cdk')\n // cdkYarnCommand: 'cdk',\n // Optional: Where to place the helper script (default: '.github/workflows/scripts/describe-cfn-changeset.ts')\n // scriptOutputPath: '.github/workflows/scripts/describe-cfn-changeset.ts',\n});\n\nproject.synth();\n```\n\n### CdkDiffStackWorkflow props\n- `project` (required) — Your Projen project instance.\n- `stacks` (required) — Array of stack entries.\n- `oidcRoleArn` (required unless provided per‑stack) — Default OIDC role ARN.\n- `oidcRegion` (required unless provided per‑stack) — Default OIDC region.\n- `nodeVersion` (optional, default `'24.x'`) — Node.js version for the workflow runner.\n- `cdkYarnCommand` (optional, default `'cdk'`) — Yarn script/command to invoke CDK.\n- `scriptOutputPath` (optional, default `'.github/workflows/scripts/describe-cfn-changeset.ts'`) — Where to write the helper script.\n\nIf neither top‑level OIDC defaults nor all per‑stack values are supplied, the construct throws a helpful error.\n\n### Stack item fields\n- `stackName` (required) — The CDK stack name to create the change set for.\n- `changesetRoleToAssumeArn` (required) — The ARN of the role used to create the change set (role chaining after OIDC).\n- `changesetRoleToAssumeRegion` (required) — The region for that role.\n- `oidcRoleArn` (optional) — Per‑stack override for the OIDC role.\n- `oidcRegion` (optional) — Per‑stack override for the OIDC region.\n\n### What gets generated\n- `.github/workflows/diff-<StackName>.yml` — One workflow per stack, triggered on PR open/sync/reopen.\n- `.github/workflows/scripts/describe-cfn-changeset.ts` — A helper script that:\n - Polls `DescribeChangeSet` until terminal\n - Filters out ignorable logical IDs or resource types using environment variables `IGNORE_LOGICAL_IDS` and `IGNORE_RESOURCE_TYPES`\n - Renders an HTML table with actions, logical IDs, types, replacements, and changed properties\n - Prints the HTML, appends to the GitHub Step Summary, and (if `GITHUB_TOKEN` and `GITHUB_COMMENT_URL` are present) posts a PR comment\n\n### Environment variables used by the change set script\n- `STACK_NAME` (required) — Stack name to describe.\n- `CHANGE_SET_NAME` (default: same as `STACK_NAME`).\n- `AWS_REGION` — Region for CloudFormation API calls. The workflow sets this via the credentials action(s).\n- `GITHUB_TOKEN` (optional) — If set with `GITHUB_COMMENT_URL`, posts a PR comment.\n- `GITHUB_COMMENT_URL` (optional) — PR comments URL.\n- `GITHUB_STEP_SUMMARY` (optional) — When present, appends the HTML to the step summary file.\n- `IGNORE_LOGICAL_IDS` (optional) — Comma‑separated logical IDs to ignore (default includes `CDKMetadata`).\n- `IGNORE_RESOURCE_TYPES` (optional) — Comma‑separated resource types to ignore (e.g., `AWS::CDK::Metadata`).\n\n## Usage: CdkDiffIamTemplate\n\nEmit an example IAM template you can deploy in your account for the Change Set workflow:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDiffIamTemplate } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ...\n});\n\nnew CdkDiffIamTemplate({\n project,\n roleName: 'cdk-diff-role',\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: custom output path (default: 'cdk-diff-workflow-iam-template.yaml')\n // outputPath: 'infra/cdk-diff-iam.yaml',\n});\n\nproject.synth();\n```\n\nThis writes `cdk-diff-workflow-iam-template.yaml` at the project root (or your chosen `outputPath`). The template defines:\n- Parameter `GitHubOIDCRoleArn` with a default from `oidcRoleArn` — the ARN of your existing GitHub OIDC role allowed to assume the change set role.\n- IAM role `CdkChangesetRole` with minimal permissions for:\n - CloudFormation Change Set operations\n - Access to common CDK bootstrap S3 buckets and SSM parameters\n - `iam:PassRole` to `cloudformation.amazonaws.com`\n- Outputs exporting the role name and ARN.\n\nA Projen task is also added:\n\n```bash\nnpx projen deploy-cdkdiff-iam-template -- --parameter-overrides GitHubOIDCRoleArn=... # plus any extra AWS CLI args\n```\n\nUse the created role ARN as `changesetRoleToAssumeArn` in `CdkDiffStackWorkflow`.\n\n---\n\n## Usage: CdkDriftDetectionWorkflow\n\n`CdkDriftDetectionWorkflow` creates a single workflow file (default `drift-detection.yml`) that can run on a schedule and via manual dispatch. It generates a helper script at `.github/workflows/scripts/detect-drift.ts` (by default) that uses AWS SDK v3 to run drift detection, write optional machine‑readable JSON, and print an HTML report for the Step Summary.\n\nExample `.projenrc.ts`:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDriftDetectionWorkflow } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({ github: true, /* ... */ });\n\nnew CdkDriftDetectionWorkflow({\n project,\n workflowName: 'Drift Detection', // optional; file name derived as 'drift-detection.yml'\n schedule: '0 1 * * *', // optional cron\n createIssues: true, // default true; create/update issue when drift detected on schedule\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: Node version (default '24.x')\n // nodeVersion: '24.x',\n // Optional: Where to place the helper script (default '.github/workflows/scripts/detect-drift.ts')\n // scriptOutputPath: '.github/workflows/scripts/detect-drift.ts',\n stacks: [\n {\n stackName: 'MyAppStack-Prod',\n driftDetectionRoleToAssumeArn: 'arn:aws:iam::123456789012:role/cdk-drift-role',\n driftDetectionRoleToAssumeRegion: 'us-east-1',\n // failOnDrift: true, // optional (default true)\n },\n ],\n});\n\nproject.synth();\n```\n\n### CdkDriftDetectionWorkflow props\n- `project` (required) — Your Projen project instance.\n- `stacks` (required) — Array of stacks to check.\n- `oidcRoleArn` (required) — Default OIDC role ARN used before chaining into per‑stack drift roles.\n- `oidcRegion` (required) — Default OIDC region.\n- `workflowName` (optional, default `'drift-detection'`) — Human‑friendly workflow name; the file name is derived in kebab‑case.\n- `schedule` (optional) — Cron expression for automatic runs.\n- `createIssues` (optional, default `true`) — When true, scheduled runs will create/update a GitHub issue if drift is detected.\n- `nodeVersion` (optional, default `'24.x'`) — Node.js version for the runner.\n- `scriptOutputPath` (optional, default `'.github/workflows/scripts/detect-drift.ts'`) — Where to write the helper script.\n\n### Per‑stack fields\n- `stackName` (required) — The full CloudFormation stack name.\n- `driftDetectionRoleToAssumeArn` (required) — Role to assume (after OIDC) for making drift API calls.\n- `driftDetectionRoleToAssumeRegion` (required) — Region for that role and API calls.\n- `failOnDrift` (optional, default `true`) — Intended to fail the detection step on drift. The provided script exits with non‑zero when drift is found; the job continues to allow artifact upload and issue creation.\n\n### What gets generated\n- `.github/workflows/<kebab(workflowName)>.yml` — A workflow with one job per stack plus a final summary job.\n- `.github/workflows/scripts/detect-drift.ts` — Helper script that:\n - Starts drift detection and polls until completion\n - Lists non‑`IN_SYNC` resources and builds an HTML report\n - Writes optional JSON to `DRIFT_DETECTION_OUTPUT` when set\n - Prints to stdout and appends to the GitHub Step Summary when available\n\n### Artifacts and summary\n- Each stack job uploads `drift-results-<stack>.json` (if produced).\n- A final `Drift Detection Summary` job downloads all artifacts and prints a consolidated summary.\n\nNote: The default workflow does not post PR comments for drift. It can create/update an Issue on scheduled runs when `createIssues` is `true`.\n\n### Post-notification steps (e.g., Slack)\n\nYou can add your own GitHub Action steps to run after the drift detection step for each stack using `postGitHubSteps`.\nThese steps receive a prepared Slack-compatible JSON payload via `${{ steps.notify.outputs.result }}` from an earlier step.\n\nExample: Send Slack notification (only when drift occurs) using slackapi/slack-github-action@v1\n\n```ts\nnew CdkDriftDetectionWorkflow({\n project,\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n stacks: [/* ... */],\n postGitHubSteps: ({ stack }) => {\n // Build a descriptive name per stack\n const name = `Notify Slack (${stack} post-drift)`;\n const step = {\n name,\n uses: 'slackapi/slack-github-action@v1',\n // by default, post steps run only when drift is detected; you can override `if`\n if: \"always() && steps.drift.outcome == 'failure'\",\n with: {\n payload: '${{ steps.notify.outputs.result }}',\n },\n env: {\n SLACK_WEBHOOK_URL: '${{ secrets.CDK_NOTIFICATIONS_SLACK_WEBHOOK }}',\n SLACK_WEBHOOK_TYPE: 'INCOMING_WEBHOOK',\n },\n };\n return [step];\n },\n});\n```\n\nDetails:\n- `postGitHubSteps` can be:\n - an array of step objects, or\n - a factory function `({ stack }) => step | step[]`.\n- Each step you provide is inserted after the results are uploaded and after a `Prepare notification payload` step.\n- The prepared payload is a Slack Block Kit JSON string summarizing results for that stack.\n- Default condition: if you do not set `if` on your step, it will default to `always() && steps.drift.outcome == 'failure'`.\n- Available context/env you can use:\n - `${{ env.STAGE_NAME }}`, `${{ env.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`\n - `${{ steps.notify.outputs.result }}` — Slack payload JSON\n```\n\n## Usage: CdkDriftIamTemplate\n\nEmit an example IAM template you can deploy in your account for the Drift Detection workflow:\n\n```ts\nimport { awscdk } from 'projen';\nimport { CdkDriftIamTemplate } from '@jjrawlins/cdk-diff-pr-github-action';\n\nconst project = new awscdk.AwsCdkConstructLibrary({\n // ...\n});\n\nnew CdkDriftIamTemplate({\n project,\n roleName: 'cdk-drift-role',\n oidcRoleArn: 'arn:aws:iam::123456789012:role/github-oidc-role',\n oidcRegion: 'us-east-1',\n // Optional: custom output path (default: 'cdk-drift-workflow-iam-template.yaml')\n // outputPath: 'infra/cdk-drift-iam.yaml',\n});\n\nproject.synth();\n```\n\nThis writes `cdk-drift-workflow-iam-template.yaml` at the project root (or your chosen `outputPath`). The template defines:\n- Parameter `GitHubOIDCRoleArn` with a default from `oidcRoleArn` — the ARN of your existing GitHub OIDC role allowed to assume this drift role.\n- IAM role `CdkDriftRole` with minimal permissions for CloudFormation drift detection operations.\n- Outputs exporting the role name and ARN.\n\nA Projen task is also added:\n\n```bash\nnpx projen deploy-cdkdrift-iam-template -- --parameter-overrides GitHubOIDCRoleArn=... # plus any extra AWS CLI args\n```\n\n## Testing\n\nThis repository includes Jest tests that snapshot the synthesized outputs from Projen and assert that:\n- Diff workflows are created per stack and contain all expected steps.\n- Drift detection workflow produces one job per stack and a summary job.\n- Only one helper script file is generated per workflow type.\n- Per‑stack OIDC overrides (where supported) are respected.\n- Helpful validation errors are thrown for missing OIDC settings.\n- The IAM template files contain the expected resources and outputs.\n\nRun tests with:\n\n```bash\nyarn test\n```\n\n## Notes\n- This package assumes your repository is configured with GitHub Actions and that you have a GitHub OIDC role configured in AWS.\n- The generated scripts use the AWS SDK v3 for CloudFormation and, where applicable, the GitHub REST API.\n"
|
|
3552
3552
|
},
|
|
3553
3553
|
"repository": {
|
|
3554
3554
|
"type": "git",
|
|
@@ -3952,7 +3952,7 @@
|
|
|
3952
3952
|
},
|
|
3953
3953
|
"locationInModule": {
|
|
3954
3954
|
"filename": "src/CdkDriftDetectionWorkflow.ts",
|
|
3955
|
-
"line":
|
|
3955
|
+
"line": 60
|
|
3956
3956
|
},
|
|
3957
3957
|
"parameters": [
|
|
3958
3958
|
{
|
|
@@ -3966,7 +3966,7 @@
|
|
|
3966
3966
|
"kind": "class",
|
|
3967
3967
|
"locationInModule": {
|
|
3968
3968
|
"filename": "src/CdkDriftDetectionWorkflow.ts",
|
|
3969
|
-
"line":
|
|
3969
|
+
"line": 57
|
|
3970
3970
|
},
|
|
3971
3971
|
"name": "CdkDriftDetectionWorkflow",
|
|
3972
3972
|
"symbolId": "src/CdkDriftDetectionWorkflow:CdkDriftDetectionWorkflow"
|
|
@@ -4092,17 +4092,12 @@
|
|
|
4092
4092
|
"immutable": true,
|
|
4093
4093
|
"locationInModule": {
|
|
4094
4094
|
"filename": "src/CdkDriftDetectionWorkflow.ts",
|
|
4095
|
-
"line":
|
|
4095
|
+
"line": 42
|
|
4096
4096
|
},
|
|
4097
4097
|
"name": "postGitHubSteps",
|
|
4098
4098
|
"optional": true,
|
|
4099
4099
|
"type": {
|
|
4100
|
-
"
|
|
4101
|
-
"elementtype": {
|
|
4102
|
-
"primitive": "any"
|
|
4103
|
-
},
|
|
4104
|
-
"kind": "array"
|
|
4105
|
-
}
|
|
4100
|
+
"primitive": "any"
|
|
4106
4101
|
}
|
|
4107
4102
|
},
|
|
4108
4103
|
{
|
|
@@ -4360,5 +4355,5 @@
|
|
|
4360
4355
|
}
|
|
4361
4356
|
},
|
|
4362
4357
|
"version": "0.0.0",
|
|
4363
|
-
"fingerprint": "
|
|
4358
|
+
"fingerprint": "yVjbJc1xBpssBwA7ahpKgmDWam2nx+ZuK3/USb9138Y="
|
|
4364
4359
|
}
|
package/README.md
CHANGED
|
@@ -246,9 +246,9 @@ new CdkDriftDetectionWorkflow({
|
|
|
246
246
|
Details:
|
|
247
247
|
- `postGitHubSteps` can be:
|
|
248
248
|
- an array of step objects, or
|
|
249
|
-
- a factory function `({ stack
|
|
249
|
+
- a factory function `({ stack }) => step | step[]`.
|
|
250
250
|
- Each step you provide is inserted after the results are uploaded and after a `Prepare notification payload` step.
|
|
251
|
-
- The prepared payload is a Slack Block Kit JSON string summarizing results for that stack
|
|
251
|
+
- The prepared payload is a Slack Block Kit JSON string summarizing results for that stack.
|
|
252
252
|
- Default condition: if you do not set `if` on your step, it will default to `always() && steps.drift.outcome == 'failure'`.
|
|
253
253
|
- Available context/env you can use:
|
|
254
254
|
- `${{ env.STAGE_NAME }}`, `${{ env.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`
|
|
@@ -23,7 +23,7 @@ export interface CdkDriftDetectionWorkflowProps {
|
|
|
23
23
|
* These steps are inserted after a 'Prepare notification payload' step which exposes
|
|
24
24
|
* a Slack-compatible JSON payload at `${{ steps.notify.outputs.result }}`.
|
|
25
25
|
*/
|
|
26
|
-
readonly postGitHubSteps?: any
|
|
26
|
+
readonly postGitHubSteps?: any;
|
|
27
27
|
}
|
|
28
28
|
export declare class CdkDriftDetectionWorkflow {
|
|
29
29
|
private static scriptCreated;
|
|
@@ -47,7 +47,6 @@ class CdkDriftDetectionWorkflow {
|
|
|
47
47
|
});
|
|
48
48
|
// One job per stack
|
|
49
49
|
const jobs = {};
|
|
50
|
-
const postSteps = Array.isArray(props.postGitHubSteps) ? props.postGitHubSteps : [];
|
|
51
50
|
for (const stack of props.stacks) {
|
|
52
51
|
const sanitizedStackName = toKebabCase(toGithubJobId(stack.stackName));
|
|
53
52
|
const originalStackName = stack.stackName;
|
|
@@ -56,6 +55,8 @@ class CdkDriftDetectionWorkflow {
|
|
|
56
55
|
const innerCond = "github.event_name == 'schedule' || !github.event.inputs.stack || github.event.inputs.stack == '" + sanitizedStackName + "' || github.event.inputs.stack == '" + originalStackName + "'";
|
|
57
56
|
const condExpr = '${{ ' + innerCond + ' }}';
|
|
58
57
|
const notCondExpr = '${{ !(' + innerCond + ') }}';
|
|
58
|
+
const rawPost = props.postGitHubSteps;
|
|
59
|
+
const postSteps = typeof rawPost === 'function' ? rawPost({ stack: sanitizedStackName }) : (rawPost ?? []);
|
|
59
60
|
jobs[jobId] = {
|
|
60
61
|
name: `Drift Detection - ${sanitizedStackName}`,
|
|
61
62
|
runsOn: ['ubuntu-latest'],
|
|
@@ -316,4 +317,4 @@ function toGithubJobId(s) {
|
|
|
316
317
|
}
|
|
317
318
|
return out;
|
|
318
319
|
}
|
|
319
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9DZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsOENBQTJEO0FBQzNELHVFQUFrRTtBQUNsRSxpRkFBMkU7QUFFM0UsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSxvQ0FBb0MsR0FBRyxJQUFJLENBQUM7QUFDbEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLENBQUM7QUErQjlDLE1BQWEseUJBQXlCO0lBR3BDLFlBQVksS0FBcUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxpQkFBaUIsQ0FBQztRQUNyRCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQzVDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDO1FBQ2hELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDOUIsTUFBTSxnQkFBZ0IsR0FBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksMkNBQTJDLENBQUM7UUFFOUYsa0VBQWtFO1FBQ2xFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM3QyxJQUFJLG9EQUF1QixDQUFDO2dCQUMxQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7YUFDN0IsQ0FBQyxDQUFDO1lBQ0gseUJBQXlCLENBQUMsYUFBYSxH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QUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzdDLGlDQUFpQztJQUNqQyxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUIscUVBQXFFO0lBQ3JFLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsQyxnRkFBZ0Y7SUFDaEYsR0FBRyxHQUFHLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4QixrREFBa0Q7SUFDbEQsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxHQUFHLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR2l0SHViLCBHaXRodWJXb3JrZmxvdyB9IGZyb20gJ3Byb2plbi9saWIvZ2l0aHViJztcbmltcG9ydCB7IEpvYlBlcm1pc3Npb24gfSBmcm9tICdwcm9qZW4vbGliL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWwnO1xuaW1wb3J0IHsgQ2RrRHJpZnREZXRlY3Rpb25TY3JpcHQgfSBmcm9tICcuL2Jpbi9jZGstZHJpZnQtZGV0ZWN0aW9uLXNjcmlwdCc7XG5cbmNvbnN0IGdpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb24gPSAndjUnO1xuY29uc3QgZ2l0aHViQWN0aW9uc0NoZWNrb3V0VmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zVXBsb2FkQXJ0aWZhY3RWZXJzaW9uID0gJ3Y0JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNEb3dubG9hZEFydGlmYWN0VmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zR2l0aHViU2NyaXB0VmVyc2lvbiA9ICd2OCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2sge1xuICByZWFkb25seSBzdGFja05hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb246IHN0cmluZztcbiAgcmVhZG9ubHkgZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm46IHN0cmluZztcbiAgcmVhZG9ubHkgZmFpbE9uRHJpZnQ/OiBib29sZWFuOyAvLyBpZiB0cnVlLCBmYWlsIGpvYiB3aGVuIGRyaWZ0IGRldGVjdGVkIChkZWZhdWx0IHRydWUpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvd1Byb3BzIHtcbiAgcmVhZG9ubHkgc2NyaXB0T3V0cHV0UGF0aD86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvamVjdDogYW55OyAvLyBhdm9pZCBleHBvcnRpbmcgcHJvamVuIHR5cGVzIGluIHB1YmxpYyBBUElcbiAgcmVhZG9ubHkgd29ya2Zsb3dOYW1lPzogc3RyaW5nOyAvLyB3b3JrZmxvdyB3b3JrZmxvd05hbWUgKGFsc28gdXNlZCB0byBkZXJpdmUgZmlsZSB3b3JrZmxvd05hbWUpXG4gIHJlYWRvbmx5IHNjaGVkdWxlPzogc3RyaW5nOyAvLyBjcm9uIGV4cHJlc3Npb24sIGUuZy4gJzAgMCAqICogKidcbiAgcmVhZG9ubHkgY3JlYXRlSXNzdWVzPzogYm9vbGVhbjsgLy8gY3JlYXRlL3VwZGF0ZSBpc3N1ZSB3aGVuIGRyaWZ0IGRldGVjdGVkIG9uIHNjaGVkdWxlIChkZWZhdWx0IHRydWUpXG4gIHJlYWRvbmx5IG9pZGNSb2xlQXJuOiBzdHJpbmc7IC8vIGRlZmF1bHQgT0lEQyByb2xlIEFSTiB0byBhc3N1bWUgZm9yIGFsbCBzdGFja3NcbiAgcmVhZG9ubHkgb2lkY1JlZ2lvbjogc3RyaW5nOyAvLyBkZWZhdWx0IE9JREMgcmVnaW9uIHRvIGFzc3VtZSBmb3IgYWxsIHN0YWNrc1xuICByZWFkb25seSBzdGFja3M6IFN0YWNrW107XG4gIHJlYWRvbmx5IG5vZGVWZXJzaW9uPzogc3RyaW5nOyAvLyBlLmcuLCAnMjQueCdcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGhvb2sgdG8gYXBwZW5kIGFkZGl0aW9uYWwgR2l0SHViIEFjdGlvbnMgc3RlcHMgYWZ0ZXIgZHJpZnQgZGV0ZWN0aW9uIHBlciBzdGFjay5cbiAgICogWW91IGNhbiBzdXBwbHkgYSBzdGF0aWMgYXJyYXkgb2Ygc3RlcHMsIG9yIGEgZmFjdG9yeSB0aGF0IHJlY2VpdmVzIGNvbnRleHQgYW5kIHJldHVybnMgc3RlcHMuXG4gICAqL1xuICAvKipcbiAgICogT3B0aW9uYWwgYWRkaXRpb25hbCBHaXRIdWIgQWN0aW9uIHN0ZXBzIHRvIHJ1biBhZnRlciBkcmlmdCBkZXRlY3Rpb24gZm9yIGVhY2ggc3RhY2suXG4gICAqIFRoZXNlIHN0ZXBzIGFyZSBpbnNlcnRlZCBhZnRlciBhICdQcmVwYXJlIG5vdGlmaWNhdGlvbiBwYXlsb2FkJyBzdGVwIHdoaWNoIGV4cG9zZXNcbiAgICogYSBTbGFjay1jb21wYXRpYmxlIEpTT04gcGF5bG9hZCBhdCBgJHt7IHN0ZXBzLm5vdGlmeS5vdXRwdXRzLnJlc3VsdCB9fWAuXG4gICAqL1xuICByZWFkb25seSBwb3N0R2l0SHViU3RlcHM/OiBhbnlbXTtcbn1cblxuZXhwb3J0IGNsYXNzIENka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3cge1xuICBwcml2YXRlIHN0YXRpYyBzY3JpcHRDcmVhdGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IENka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3dQcm9wcykge1xuICAgIGNvbnN0IG5hbWUgPSBwcm9wcy53b3JrZmxvd05hbWUgPz8gJ2RyaWZ0LWRldGVjdGlvbic7XG4gICAgY29uc3QgZmlsZU5hbWUgPSB0b0tlYmFiQ2FzZShuYW1lKSArICcueW1sJztcbiAgICBjb25zdCBub2RlVmVyc2lvbiA9IHByb3BzLm5vZGVWZXJzaW9uID8/ICcyNC54JztcbiAgICBjb25zdCBjcmVhdGVJc3N1ZXMgPSBwcm9wcy5jcmVhdGVJc3N1ZXMgPz8gdHJ1ZTtcbiAgICBjb25zdCBwcm9qZWN0ID0gcHJvcHMucHJvamVjdDtcbiAgICBjb25zdCBzY3JpcHRPdXRwdXRQYXRoPSBwcm9wcy5zY3JpcHRPdXRwdXRQYXRoID8/ICcuZ2l0aHViL3dvcmtmbG93cy9zY3JpcHRzL2RldGVjdC1kcmlmdC50cyc7XG5cbiAgICAvLyBPbmx5IGNyZWF0ZSB0aGUgZHJpZnQgZGV0ZWN0aW9uIHNjcmlwdCBvbmNlIHRvIGF2b2lkIGNvbGxpc2lvbnNcbiAgICBpZiAoIUNka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3cuc2NyaXB0Q3JlYXRlZCkge1xuICAgICAgbmV3IENka0RyaWZ0RGV0ZWN0aW9uU2NyaXB0KHtcbiAgICAgICAgcHJvamVjdDogcHJvcHMucHJvamVjdCxcbiAgICAgICAgb3V0cHV0UGF0aDogc2NyaXB0T3V0cHV0UGF0aCxcbiAgICAgIH0pO1xuICAgICAgQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5zY3JpcHRDcmVhdGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBnaCA9IChwcm9qZWN0IGFzIGFueSkuZ2l0aHViID8/IG5ldyBHaXRIdWIocHJvamVjdCk7XG4gICAgY29uc3Qgd29ya2Zsb3cgPSBuZXcgR2l0aHViV29ya2Zsb3coZ2gsIG5hbWUsIHsgZmlsZU5hbWUgfSk7XG5cbiAgICAvLyB0cmlnZ2Vyczogc2NoZWR1bGUgKyBtYW51YWwgZGlzcGF0Y2ggd2l0aCBzdGFjayBjaG9pY2VcbiAgICBjb25zdCBzdGFja0Nob2ljZXMgPSBwcm9wcy5zdGFja3MubWFwKChzKSA9PiBzLnN0YWNrTmFtZSk7XG4gICAgd29ya2Zsb3cub24oe1xuICAgICAgc2NoZWR1bGU6IHByb3BzLnNjaGVkdWxlID8gW3sgY3JvbjogcHJvcHMuc2NoZWR1bGUgfV0gOiB1bmRlZmluZWQsXG4gICAgICB3b3JrZmxvd0Rpc3BhdGNoOiB7XG4gICAgICAgIGlucHV0czoge1xuICAgICAgICAgIHN0YWNrOiB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogJ1N0YWNrIHRvIGNoZWNrIGZvciBkcmlmdCAobGVhdmUgZW1wdHkgZm9yIGFsbCknLFxuICAgICAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgICAgICAgdHlwZTogJ2Nob2ljZScsXG4gICAgICAgICAgICBvcHRpb25zOiBzdGFja0Nob2ljZXMsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBPbmUgam9iIHBlciBzdGFja1xuICAgIGNvbnN0IGpvYnM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcblxuICAgIGNvbnN0IHBvc3RTdGVwczogYW55W10gPSBBcnJheS5pc0FycmF5KChwcm9wcyBhcyBhbnkpLnBvc3RHaXRIdWJTdGVwcykgPyAocHJvcHMgYXMgYW55KS5wb3N0R2l0SHViU3RlcHMgOiBbXTtcblxuICAgIGZvciAoY29uc3Qgc3RhY2sgb2YgcHJvcHMuc3RhY2tzKSB7XG4gICAgICBjb25zdCBzYW5pdGl6ZWRTdGFja05hbWUgPSB0b0tlYmFiQ2FzZSh0b0dpdGh1YkpvYklkKHN0YWNrLnN0YWNrTmFtZSkpO1xuICAgICAgY29uc3Qgb3JpZ2luYWxTdGFja05hbWUgPSBzdGFjay5zdGFja05hbWU7XG4gICAgICBjb25zdCBqb2JJZCA9IGBkcmlmdC0ke3Nhbml0aXplZFN0YWNrTmFtZX1gO1xuICAgICAgY29uc3QgcmVzdWx0c0ZpbGUgPSBgZHJpZnQtcmVzdWx0cy0ke3Nhbml0aXplZFN0YWNrTmFtZX0uanNvbmA7XG4gICAgICBjb25zdCBpbm5lckNvbmQgPSBcImdpdGh1Yi5ldmVudF9uYW1lID09ICdzY2hlZHVsZScgfHwgIWdpdGh1Yi5ldmVudC5pbnB1dHMuc3RhY2sgfHwgZ2l0aHViLmV2ZW50LmlucHV0cy5zdGFjayA9PSAnXCIgKyBzYW5pdGl6ZWRTdGFja05hbWUgKyBcIicgfHwgZ2l0aHViLmV2ZW50LmlucHV0cy5zdGFjayA9PSAnXCIgKyBvcmlnaW5hbFN0YWNrTmFtZSArIFwiJ1wiO1xuICAgICAgY29uc3QgY29uZEV4cHIgPSAnJHt7ICcgKyBpbm5lckNvbmQgKyAnIH19JztcbiAgICAgIGNvbnN0IG5vdENvbmRFeHByID0gJyR7eyAhKCcgKyBpbm5lckNvbmQgKyAnKSB9fSc7XG5cbiAgICAgIGpvYnNbam9iSWRdID0ge1xuICAgICAgICBuYW1lOiBgRHJpZnQgRGV0ZWN0aW9uIC0gJHtzYW5pdGl6ZWRTdGFja05hbWV9YCxcbiAgICAgICAgcnVuc09uOiBbJ3VidW50dS1sYXRlc3QnXSxcbiAgICAgICAgcGVybWlzc2lvbnM6IHtcbiAgICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgICAgIGlkVG9rZW46IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgICAgaXNzdWVzOiBKb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgICB9LFxuICAgICAgICBlbnY6IHtcbiAgICAgICAgICBBV1NfREVGQVVMVF9SRUdJT046IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgIEFXU19SRUdJT046IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgIERSSUZUX0RFVEVDVElPTl9PVVRQVVQ6IHJlc3VsdHNGaWxlLFxuICAgICAgICAgIFNUQUdFX05BTUU6IHNhbml0aXplZFN0YWNrTmFtZSxcbiAgICAgICAgICBTVEFDS19OQU1FOiBzdGFjay5zdGFja05hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIC8vIE5vIGpvYi1sZXZlbCBjb25kaXRpb247IHdlIGdhdGUgc3RlcHMgc28gdGhlIGpvYiBhbHdheXMgY29tcGxldGVzIGFuZCBzdW1tYXJ5IGNhbiBydW5cbiAgICAgICAgc3RlcHM6IFtcbiAgICAgICAgICB7IG5hbWU6ICdTa2lwIChzdGFjayBub3Qgc2VsZWN0ZWQpJywgaWY6IG5vdENvbmRFeHByLCBydW46ICdlY2hvIFwiU3RhZ2Ugbm90IHNlbGVjdGVkOyBza2lwcGluZyBkcmlmdCBkZXRlY3Rpb24gZm9yIHRoaXMgam9iLlwiJyB9LFxuICAgICAgICAgIHsgbmFtZTogJ0NoZWNrb3V0JywgaWY6IGNvbmRFeHByLCB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke2dpdGh1YkFjdGlvbnNDaGVja291dFZlcnNpb259YCB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3NldHVwLW5vZGVAJHtnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbn1gLFxuICAgICAgICAgICAgd2l0aDogeyAnbm9kZS12ZXJzaW9uJzogbm9kZVZlcnNpb24gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbmFtZTogJ0luc3RhbGwgZGVwZW5kZW5jaWVzJywgaWY6IGNvbmRFeHByLCBydW46ICd5YXJuIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGUgfHwgbnBtIGNpJywgZW52OiB7IEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdBV1MgQ3JlZGVudGlhbHMnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdjcmVkcycsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogcHJvcHMub2lkY1JvbGVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLXNlc3Npb24tbmFtZSc6ICdHaXRIdWJBY3Rpb24nLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHByb3BzLm9pZGNSZWdpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0Fzc3VtZSBEcmlmdCBEZXRlY3Rpb24gUm9sZScsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLWNoYWluaW5nJzogdHJ1ZSxcbiAgICAgICAgICAgICAgJ3JvbGUtc2tpcC1zZXNzaW9uLXRhZ2dpbmcnOiB0cnVlLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgICAgICAnYXdzLWFjY2Vzcy1rZXktaWQnOiAnJHt7IHN0ZXBzLmNyZWRzLm91dHB1dHMuYXdzLWFjY2Vzcy1rZXktaWQgfX0nLFxuICAgICAgICAgICAgICAnYXdzLXNlY3JldC1hY2Nlc3Mta2V5JzogJyR7eyBzdGVwcy5jcmVkcy5vdXRwdXRzLmF3cy1zZWNyZXQtYWNjZXNzLWtleSB9fScsXG4gICAgICAgICAgICAgICdhd3Mtc2Vzc2lvbi10b2tlbic6ICcke3sgc3RlcHMuY3JlZHMub3V0cHV0cy5hd3Mtc2Vzc2lvbi10b2tlbiB9fScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0RldGVjdCBkcmlmdCcsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICBpZDogJ2RyaWZ0JyxcbiAgICAgICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSwgLy8gYWxsb3cgYXJ0aWZhY3QgdXBsb2FkIGFuZCBpc3N1ZSBjcmVhdGlvbiBldmVuIHdoZW4gZHJpZnQgaXMgZGV0ZWN0ZWRcbiAgICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgICAnc2V0IC1lJyxcbiAgICAgICAgICAgICAgLy8gVXNlIHRoZSBidW5kbGVkIHNjcmlwdCBmcm9tIHRoaXMgcGFja2FnZVxuICAgICAgICAgICAgICAnbm9kZSAuL25vZGVfbW9kdWxlcy9AampyYXdsaW5zL2Nkay1kaWZmLXByLWdpdGh1Yi1hY3Rpb24vbGliL2Jpbi9kZXRlY3QtZHJpZnQuanMnLFxuICAgICAgICAgICAgICAnaWYgWyAtZiBcIiREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCIgXTsgdGhlbiBlY2hvIFwiUmVzdWx0cyBmaWxlIGNyZWF0ZWQ6ICREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCI7IGZpJyxcbiAgICAgICAgICAgIF0uam9pbignXFxuJyksXG4gICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgU1RBQ0tfTkFNRTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICAgICAgICBBV1NfUkVHSU9OOiBzdGFjay5kcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbixcbiAgICAgICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1VwbG9hZCByZXN1bHRzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3VwbG9hZC1hcnRpZmFjdEAke2dpdGh1YkFjdGlvbnNVcGxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHsgbmFtZTogYGRyaWZ0LXJlc3VsdHMtJHtzYW5pdGl6ZWRTdGFja05hbWV9YCwgcGF0aDogcmVzdWx0c0ZpbGUsIGlmTm9GaWxlc0ZvdW5kOiAnaWdub3JlJyB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1ByZXBhcmUgbm90aWZpY2F0aW9uIHBheWxvYWQnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdub3RpZnknLFxuICAgICAgICAgICAgdXNlczogYGFjdGlvbnMvZ2l0aHViLXNjcmlwdEAke2dpdGh1YkFjdGlvbnNHaXRodWJTY3JpcHRWZXJzaW9ufWAsXG4gICAgICAgICAgICB3aXRoOiB7XG4gICAgICAgICAgICAgICdyZXN1bHQtZW5jb2RpbmcnOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgJ3NjcmlwdCc6IG5vdGlmaWNhdGlvblNjcmlwdChzYW5pdGl6ZWRTdGFja05hbWUsIHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLCByZXN1bHRzRmlsZSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4ucG9zdFN0ZXBzLm1hcCgoc3RlcCkgPT4gKHtcbiAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIG9ubHkgcnVuIGV4dHJhIG5vdGlmaWNhdGlvbiBzdGVwcyB3aGVuIGRyaWZ0IG9jY3Vyc1xuICAgICAgICAgICAgaWY6IChzdGVwIGFzIGFueSkuaWYgPz8gXCJhbHdheXMoKSAmJiBzdGVwcy5kcmlmdC5vdXRjb21lID09ICdmYWlsdXJlJ1wiLFxuICAgICAgICAgICAgLi4uKHN0ZXAgYXMgYW55KSxcbiAgICAgICAgICB9KSksXG4gICAgICAgICAgLi4uKFxuICAgICAgICAgICAgY3JlYXRlSXNzdWVzXG4gICAgICAgICAgICAgID8gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG5hbWU6ICdDcmVhdGUgSXNzdWUgb24gRHJpZnQnLFxuICAgICAgICAgICAgICAgICAgaWY6IFwiYWx3YXlzKCkgJiYgc3RlcHMuZHJpZnQub3V0Y29tZSA9PSAnZmFpbHVyZSdcIixcbiAgICAgICAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL2dpdGh1Yi1zY3JpcHRAJHtnaXRodWJBY3Rpb25zR2l0aHViU2NyaXB0VmVyc2lvbn1gLFxuICAgICAgICAgICAgICAgICAgd2l0aDogeyBzY3JpcHQ6IGlzc3VlU2NyaXB0KHNhbml0aXplZFN0YWNrTmFtZSwgc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sIHJlc3VsdHNGaWxlKSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgOiBbXVxuICAgICAgICAgICksXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIHN1bW1hcnkgYWdncmVnYXRvciBqb2JcbiAgICBqb2JzWydkcmlmdC1zdW1tYXJ5J10gPSB7XG4gICAgICBuYW1lOiAnRHJpZnQgRGV0ZWN0aW9uIFN1bW1hcnknLFxuICAgICAgbmVlZHM6IE9iamVjdC5rZXlzKGpvYnMpLmZpbHRlcigoaikgPT4gai5zdGFydHNXaXRoKCdkcmlmdC0nKSAmJiBqICE9PSAnZHJpZnQtc3VtbWFyeScpLFxuICAgICAgcnVuc09uOiBbJ3VidW50dS1sYXRlc3QnXSxcbiAgICAgIHBlcm1pc3Npb25zOiB7IGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLlJFQUQgfSxcbiAgICAgIHN0ZXBzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnRG93bmxvYWQgYWxsIGFydGlmYWN0cycsXG4gICAgICAgICAgdXNlczogYGFjdGlvbnMvZG93bmxvYWQtYXJ0aWZhY3RAJHtnaXRodWJBY3Rpb25zRG93bmxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICB3aXRoOiB7IHBhdGg6ICdkcmlmdC1yZXN1bHRzJyB9LFxuICAgICAgICB9LFxuICAgICAgICB7IG5hbWU6ICdHZW5lcmF0ZSBzdW1tYXJ5Jywgc2hlbGw6ICdiYXNoJywgcnVuOiBzdW1tYXJ5U2NyaXB0KCkgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIHdvcmtmbG93LmFkZEpvYnMoam9icyk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBpc3N1ZVNjcmlwdChzdGFnZTogc3RyaW5nLCByZWdpb246IHN0cmluZywgcmVzdWx0c0ZpbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIENvbnN0cnVjdCBhIHBsYWluIEpTIHNjcmlwdCBzdHJpbmcgKG5vIHRlbXBsYXRlIHN0cmluZyBuZXN0aW5nIG1pc2hhcHMpXG4gIGNvbnN0IGxpbmVzID0gW1xuICAgIFwiY29uc3QgZnMgPSByZXF1aXJlKCdmcycpO1wiLFxuICAgIGBjb25zdCByZXN1bHRzRmlsZSA9ICcke3Jlc3VsdHNGaWxlfSc7YCxcbiAgICBcImlmICghZnMuZXhpc3RzU3luYyhyZXN1bHRzRmlsZSkpIHsgY29uc29sZS5sb2coJ05vIHJlc3VsdHMgZmlsZSBmb3VuZCcpOyByZXR1cm47IH1cIixcbiAgICBcImNvbnN0IHJlc3VsdHMgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhyZXN1bHRzRmlsZSwgJ3V0ZjgnKSk7XCIsXG4gICAgXCJjb25zdCBkcmlmdGVkU3RhY2tzID0gcmVzdWx0cy5maWx0ZXIociA9PiByLmRyaWZ0U3RhdHVzID09PSAnRFJJRlRFRCcpO1wiLFxuICAgIFwiaWYgKGRyaWZ0ZWRTdGFja3MubGVuZ3RoID09PSAwKSB7IGNvbnNvbGUubG9nKCdObyBkcmlmdCBkZXRlY3RlZCcpOyByZXR1cm47IH1cIixcbiAgICBgY29uc3QgdGl0bGUgPSAnRHJpZnQgRGV0ZWN0ZWQgaW4gJHtzdGFnZX0nO2AsXG4gICAgYGxldCBib2R5ID0gJyMjIERyaWZ0IERldGVjdGlvbiBSZXBvcnRcXFxcblxcXFxuJyArICcqKlN0YWdlOioqICR7c3RhZ2V9XFxcXG4nICsgJyoqUmVnaW9uOioqICR7cmVnaW9ufVxcXFxuJyArICcqKlRpbWU6KiogJyArIG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSArICdcXFxcblxcXFxuJztgLFxuICAgIFwiYm9keSArPSAnIyMjIFN1bW1hcnlcXFxcbic7XCIsXG4gICAgXCJib2R5ICs9ICctIFRvdGFsIHN0YWNrcyBjaGVja2VkOiAnICsgcmVzdWx0cy5sZW5ndGggKyAnXFxcXG4nO1wiLFxuICAgIFwiYm9keSArPSAnLSBEcmlmdGVkIHN0YWNrczogJyArIGRyaWZ0ZWRTdGFja3MubGVuZ3RoICsgJ1xcXFxuXFxcXG4nO1wiLFxuICAgIFwiYm9keSArPSAnIyMjIERyaWZ0ZWQgU3RhY2tzXFxcXG4nO1wiLFxuICAgICdmb3IgKGNvbnN0IHMgb2YgZHJpZnRlZFN0YWNrcykgeycsXG4gICAgJyAgY29uc3QgcmVzb3VyY2VzID0gcy5kcmlmdGVkUmVzb3VyY2VzIHx8IFtdOycsXG4gICAgXCIgIGJvZHkgKz0gJyMjIyMgJyArIHMuc3RhY2tOYW1lICsgJ1xcXFxuJztcIixcbiAgICBcIiAgYm9keSArPSAnLSBEcmlmdGVkIHJlc291cmNlczogJyArIHJlc291cmNlcy5sZW5ndGggKyAnXFxcXG4nO1wiLFxuICAgIFwiICBmb3IgKGNvbnN0IHIgb2YgcmVzb3VyY2VzKSB7IGJvZHkgKz0gJyAgLSAnICsgci5sb2dpY2FsUmVzb3VyY2VJZCArICcgKCcgKyByLnJlc291cmNlVHlwZSArICcpXFxcXG4nOyB9XCIsXG4gICAgXCIgIGJvZHkgKz0gJ1xcXFxuJztcIixcbiAgICAnfScsXG4gICAgXCJib2R5ICs9ICcjIyMgQWN0aW9uIFJlcXVpcmVkXFxcXG4nICsgJ1BsZWFzZSByZXZpZXcgdGhlIGRyaWZ0ZWQgcmVzb3VyY2VzIGFuZCBlaXRoZXI6XFxcXG4xLiBVcGRhdGUgdGhlIGluZnJhc3RydWN0dXJlIGNvZGUgdG8gbWF0Y2ggdGhlIGFjdHVhbCBzdGF0ZVxcXFxuMi4gUmVzdG9yZSB0aGUgcmVzb3VyY2VzIHRvIG1hdGNoIHRoZSBleHBlY3RlZCBzdGF0ZVxcXFxuXFxcXG4nO1wiLFxuICAgICdib2R5ICs9IGBbVmlldyB3b3JrZmxvdyBydW5dKCR7Y29udGV4dC5zZXJ2ZXJVcmx9LyR7Y29udGV4dC5yZXBvLm93bmVyfS8ke2NvbnRleHQucmVwby5yZXBvfS9hY3Rpb25zL3J1bnMvJHtjb250ZXh0LnJ1bklkfSlgOycsXG4gICAgLy8gTGlzdCBvciB1cGRhdGUgYW4gaXNzdWUgd2l0aCBsYWJlbHNcbiAgICBgY29uc3QgaXNzdWVzID0gYXdhaXQgZ2l0aHViLnJlc3QuaXNzdWVzLmxpc3RGb3JSZXBvKHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIHN0YXRlOiAnb3BlbicsIGxhYmVsczogWydkcmlmdC1kZXRlY3Rpb24nLCAnJHtzdGFnZX0nXSB9KTtgLFxuICAgICdpZiAoaXNzdWVzLmRhdGEubGVuZ3RoID09PSAwKSB7JyxcbiAgICBgICBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlKHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIHRpdGxlLCBib2R5LCBsYWJlbHM6IFsnZHJpZnQtZGV0ZWN0aW9uJywgJyR7c3RhZ2V9J10gfSk7YCxcbiAgICAnfSBlbHNlIHsnLFxuICAgICcgIGNvbnN0IGlzc3VlID0gaXNzdWVzLmRhdGFbMF07JyxcbiAgICAnICBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlQ29tbWVudCh7IG93bmVyOiBjb250ZXh0LnJlcG8ub3duZXIsIHJlcG86IGNvbnRleHQucmVwby5yZXBvLCBpc3N1ZV9udW1iZXI6IGlzc3VlLm51bWJlciwgYm9keSB9KTsnLFxuICAgICd9JyxcbiAgXTtcbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuXG5mdW5jdGlvbiBub3RpZmljYXRpb25TY3JpcHQoc3RhZ2U6IHN0cmluZywgcmVnaW9uOiBzdHJpbmcsIHJlc3VsdHNGaWxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsaW5lcyA9IFtcbiAgICBcImNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTtcIixcbiAgICBgY29uc3QgcmVzdWx0c0ZpbGUgPSAnJHtyZXN1bHRzRmlsZX0nO2AsXG4gICAgJ2xldCBwYXlsb2FkOycsXG4gICAgJ2lmICghZnMuZXhpc3RzU3luYyhyZXN1bHRzRmlsZSkpIHsnLFxuICAgICcgIHBheWxvYWQgPSB7IHRleHQ6IGBEcmlmdCBEZXRlY3Rpb24gKCR7c3RhY2t9KSAtIE5vIHJlc3VsdHMgZm91bmRgLCBibG9ja3M6IFsnLFxuICAgIFwiICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiBgKkRyaWZ0IERldGVjdGlvbiAoJHtzdGFja30pKmAgfSB9LFwiLFxuICAgIFwiICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiAnTm8gcmVzdWx0cyBmaWxlIGZvdW5kLiBUaGUgZGV0ZWN0aW9uIHN0ZXAgbWF5IGhhdmUgYmVlbiBza2lwcGVkLicgfSB9XCIsXG4gICAgJyAgXSB9OycsXG4gICAgJyAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOycsXG4gICAgJ30nLFxuICAgIFwiY29uc3QgcmVzdWx0cyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHJlc3VsdHNGaWxlLCAndXRmOCcpKTtcIixcbiAgICBcImNvbnN0IGRyaWZ0ZWQgPSByZXN1bHRzLmZpbHRlcihyID0+IHIuZHJpZnRTdGF0dXMgPT09ICdEUklGVEVEJyk7XCIsXG4gICAgJ2NvbnN0IGVycm9ycyA9IHJlc3VsdHMuZmlsdGVyKHIgPT4gci5lcnJvcik7JyxcbiAgICBgY29uc3QgaGVhZGVyID0gXFxgKkRyaWZ0IERldGVjdGlvbiAoJHtzdGFnZX0pKiDigJQgUmVnaW9uOiAke3JlZ2lvbn1cXGA7YCxcbiAgICAnY29uc3Qgc3VtbWFyeSA9IGBUb3RhbCBzdGFja3M6ICR7cmVzdWx0cy5sZW5ndGh9IHwgRHJpZnRlZDogJHtkcmlmdGVkLmxlbmd0aH0gfCBFcnJvcnM6ICR7ZXJyb3JzLmxlbmd0aH1gOycsXG4gICAgJ2NvbnN0IGxpbmVzQXJyID0gW107JyxcbiAgICAnZm9yIChjb25zdCBzIG9mIGRyaWZ0ZWQpIHsnLFxuICAgICcgIGNvbnN0IGNvdW50ID0gKHMuZHJpZnRlZFJlc291cmNlcyB8fCBbXSkubGVuZ3RoOycsXG4gICAgJyAgbGluZXNBcnIucHVzaChg4oCiICR7cy5zdGFja05hbWV9IOKAlCAke2NvdW50fSByZXNvdXJjZShzKSBkcmlmdGVkYCk7JyxcbiAgICAnfScsXG4gICAgJ3BheWxvYWQgPSB7JyxcbiAgICAnICB0ZXh0OiBgRHJpZnQgRGV0ZWN0aW9uICgke3N0YWNrfSlgLCcsXG4gICAgJyAgYmxvY2tzOiBbJyxcbiAgICBcIiAgICB7IHR5cGU6ICdzZWN0aW9uJywgdGV4dDogeyB0eXBlOiAnbXJrZHduJywgdGV4dDogaGVhZGVyIH0gfSxcIixcbiAgICBcIiAgICB7IHR5cGU6ICdjb250ZXh0JywgZWxlbWVudHM6IFt7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiBzdW1tYXJ5IH1dIH0sXCIsXG4gICAgJyAgICAuLi4oZHJpZnRlZC5sZW5ndGggPiAwID8gWycsXG4gICAgXCIgICAgICB7IHR5cGU6ICdkaXZpZGVyJyB9LFwiLFxuICAgIFwiICAgICAgeyB0eXBlOiAnc2VjdGlvbicsIHRleHQ6IHsgdHlwZTogJ21ya2R3bicsIHRleHQ6ICcqRHJpZnRlZCBTdGFja3M6KlxcbicgKyBsaW5lc0Fyci5qb2luKCdcXG4nKSB9IH1cIixcbiAgICAnICAgIF0gOiBbJyxcbiAgICBcIiAgICAgIHsgdHlwZTogJ2RpdmlkZXInIH0sXCIsXG4gICAgXCIgICAgICB7IHR5cGU6ICdzZWN0aW9uJywgdGV4dDogeyB0eXBlOiAnbXJrZHduJywgdGV4dDogJ05vIGRyaWZ0IGRldGVjdGVkLicgfSB9XCIsXG4gICAgJyAgICBdKScsXG4gICAgJyAgXScsXG4gICAgJ307JyxcbiAgICAncmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOycsXG4gIF07XG4gIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gc3VtbWFyeVNjcmlwdCgpOiBzdHJpbmcge1xuICByZXR1cm4gW1xuICAgICcjIS9iaW4vYmFzaCcsXG4gICAgJ3NldCAtZScsXG4gICAgJ2VjaG8gXCIjIyBEcmlmdCBEZXRlY3Rpb24gU3VtbWFyeVwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnZWNobyBcIlwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnJyxcbiAgICAndG90YWxfc3RhY2tzPTAnLFxuICAgICd0b3RhbF9kcmlmdGVkPTAnLFxuICAgICd0b3RhbF9lcnJvcnM9MCcsXG4gICAgJycsXG4gICAgJ3Nob3B0IC1zIG51bGxnbG9iJyxcbiAgICAnZm9yIGZpbGUgaW4gZHJpZnQtcmVzdWx0cy0qLmpzb24gZHJpZnQtcmVzdWx0cy8qL2RyaWZ0LXJlc3VsdHMtKi5qc29uOyBkbycsXG4gICAgJyAgaWYgW1sgLWYgXCIkZmlsZVwiIF1dOyB0aGVuJyxcbiAgICAnICAgIHN0YWNrPSQoYmFzZW5hbWUgXCIkZmlsZVwiIHwgc2VkIC1FIFxcXCJzL15kcmlmdC1yZXN1bHRzLShbXi5dKylcXFxcLmpzb24kL1xcXFwxL1xcXCIpJyxcbiAgICAnICAgIGVjaG8gXCIjIyMgU3RhZ2U6ICRzdGFja1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIGpxIC1yIFxcJycgK1xuICAgICAgJy4gYXMgJHJlc3VsdHMgfFxcbicgK1xuICAgICAgJ1wiLSBUb3RhbCBzdGFja3M6IFwiICsgKCRyZXN1bHRzIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICdcIi0gRHJpZnRlZDogXCIgKyAoWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXCJEUklGVEVEXCIpXSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiXFxcXG5cIiArXFxuJyArXG4gICAgICAnXCItIEVycm9yczogXCIgKyAoWy5bXSB8IHNlbGVjdCguZXJyb3IpXSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiXFxcXG5cIiArXFxuJyArXG4gICAgICAnKFsuW10gfCBzZWxlY3QoLmRyaWZ0U3RhdHVzID09IFwiRFJJRlRFRFwiKV0gfCBpZiBsZW5ndGggPiAwIHRoZW4gXCJcXFxcbioqRHJpZnRlZCBzdGFja3M6KipcXFxcblwiICsgKG1hcChcIiAgLSBcIiArIC5zdGFja05hbWUgKyBcIiAoXCIgKyAoKC5kcmlmdGVkUmVzb3VyY2VzIC8vIFtdKSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiIHJlc291cmNlcylcIikgfCBqb2luKFwiXFxcXG5cIikpIGVsc2UgXCJcIiBlbmQpXFxuJyArXG4gICAgJ1xcJycgK1xuICAgICcgXCIkZmlsZVwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIGVjaG8gXCJcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJyAgICB0b3RhbF9zdGFja3M9JCgodG90YWxfc3RhY2tzICsgJChqcSBcXFwibGVuZ3RoXFxcIiBcXFwiJGZpbGVcXFwiKSkpJyxcbiAgICAnICAgIHRvdGFsX2RyaWZ0ZWQ9JCgodG90YWxfZHJpZnRlZCArICQoanEgXFxcIlsuW10gfCBzZWxlY3QoLmRyaWZ0U3RhdHVzID09IFxcXFxcXFwiRFJJRlRFRFxcXFxcXFwiKV0gfCBsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgICAgdG90YWxfZXJyb3JzPSQoKHRvdGFsX2Vycm9ycyArICQoanEgXFxcIlsuW10gfCBzZWxlY3QoLmVycm9yKV0gfCBsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgIGZpJyxcbiAgICAnZG9uZScsXG4gICAgJycsXG4gICAgJ2VjaG8gXCIjIyMgT3ZlcmFsbCBTdW1tYXJ5XCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBzdGFja3MgY2hlY2tlZDogJHRvdGFsX3N0YWNrc1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnZWNobyBcIi0gVG90YWwgZHJpZnRlZCBzdGFja3M6ICR0b3RhbF9kcmlmdGVkXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBlcnJvcnM6ICR0b3RhbF9lcnJvcnNcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJycsXG4gICAgJ2lmIFtbICR0b3RhbF9kcmlmdGVkIC1ndCAwIF1dOyB0aGVuJyxcbiAgICAnICBlY2hvIFwiXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgIGVjaG8gXCLimqDvuI8gKipBY3Rpb24gcmVxdWlyZWQ6KiogRHJpZnQgZGV0ZWN0ZWQgaW4gJHRvdGFsX2RyaWZ0ZWQgc3RhY2tzXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdmaScsXG4gIF0uam9pbignXFxuJyk7XG59XG5cbmZ1bmN0aW9uIHRvS2ViYWJDYXNlKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBzLnJlcGxhY2UoL1teYS16QS1aMC05XSsvZywgJy0nKS5yZXBsYWNlKC9eLSt8LSskL2csICcnKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5cbmZ1bmN0aW9uIHRvR2l0aHViSm9iSWQoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gR2l0SHViIGpvYl9pZCBtdXN0IHN0YXJ0IHdpdGggYSBsZXR0ZXIgb3IgdW5kZXJzY29yZSBhbmQgY29udGFpbiBvbmx5IEEtWmEtejAtOSwgJy0nLCAnXydcbiAgLy8gMSkgUmVwbGFjZSBhbnkgZGlzYWxsb3dlZCBjaGFycyB3aXRoICctJ1xuICBsZXQgb3V0ID0gcy5yZXBsYWNlKC9bXkEtWmEtejAtOV8tXSsvZywgJy0nKTtcbiAgLy8gMikgQ29sbGFwc2UgY29uc2VjdXRpdmUgZGFzaGVzXG4gIG91dCA9IG91dC5yZXBsYWNlKC8tKy9nLCAnLScpO1xuICAvLyAzKSBUcmltIGxlYWRpbmcvdHJhaWxpbmcgZGFzaGVzICh1bmRlcnNjb3JlcyBhcmUgYWxsb3dlZCBhdCBzdGFydClcbiAgb3V0ID0gb3V0LnJlcGxhY2UoL14tK3wtKyQvZywgJycpO1xuICAvLyA0KSBMb3dlcmNhc2UgZm9yIGNvbnNpc3RlbmN5IChub3QgcmVxdWlyZWQgYnkgR2l0SHViIGJ1dCBrZWVwcyB0aGluZ3Mgc3RhYmxlKVxuICBvdXQgPSBvdXQudG9Mb3dlckNhc2UoKTtcbiAgLy8gNSkgRW5zdXJlIGl0IHN0YXJ0cyB3aXRoIGEgbGV0dGVyIG9yIHVuZGVyc2NvcmVcbiAgaWYgKCFvdXQgfHwgIS9eW2Etel9dL2kudGVzdChvdXQpKSB7XG4gICAgb3V0ID0gYHMtJHtvdXR9YDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuIl19
|
|
320
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9DZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsOENBQTJEO0FBQzNELHVFQUFrRTtBQUNsRSxpRkFBMkU7QUFFM0UsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSxvQ0FBb0MsR0FBRyxJQUFJLENBQUM7QUFDbEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLENBQUM7QUErQzlDLE1BQWEseUJBQXlCO0lBR3BDLFlBQVksS0FBcUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxpQkFBaUIsQ0FBQztRQUNyRCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQzVDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDO1FBQ2hELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDOUIsTUFBTSxnQkFBZ0IsR0FBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksMkNBQTJDLENBQUM7UUFFOUYsa0VBQWtFO1FBQ2xFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM3QyxJQUFJLG9EQUF1QixDQUFDO2dCQUMxQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7YUFDN0IsQ0FBQyxDQUFDO1lBQ0gseUJBQXlCLENBQUMsYUFBYSxH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LDRGQUE0RjtJQUM1RiwyQ0FBMkM7SUFDM0MsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM3QyxpQ0FBaUM7SUFDakMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzlCLHFFQUFxRTtJQUNyRSxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEMsZ0ZBQWdGO0lBQ2hGLEdBQUcsR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDeEIsa0RBQWtEO0lBQ2xELElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbEMsR0FBRyxHQUFHLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEdpdEh1YiwgR2l0aHViV29ya2Zsb3cgfSBmcm9tICdwcm9qZW4vbGliL2dpdGh1Yic7XG5pbXBvcnQgeyBKb2JQZXJtaXNzaW9uIH0gZnJvbSAncHJvamVuL2xpYi9naXRodWIvd29ya2Zsb3dzLW1vZGVsJztcbmltcG9ydCB7IENka0RyaWZ0RGV0ZWN0aW9uU2NyaXB0IH0gZnJvbSAnLi9iaW4vY2RrLWRyaWZ0LWRldGVjdGlvbi1zY3JpcHQnO1xuXG5jb25zdCBnaXRodWJBY3Rpb25zQXdzQ3JlZGVudGlhbHNWZXJzaW9uID0gJ3Y1JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNDaGVja291dFZlcnNpb24gPSAndjUnO1xuY29uc3QgZ2l0aHViQWN0aW9uc1NldHVwTm9kZVZlcnNpb24gPSAndjUnO1xuY29uc3QgZ2l0aHViQWN0aW9uc1VwbG9hZEFydGlmYWN0VmVyc2lvbiA9ICd2NCc7XG5jb25zdCBnaXRodWJBY3Rpb25zRG93bmxvYWRBcnRpZmFjdFZlcnNpb24gPSAndjUnO1xuY29uc3QgZ2l0aHViQWN0aW9uc0dpdGh1YlNjcmlwdFZlcnNpb24gPSAndjgnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWNrIHtcbiAgcmVhZG9ubHkgc3RhY2tOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lQXJuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZhaWxPbkRyaWZ0PzogYm9vbGVhbjsgLy8gaWYgdHJ1ZSwgZmFpbCBqb2Igd2hlbiBkcmlmdCBkZXRlY3RlZCAoZGVmYXVsdCB0cnVlKVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3dQcm9wcyB7XG4gIHJlYWRvbmx5IHNjcmlwdE91dHB1dFBhdGg/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByb2plY3Q6IGFueTsgLy8gYXZvaWQgZXhwb3J0aW5nIHByb2plbiB0eXBlcyBpbiBwdWJsaWMgQVBJXG4gIHJlYWRvbmx5IHdvcmtmbG93TmFtZT86IHN0cmluZzsgLy8gd29ya2Zsb3cgd29ya2Zsb3dOYW1lIChhbHNvIHVzZWQgdG8gZGVyaXZlIGZpbGUgd29ya2Zsb3dOYW1lKVxuICByZWFkb25seSBzY2hlZHVsZT86IHN0cmluZzsgLy8gY3JvbiBleHByZXNzaW9uLCBlLmcuICcwIDAgKiAqIConXG4gIHJlYWRvbmx5IGNyZWF0ZUlzc3Vlcz86IGJvb2xlYW47IC8vIGNyZWF0ZS91cGRhdGUgaXNzdWUgd2hlbiBkcmlmdCBkZXRlY3RlZCBvbiBzY2hlZHVsZSAoZGVmYXVsdCB0cnVlKVxuICByZWFkb25seSBvaWRjUm9sZUFybjogc3RyaW5nOyAvLyBkZWZhdWx0IE9JREMgcm9sZSBBUk4gdG8gYXNzdW1lIGZvciBhbGwgc3RhY2tzXG4gIHJlYWRvbmx5IG9pZGNSZWdpb246IHN0cmluZzsgLy8gZGVmYXVsdCBPSURDIHJlZ2lvbiB0byBhc3N1bWUgZm9yIGFsbCBzdGFja3NcbiAgcmVhZG9ubHkgc3RhY2tzOiBTdGFja1tdO1xuICByZWFkb25seSBub2RlVmVyc2lvbj86IHN0cmluZzsgLy8gZS5nLiwgJzI0LngnXG4gIC8qKlxuICAgKiBPcHRpb25hbCBob29rIHRvIGFwcGVuZCBhZGRpdGlvbmFsIEdpdEh1YiBBY3Rpb25zIHN0ZXBzIGFmdGVyIGRyaWZ0IGRldGVjdGlvbiBwZXIgc3RhY2suXG4gICAqIFlvdSBjYW4gc3VwcGx5IGEgc3RhdGljIGFycmF5IG9mIHN0ZXBzLCBvciBhIGZhY3RvcnkgdGhhdCByZWNlaXZlcyBjb250ZXh0IGFuZCByZXR1cm5zIHN0ZXBzLlxuICAgKi9cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGFkZGl0aW9uYWwgR2l0SHViIEFjdGlvbiBzdGVwcyB0byBydW4gYWZ0ZXIgZHJpZnQgZGV0ZWN0aW9uIGZvciBlYWNoIHN0YWNrLlxuICAgKiBUaGVzZSBzdGVwcyBhcmUgaW5zZXJ0ZWQgYWZ0ZXIgYSAnUHJlcGFyZSBub3RpZmljYXRpb24gcGF5bG9hZCcgc3RlcCB3aGljaCBleHBvc2VzXG4gICAqIGEgU2xhY2stY29tcGF0aWJsZSBKU09OIHBheWxvYWQgYXQgYCR7eyBzdGVwcy5ub3RpZnkub3V0cHV0cy5yZXN1bHQgfX1gLlxuICAgKi9cbiAgLy8gTk9URToganNpaSBkb2VzIG5vdCBzdXBwb3J0IGZ1bmN0aW9uIHR5cGVzIGluIHB1YmxpYyBBUElzOyB1c2UgJ2FueScgaGVyZSBhbmQgYWNjZXB0IGVpdGhlcjpcbiAgLy8gLSBBbiBhcnJheSBvZiBHaXRIdWIgc3RlcHMsIG9yXG4gIC8vIC0gQSBmdW5jdGlvbiAoY3R4OiB7IHN0YWNrOiBzdHJpbmcgfSkgPT4gR2l0SHViU3RlcFtdXG4gIC8vIFRoZSBjb25zdHJ1Y3RvciBoYW5kbGVzIGJvdGggYXQgcnVudGltZS5cbiAgcmVhZG9ubHkgcG9zdEdpdEh1YlN0ZXBzPzogYW55O1xufVxuXG50eXBlIEdpdEh1YlN0ZXAgPSB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIGlkPzogc3RyaW5nO1xuICBpZj86IHN0cmluZztcbiAgdXNlcz86IHN0cmluZztcbiAgcnVuPzogc3RyaW5nO1xuICB3aXRoPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgZW52PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgY29udGludWVPbkVycm9yPzogYm9vbGVhbjtcbiAgc2hlbGw/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgY2xhc3MgQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdyB7XG4gIHByaXZhdGUgc3RhdGljIHNjcmlwdENyZWF0ZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvd1Byb3BzKSB7XG4gICAgY29uc3QgbmFtZSA9IHByb3BzLndvcmtmbG93TmFtZSA/PyAnZHJpZnQtZGV0ZWN0aW9uJztcbiAgICBjb25zdCBmaWxlTmFtZSA9IHRvS2ViYWJDYXNlKG5hbWUpICsgJy55bWwnO1xuICAgIGNvbnN0IG5vZGVWZXJzaW9uID0gcHJvcHMubm9kZVZlcnNpb24gPz8gJzI0LngnO1xuICAgIGNvbnN0IGNyZWF0ZUlzc3VlcyA9IHByb3BzLmNyZWF0ZUlzc3VlcyA/PyB0cnVlO1xuICAgIGNvbnN0IHByb2plY3QgPSBwcm9wcy5wcm9qZWN0O1xuICAgIGNvbnN0IHNjcmlwdE91dHB1dFBhdGg9IHByb3BzLnNjcmlwdE91dHB1dFBhdGggPz8gJy5naXRodWIvd29ya2Zsb3dzL3NjcmlwdHMvZGV0ZWN0LWRyaWZ0LnRzJztcblxuICAgIC8vIE9ubHkgY3JlYXRlIHRoZSBkcmlmdCBkZXRlY3Rpb24gc2NyaXB0IG9uY2UgdG8gYXZvaWQgY29sbGlzaW9uc1xuICAgIGlmICghQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5zY3JpcHRDcmVhdGVkKSB7XG4gICAgICBuZXcgQ2RrRHJpZnREZXRlY3Rpb25TY3JpcHQoe1xuICAgICAgICBwcm9qZWN0OiBwcm9wcy5wcm9qZWN0LFxuICAgICAgICBvdXRwdXRQYXRoOiBzY3JpcHRPdXRwdXRQYXRoLFxuICAgICAgfSk7XG4gICAgICBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnNjcmlwdENyZWF0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGNvbnN0IGdoID0gKHByb2plY3QgYXMgYW55KS5naXRodWIgPz8gbmV3IEdpdEh1Yihwcm9qZWN0KTtcbiAgICBjb25zdCB3b3JrZmxvdyA9IG5ldyBHaXRodWJXb3JrZmxvdyhnaCwgbmFtZSwgeyBmaWxlTmFtZSB9KTtcblxuICAgIC8vIHRyaWdnZXJzOiBzY2hlZHVsZSArIG1hbnVhbCBkaXNwYXRjaCB3aXRoIHN0YWNrIGNob2ljZVxuICAgIGNvbnN0IHN0YWNrQ2hvaWNlcyA9IHByb3BzLnN0YWNrcy5tYXAoKHMpID0+IHMuc3RhY2tOYW1lKTtcbiAgICB3b3JrZmxvdy5vbih7XG4gICAgICBzY2hlZHVsZTogcHJvcHMuc2NoZWR1bGUgPyBbeyBjcm9uOiBwcm9wcy5zY2hlZHVsZSB9XSA6IHVuZGVmaW5lZCxcbiAgICAgIHdvcmtmbG93RGlzcGF0Y2g6IHtcbiAgICAgICAgaW5wdXRzOiB7XG4gICAgICAgICAgc3RhY2s6IHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnU3RhY2sgdG8gY2hlY2sgZm9yIGRyaWZ0IChsZWF2ZSBlbXB0eSBmb3IgYWxsKScsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICB0eXBlOiAnY2hvaWNlJyxcbiAgICAgICAgICAgIG9wdGlvbnM6IHN0YWNrQ2hvaWNlcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIE9uZSBqb2IgcGVyIHN0YWNrXG4gICAgY29uc3Qgam9iczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBzdGFjayBvZiBwcm9wcy5zdGFja3MpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZFN0YWNrTmFtZSA9IHRvS2ViYWJDYXNlKHRvR2l0aHViSm9iSWQoc3RhY2suc3RhY2tOYW1lKSk7XG4gICAgICBjb25zdCBvcmlnaW5hbFN0YWNrTmFtZSA9IHN0YWNrLnN0YWNrTmFtZTtcbiAgICAgIGNvbnN0IGpvYklkID0gYGRyaWZ0LSR7c2FuaXRpemVkU3RhY2tOYW1lfWA7XG4gICAgICBjb25zdCByZXN1bHRzRmlsZSA9IGBkcmlmdC1yZXN1bHRzLSR7c2FuaXRpemVkU3RhY2tOYW1lfS5qc29uYDtcbiAgICAgIGNvbnN0IGlubmVyQ29uZCA9IFwiZ2l0aHViLmV2ZW50X25hbWUgPT0gJ3NjaGVkdWxlJyB8fCAhZ2l0aHViLmV2ZW50LmlucHV0cy5zdGFjayB8fCBnaXRodWIuZXZlbnQuaW5wdXRzLnN0YWNrID09ICdcIiArIHNhbml0aXplZFN0YWNrTmFtZSArIFwiJyB8fCBnaXRodWIuZXZlbnQuaW5wdXRzLnN0YWNrID09ICdcIiArIG9yaWdpbmFsU3RhY2tOYW1lICsgXCInXCI7XG4gICAgICBjb25zdCBjb25kRXhwciA9ICcke3sgJyArIGlubmVyQ29uZCArICcgfX0nO1xuICAgICAgY29uc3Qgbm90Q29uZEV4cHIgPSAnJHt7ICEoJyArIGlubmVyQ29uZCArICcpIH19JztcblxuICAgICAgY29uc3QgcmF3UG9zdCA9IHByb3BzLnBvc3RHaXRIdWJTdGVwcztcbiAgICAgIGNvbnN0IHBvc3RTdGVwczogR2l0SHViU3RlcFtdID0gdHlwZW9mIHJhd1Bvc3QgPT09ICdmdW5jdGlvbicgPyAocmF3UG9zdCBhcyAoY3R4OiB7IHN0YWNrOiBzdHJpbmcgfSkgPT4gR2l0SHViU3RlcFtdKSh7IHN0YWNrOiBzYW5pdGl6ZWRTdGFja05hbWUgfSkgOiAocmF3UG9zdCA/PyBbXSk7XG5cbiAgICAgIGpvYnNbam9iSWRdID0ge1xuICAgICAgICBuYW1lOiBgRHJpZnQgRGV0ZWN0aW9uIC0gJHtzYW5pdGl6ZWRTdGFja05hbWV9YCxcbiAgICAgICAgcnVuc09uOiBbJ3VidW50dS1sYXRlc3QnXSxcbiAgICAgICAgcGVybWlzc2lvbnM6IHtcbiAgICAgICAgICBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgICAgIGlkVG9rZW46IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgICAgaXNzdWVzOiBKb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgICB9LFxuICAgICAgICBlbnY6IHtcbiAgICAgICAgICBBV1NfREVGQVVMVF9SRUdJT046IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgIEFXU19SRUdJT046IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgIERSSUZUX0RFVEVDVElPTl9PVVRQVVQ6IHJlc3VsdHNGaWxlLFxuICAgICAgICAgIFNUQUdFX05BTUU6IHNhbml0aXplZFN0YWNrTmFtZSxcbiAgICAgICAgICBTVEFDS19OQU1FOiBzdGFjay5zdGFja05hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIC8vIE5vIGpvYi1sZXZlbCBjb25kaXRpb247IHdlIGdhdGUgc3RlcHMgc28gdGhlIGpvYiBhbHdheXMgY29tcGxldGVzIGFuZCBzdW1tYXJ5IGNhbiBydW5cbiAgICAgICAgc3RlcHM6IFtcbiAgICAgICAgICB7IG5hbWU6ICdTa2lwIChzdGFjayBub3Qgc2VsZWN0ZWQpJywgaWY6IG5vdENvbmRFeHByLCBydW46ICdlY2hvIFwiU3RhZ2Ugbm90IHNlbGVjdGVkOyBza2lwcGluZyBkcmlmdCBkZXRlY3Rpb24gZm9yIHRoaXMgam9iLlwiJyB9LFxuICAgICAgICAgIHsgbmFtZTogJ0NoZWNrb3V0JywgaWY6IGNvbmRFeHByLCB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke2dpdGh1YkFjdGlvbnNDaGVja291dFZlcnNpb259YCB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3NldHVwLW5vZGVAJHtnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbn1gLFxuICAgICAgICAgICAgd2l0aDogeyAnbm9kZS12ZXJzaW9uJzogbm9kZVZlcnNpb24gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbmFtZTogJ0luc3RhbGwgZGVwZW5kZW5jaWVzJywgaWY6IGNvbmRFeHByLCBydW46ICd5YXJuIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGUgfHwgbnBtIGNpJywgZW52OiB7IEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdBV1MgQ3JlZGVudGlhbHMnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdjcmVkcycsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogcHJvcHMub2lkY1JvbGVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLXNlc3Npb24tbmFtZSc6ICdHaXRIdWJBY3Rpb24nLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHByb3BzLm9pZGNSZWdpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0Fzc3VtZSBEcmlmdCBEZXRlY3Rpb24gUm9sZScsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLWNoYWluaW5nJzogdHJ1ZSxcbiAgICAgICAgICAgICAgJ3JvbGUtc2tpcC1zZXNzaW9uLXRhZ2dpbmcnOiB0cnVlLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgICAgICAnYXdzLWFjY2Vzcy1rZXktaWQnOiAnJHt7IHN0ZXBzLmNyZWRzLm91dHB1dHMuYXdzLWFjY2Vzcy1rZXktaWQgfX0nLFxuICAgICAgICAgICAgICAnYXdzLXNlY3JldC1hY2Nlc3Mta2V5JzogJyR7eyBzdGVwcy5jcmVkcy5vdXRwdXRzLmF3cy1zZWNyZXQtYWNjZXNzLWtleSB9fScsXG4gICAgICAgICAgICAgICdhd3Mtc2Vzc2lvbi10b2tlbic6ICcke3sgc3RlcHMuY3JlZHMub3V0cHV0cy5hd3Mtc2Vzc2lvbi10b2tlbiB9fScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0RldGVjdCBkcmlmdCcsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICBpZDogJ2RyaWZ0JyxcbiAgICAgICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSwgLy8gYWxsb3cgYXJ0aWZhY3QgdXBsb2FkIGFuZCBpc3N1ZSBjcmVhdGlvbiBldmVuIHdoZW4gZHJpZnQgaXMgZGV0ZWN0ZWRcbiAgICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgICAnc2V0IC1lJyxcbiAgICAgICAgICAgICAgLy8gVXNlIHRoZSBidW5kbGVkIHNjcmlwdCBmcm9tIHRoaXMgcGFja2FnZVxuICAgICAgICAgICAgICAnbm9kZSAuL25vZGVfbW9kdWxlcy9AampyYXdsaW5zL2Nkay1kaWZmLXByLWdpdGh1Yi1hY3Rpb24vbGliL2Jpbi9kZXRlY3QtZHJpZnQuanMnLFxuICAgICAgICAgICAgICAnaWYgWyAtZiBcIiREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCIgXTsgdGhlbiBlY2hvIFwiUmVzdWx0cyBmaWxlIGNyZWF0ZWQ6ICREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCI7IGZpJyxcbiAgICAgICAgICAgIF0uam9pbignXFxuJyksXG4gICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgU1RBQ0tfTkFNRTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICAgICAgICBBV1NfUkVHSU9OOiBzdGFjay5kcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbixcbiAgICAgICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1VwbG9hZCByZXN1bHRzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3VwbG9hZC1hcnRpZmFjdEAke2dpdGh1YkFjdGlvbnNVcGxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHsgbmFtZTogYGRyaWZ0LXJlc3VsdHMtJHtzYW5pdGl6ZWRTdGFja05hbWV9YCwgcGF0aDogcmVzdWx0c0ZpbGUsIGlmTm9GaWxlc0ZvdW5kOiAnaWdub3JlJyB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1ByZXBhcmUgbm90aWZpY2F0aW9uIHBheWxvYWQnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdub3RpZnknLFxuICAgICAgICAgICAgdXNlczogYGFjdGlvbnMvZ2l0aHViLXNjcmlwdEAke2dpdGh1YkFjdGlvbnNHaXRodWJTY3JpcHRWZXJzaW9ufWAsXG4gICAgICAgICAgICB3aXRoOiB7XG4gICAgICAgICAgICAgICdyZXN1bHQtZW5jb2RpbmcnOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgJ3NjcmlwdCc6IG5vdGlmaWNhdGlvblNjcmlwdChzYW5pdGl6ZWRTdGFja05hbWUsIHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLCByZXN1bHRzRmlsZSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4ucG9zdFN0ZXBzLm1hcCgoc3RlcCkgPT4gKHtcbiAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIG9ubHkgcnVuIGV4dHJhIG5vdGlmaWNhdGlvbiBzdGVwcyB3aGVuIGRyaWZ0IG9jY3Vyc1xuICAgICAgICAgICAgaWY6IChzdGVwIGFzIGFueSkuaWYgPz8gXCJhbHdheXMoKSAmJiBzdGVwcy5kcmlmdC5vdXRjb21lID09ICdmYWlsdXJlJ1wiLFxuICAgICAgICAgICAgLi4uKHN0ZXAgYXMgYW55KSxcbiAgICAgICAgICB9KSksXG4gICAgICAgICAgLi4uKFxuICAgICAgICAgICAgY3JlYXRlSXNzdWVzXG4gICAgICAgICAgICAgID8gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG5hbWU6ICdDcmVhdGUgSXNzdWUgb24gRHJpZnQnLFxuICAgICAgICAgICAgICAgICAgaWY6IFwiYWx3YXlzKCkgJiYgc3RlcHMuZHJpZnQub3V0Y29tZSA9PSAnZmFpbHVyZSdcIixcbiAgICAgICAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL2dpdGh1Yi1zY3JpcHRAJHtnaXRodWJBY3Rpb25zR2l0aHViU2NyaXB0VmVyc2lvbn1gLFxuICAgICAgICAgICAgICAgICAgd2l0aDogeyBzY3JpcHQ6IGlzc3VlU2NyaXB0KHNhbml0aXplZFN0YWNrTmFtZSwgc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sIHJlc3VsdHNGaWxlKSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgOiBbXVxuICAgICAgICAgICksXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIHN1bW1hcnkgYWdncmVnYXRvciBqb2JcbiAgICBqb2JzWydkcmlmdC1zdW1tYXJ5J10gPSB7XG4gICAgICBuYW1lOiAnRHJpZnQgRGV0ZWN0aW9uIFN1bW1hcnknLFxuICAgICAgbmVlZHM6IE9iamVjdC5rZXlzKGpvYnMpLmZpbHRlcigoaikgPT4gai5zdGFydHNXaXRoKCdkcmlmdC0nKSAmJiBqICE9PSAnZHJpZnQtc3VtbWFyeScpLFxuICAgICAgcnVuc09uOiBbJ3VidW50dS1sYXRlc3QnXSxcbiAgICAgIHBlcm1pc3Npb25zOiB7IGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLlJFQUQgfSxcbiAgICAgIHN0ZXBzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnRG93bmxvYWQgYWxsIGFydGlmYWN0cycsXG4gICAgICAgICAgdXNlczogYGFjdGlvbnMvZG93bmxvYWQtYXJ0aWZhY3RAJHtnaXRodWJBY3Rpb25zRG93bmxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICB3aXRoOiB7IHBhdGg6ICdkcmlmdC1yZXN1bHRzJyB9LFxuICAgICAgICB9LFxuICAgICAgICB7IG5hbWU6ICdHZW5lcmF0ZSBzdW1tYXJ5Jywgc2hlbGw6ICdiYXNoJywgcnVuOiBzdW1tYXJ5U2NyaXB0KCkgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIHdvcmtmbG93LmFkZEpvYnMoam9icyk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBpc3N1ZVNjcmlwdChzdGFnZTogc3RyaW5nLCByZWdpb246IHN0cmluZywgcmVzdWx0c0ZpbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIENvbnN0cnVjdCBhIHBsYWluIEpTIHNjcmlwdCBzdHJpbmcgKG5vIHRlbXBsYXRlIHN0cmluZyBuZXN0aW5nIG1pc2hhcHMpXG4gIGNvbnN0IGxpbmVzID0gW1xuICAgIFwiY29uc3QgZnMgPSByZXF1aXJlKCdmcycpO1wiLFxuICAgIGBjb25zdCByZXN1bHRzRmlsZSA9ICcke3Jlc3VsdHNGaWxlfSc7YCxcbiAgICBcImlmICghZnMuZXhpc3RzU3luYyhyZXN1bHRzRmlsZSkpIHsgY29uc29sZS5sb2coJ05vIHJlc3VsdHMgZmlsZSBmb3VuZCcpOyByZXR1cm47IH1cIixcbiAgICBcImNvbnN0IHJlc3VsdHMgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhyZXN1bHRzRmlsZSwgJ3V0ZjgnKSk7XCIsXG4gICAgXCJjb25zdCBkcmlmdGVkU3RhY2tzID0gcmVzdWx0cy5maWx0ZXIociA9PiByLmRyaWZ0U3RhdHVzID09PSAnRFJJRlRFRCcpO1wiLFxuICAgIFwiaWYgKGRyaWZ0ZWRTdGFja3MubGVuZ3RoID09PSAwKSB7IGNvbnNvbGUubG9nKCdObyBkcmlmdCBkZXRlY3RlZCcpOyByZXR1cm47IH1cIixcbiAgICBgY29uc3QgdGl0bGUgPSAnRHJpZnQgRGV0ZWN0ZWQgaW4gJHtzdGFnZX0nO2AsXG4gICAgYGxldCBib2R5ID0gJyMjIERyaWZ0IERldGVjdGlvbiBSZXBvcnRcXFxcblxcXFxuJyArICcqKlN0YWdlOioqICR7c3RhZ2V9XFxcXG4nICsgJyoqUmVnaW9uOioqICR7cmVnaW9ufVxcXFxuJyArICcqKlRpbWU6KiogJyArIG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSArICdcXFxcblxcXFxuJztgLFxuICAgIFwiYm9keSArPSAnIyMjIFN1bW1hcnlcXFxcbic7XCIsXG4gICAgXCJib2R5ICs9ICctIFRvdGFsIHN0YWNrcyBjaGVja2VkOiAnICsgcmVzdWx0cy5sZW5ndGggKyAnXFxcXG4nO1wiLFxuICAgIFwiYm9keSArPSAnLSBEcmlmdGVkIHN0YWNrczogJyArIGRyaWZ0ZWRTdGFja3MubGVuZ3RoICsgJ1xcXFxuXFxcXG4nO1wiLFxuICAgIFwiYm9keSArPSAnIyMjIERyaWZ0ZWQgU3RhY2tzXFxcXG4nO1wiLFxuICAgICdmb3IgKGNvbnN0IHMgb2YgZHJpZnRlZFN0YWNrcykgeycsXG4gICAgJyAgY29uc3QgcmVzb3VyY2VzID0gcy5kcmlmdGVkUmVzb3VyY2VzIHx8IFtdOycsXG4gICAgXCIgIGJvZHkgKz0gJyMjIyMgJyArIHMuc3RhY2tOYW1lICsgJ1xcXFxuJztcIixcbiAgICBcIiAgYm9keSArPSAnLSBEcmlmdGVkIHJlc291cmNlczogJyArIHJlc291cmNlcy5sZW5ndGggKyAnXFxcXG4nO1wiLFxuICAgIFwiICBmb3IgKGNvbnN0IHIgb2YgcmVzb3VyY2VzKSB7IGJvZHkgKz0gJyAgLSAnICsgci5sb2dpY2FsUmVzb3VyY2VJZCArICcgKCcgKyByLnJlc291cmNlVHlwZSArICcpXFxcXG4nOyB9XCIsXG4gICAgXCIgIGJvZHkgKz0gJ1xcXFxuJztcIixcbiAgICAnfScsXG4gICAgXCJib2R5ICs9ICcjIyMgQWN0aW9uIFJlcXVpcmVkXFxcXG4nICsgJ1BsZWFzZSByZXZpZXcgdGhlIGRyaWZ0ZWQgcmVzb3VyY2VzIGFuZCBlaXRoZXI6XFxcXG4xLiBVcGRhdGUgdGhlIGluZnJhc3RydWN0dXJlIGNvZGUgdG8gbWF0Y2ggdGhlIGFjdHVhbCBzdGF0ZVxcXFxuMi4gUmVzdG9yZSB0aGUgcmVzb3VyY2VzIHRvIG1hdGNoIHRoZSBleHBlY3RlZCBzdGF0ZVxcXFxuXFxcXG4nO1wiLFxuICAgICdib2R5ICs9IGBbVmlldyB3b3JrZmxvdyBydW5dKCR7Y29udGV4dC5zZXJ2ZXJVcmx9LyR7Y29udGV4dC5yZXBvLm93bmVyfS8ke2NvbnRleHQucmVwby5yZXBvfS9hY3Rpb25zL3J1bnMvJHtjb250ZXh0LnJ1bklkfSlgOycsXG4gICAgLy8gTGlzdCBvciB1cGRhdGUgYW4gaXNzdWUgd2l0aCBsYWJlbHNcbiAgICBgY29uc3QgaXNzdWVzID0gYXdhaXQgZ2l0aHViLnJlc3QuaXNzdWVzLmxpc3RGb3JSZXBvKHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIHN0YXRlOiAnb3BlbicsIGxhYmVsczogWydkcmlmdC1kZXRlY3Rpb24nLCAnJHtzdGFnZX0nXSB9KTtgLFxuICAgICdpZiAoaXNzdWVzLmRhdGEubGVuZ3RoID09PSAwKSB7JyxcbiAgICBgICBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlKHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIHRpdGxlLCBib2R5LCBsYWJlbHM6IFsnZHJpZnQtZGV0ZWN0aW9uJywgJyR7c3RhZ2V9J10gfSk7YCxcbiAgICAnfSBlbHNlIHsnLFxuICAgICcgIGNvbnN0IGlzc3VlID0gaXNzdWVzLmRhdGFbMF07JyxcbiAgICAnICBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlQ29tbWVudCh7IG93bmVyOiBjb250ZXh0LnJlcG8ub3duZXIsIHJlcG86IGNvbnRleHQucmVwby5yZXBvLCBpc3N1ZV9udW1iZXI6IGlzc3VlLm51bWJlciwgYm9keSB9KTsnLFxuICAgICd9JyxcbiAgXTtcbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuXG5mdW5jdGlvbiBub3RpZmljYXRpb25TY3JpcHQoc3RhZ2U6IHN0cmluZywgcmVnaW9uOiBzdHJpbmcsIHJlc3VsdHNGaWxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsaW5lcyA9IFtcbiAgICBcImNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTtcIixcbiAgICBgY29uc3QgcmVzdWx0c0ZpbGUgPSAnJHtyZXN1bHRzRmlsZX0nO2AsXG4gICAgJ2xldCBwYXlsb2FkOycsXG4gICAgJ2lmICghZnMuZXhpc3RzU3luYyhyZXN1bHRzRmlsZSkpIHsnLFxuICAgICcgIHBheWxvYWQgPSB7IHRleHQ6IGBEcmlmdCBEZXRlY3Rpb24gKCR7c3RhY2t9KSAtIE5vIHJlc3VsdHMgZm91bmRgLCBibG9ja3M6IFsnLFxuICAgIFwiICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiBgKkRyaWZ0IERldGVjdGlvbiAoJHtzdGFja30pKmAgfSB9LFwiLFxuICAgIFwiICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiAnTm8gcmVzdWx0cyBmaWxlIGZvdW5kLiBUaGUgZGV0ZWN0aW9uIHN0ZXAgbWF5IGhhdmUgYmVlbiBza2lwcGVkLicgfSB9XCIsXG4gICAgJyAgXSB9OycsXG4gICAgJyAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOycsXG4gICAgJ30nLFxuICAgIFwiY29uc3QgcmVzdWx0cyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHJlc3VsdHNGaWxlLCAndXRmOCcpKTtcIixcbiAgICBcImNvbnN0IGRyaWZ0ZWQgPSByZXN1bHRzLmZpbHRlcihyID0+IHIuZHJpZnRTdGF0dXMgPT09ICdEUklGVEVEJyk7XCIsXG4gICAgJ2NvbnN0IGVycm9ycyA9IHJlc3VsdHMuZmlsdGVyKHIgPT4gci5lcnJvcik7JyxcbiAgICBgY29uc3QgaGVhZGVyID0gXFxgKkRyaWZ0IERldGVjdGlvbiAoJHtzdGFnZX0pKiDigJQgUmVnaW9uOiAke3JlZ2lvbn1cXGA7YCxcbiAgICAnY29uc3Qgc3VtbWFyeSA9IGBUb3RhbCBzdGFja3M6ICR7cmVzdWx0cy5sZW5ndGh9IHwgRHJpZnRlZDogJHtkcmlmdGVkLmxlbmd0aH0gfCBFcnJvcnM6ICR7ZXJyb3JzLmxlbmd0aH1gOycsXG4gICAgJ2NvbnN0IGxpbmVzQXJyID0gW107JyxcbiAgICAnZm9yIChjb25zdCBzIG9mIGRyaWZ0ZWQpIHsnLFxuICAgICcgIGNvbnN0IGNvdW50ID0gKHMuZHJpZnRlZFJlc291cmNlcyB8fCBbXSkubGVuZ3RoOycsXG4gICAgJyAgbGluZXNBcnIucHVzaChg4oCiICR7cy5zdGFja05hbWV9IOKAlCAke2NvdW50fSByZXNvdXJjZShzKSBkcmlmdGVkYCk7JyxcbiAgICAnfScsXG4gICAgJ3BheWxvYWQgPSB7JyxcbiAgICAnICB0ZXh0OiBgRHJpZnQgRGV0ZWN0aW9uICgke3N0YWNrfSlgLCcsXG4gICAgJyAgYmxvY2tzOiBbJyxcbiAgICBcIiAgICB7IHR5cGU6ICdzZWN0aW9uJywgdGV4dDogeyB0eXBlOiAnbXJrZHduJywgdGV4dDogaGVhZGVyIH0gfSxcIixcbiAgICBcIiAgICB7IHR5cGU6ICdjb250ZXh0JywgZWxlbWVudHM6IFt7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiBzdW1tYXJ5IH1dIH0sXCIsXG4gICAgJyAgICAuLi4oZHJpZnRlZC5sZW5ndGggPiAwID8gWycsXG4gICAgXCIgICAgICB7IHR5cGU6ICdkaXZpZGVyJyB9LFwiLFxuICAgIFwiICAgICAgeyB0eXBlOiAnc2VjdGlvbicsIHRleHQ6IHsgdHlwZTogJ21ya2R3bicsIHRleHQ6ICcqRHJpZnRlZCBTdGFja3M6KlxcbicgKyBsaW5lc0Fyci5qb2luKCdcXG4nKSB9IH1cIixcbiAgICAnICAgIF0gOiBbJyxcbiAgICBcIiAgICAgIHsgdHlwZTogJ2RpdmlkZXInIH0sXCIsXG4gICAgXCIgICAgICB7IHR5cGU6ICdzZWN0aW9uJywgdGV4dDogeyB0eXBlOiAnbXJrZHduJywgdGV4dDogJ05vIGRyaWZ0IGRldGVjdGVkLicgfSB9XCIsXG4gICAgJyAgICBdKScsXG4gICAgJyAgXScsXG4gICAgJ307JyxcbiAgICAncmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOycsXG4gIF07XG4gIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gc3VtbWFyeVNjcmlwdCgpOiBzdHJpbmcge1xuICByZXR1cm4gW1xuICAgICcjIS9iaW4vYmFzaCcsXG4gICAgJ3NldCAtZScsXG4gICAgJ2VjaG8gXCIjIyBEcmlmdCBEZXRlY3Rpb24gU3VtbWFyeVwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnZWNobyBcIlwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnJyxcbiAgICAndG90YWxfc3RhY2tzPTAnLFxuICAgICd0b3RhbF9kcmlmdGVkPTAnLFxuICAgICd0b3RhbF9lcnJvcnM9MCcsXG4gICAgJycsXG4gICAgJ3Nob3B0IC1zIG51bGxnbG9iJyxcbiAgICAnZm9yIGZpbGUgaW4gZHJpZnQtcmVzdWx0cy0qLmpzb24gZHJpZnQtcmVzdWx0cy8qL2RyaWZ0LXJlc3VsdHMtKi5qc29uOyBkbycsXG4gICAgJyAgaWYgW1sgLWYgXCIkZmlsZVwiIF1dOyB0aGVuJyxcbiAgICAnICAgIHN0YWNrPSQoYmFzZW5hbWUgXCIkZmlsZVwiIHwgc2VkIC1FIFxcXCJzL15kcmlmdC1yZXN1bHRzLShbXi5dKylcXFxcLmpzb24kL1xcXFwxL1xcXCIpJyxcbiAgICAnICAgIGVjaG8gXCIjIyMgU3RhZ2U6ICRzdGFja1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIGpxIC1yIFxcJycgK1xuICAgICAgJy4gYXMgJHJlc3VsdHMgfFxcbicgK1xuICAgICAgJ1wiLSBUb3RhbCBzdGFja3M6IFwiICsgKCRyZXN1bHRzIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICdcIi0gRHJpZnRlZDogXCIgKyAoWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXCJEUklGVEVEXCIpXSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiXFxcXG5cIiArXFxuJyArXG4gICAgICAnXCItIEVycm9yczogXCIgKyAoWy5bXSB8IHNlbGVjdCguZXJyb3IpXSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiXFxcXG5cIiArXFxuJyArXG4gICAgICAnKFsuW10gfCBzZWxlY3QoLmRyaWZ0U3RhdHVzID09IFwiRFJJRlRFRFwiKV0gfCBpZiBsZW5ndGggPiAwIHRoZW4gXCJcXFxcbioqRHJpZnRlZCBzdGFja3M6KipcXFxcblwiICsgKG1hcChcIiAgLSBcIiArIC5zdGFja05hbWUgKyBcIiAoXCIgKyAoKC5kcmlmdGVkUmVzb3VyY2VzIC8vIFtdKSB8IGxlbmd0aCB8IHRvc3RyaW5nKSArIFwiIHJlc291cmNlcylcIikgfCBqb2luKFwiXFxcXG5cIikpIGVsc2UgXCJcIiBlbmQpXFxuJyArXG4gICAgJ1xcJycgK1xuICAgICcgXCIkZmlsZVwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIGVjaG8gXCJcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJyAgICB0b3RhbF9zdGFja3M9JCgodG90YWxfc3RhY2tzICsgJChqcSBcXFwibGVuZ3RoXFxcIiBcXFwiJGZpbGVcXFwiKSkpJyxcbiAgICAnICAgIHRvdGFsX2RyaWZ0ZWQ9JCgodG90YWxfZHJpZnRlZCArICQoanEgXFxcIlsuW10gfCBzZWxlY3QoLmRyaWZ0U3RhdHVzID09IFxcXFxcXFwiRFJJRlRFRFxcXFxcXFwiKV0gfCBsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgICAgdG90YWxfZXJyb3JzPSQoKHRvdGFsX2Vycm9ycyArICQoanEgXFxcIlsuW10gfCBzZWxlY3QoLmVycm9yKV0gfCBsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgIGZpJyxcbiAgICAnZG9uZScsXG4gICAgJycsXG4gICAgJ2VjaG8gXCIjIyMgT3ZlcmFsbCBTdW1tYXJ5XCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBzdGFja3MgY2hlY2tlZDogJHRvdGFsX3N0YWNrc1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnZWNobyBcIi0gVG90YWwgZHJpZnRlZCBzdGFja3M6ICR0b3RhbF9kcmlmdGVkXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBlcnJvcnM6ICR0b3RhbF9lcnJvcnNcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJycsXG4gICAgJ2lmIFtbICR0b3RhbF9kcmlmdGVkIC1ndCAwIF1dOyB0aGVuJyxcbiAgICAnICBlY2hvIFwiXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgIGVjaG8gXCLimqDvuI8gKipBY3Rpb24gcmVxdWlyZWQ6KiogRHJpZnQgZGV0ZWN0ZWQgaW4gJHRvdGFsX2RyaWZ0ZWQgc3RhY2tzXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdmaScsXG4gIF0uam9pbignXFxuJyk7XG59XG5cbmZ1bmN0aW9uIHRvS2ViYWJDYXNlKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBzLnJlcGxhY2UoL1teYS16QS1aMC05XSsvZywgJy0nKS5yZXBsYWNlKC9eLSt8LSskL2csICcnKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5cbmZ1bmN0aW9uIHRvR2l0aHViSm9iSWQoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gR2l0SHViIGpvYl9pZCBtdXN0IHN0YXJ0IHdpdGggYSBsZXR0ZXIgb3IgdW5kZXJzY29yZSBhbmQgY29udGFpbiBvbmx5IEEtWmEtejAtOSwgJy0nLCAnXydcbiAgLy8gMSkgUmVwbGFjZSBhbnkgZGlzYWxsb3dlZCBjaGFycyB3aXRoICctJ1xuICBsZXQgb3V0ID0gcy5yZXBsYWNlKC9bXkEtWmEtejAtOV8tXSsvZywgJy0nKTtcbiAgLy8gMikgQ29sbGFwc2UgY29uc2VjdXRpdmUgZGFzaGVzXG4gIG91dCA9IG91dC5yZXBsYWNlKC8tKy9nLCAnLScpO1xuICAvLyAzKSBUcmltIGxlYWRpbmcvdHJhaWxpbmcgZGFzaGVzICh1bmRlcnNjb3JlcyBhcmUgYWxsb3dlZCBhdCBzdGFydClcbiAgb3V0ID0gb3V0LnJlcGxhY2UoL14tK3wtKyQvZywgJycpO1xuICAvLyA0KSBMb3dlcmNhc2UgZm9yIGNvbnNpc3RlbmN5IChub3QgcmVxdWlyZWQgYnkgR2l0SHViIGJ1dCBrZWVwcyB0aGluZ3Mgc3RhYmxlKVxuICBvdXQgPSBvdXQudG9Mb3dlckNhc2UoKTtcbiAgLy8gNSkgRW5zdXJlIGl0IHN0YXJ0cyB3aXRoIGEgbGV0dGVyIG9yIHVuZGVyc2NvcmVcbiAgaWYgKCFvdXQgfHwgIS9eW2Etel9dL2kudGVzdChvdXQpKSB7XG4gICAgb3V0ID0gYHMtJHtvdXR9YDtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuIl19
|