@jjrawlins/cdk-diff-pr-github-action 0.0.14-beta → 0.0.16-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 -6
- package/README.md +26 -36
- package/lib/CdkDriftDetectionWorkflow.d.ts +3 -2
- package/lib/CdkDriftDetectionWorkflow.js +10 -69
- 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\nOption A: slackapi/slack-github-action (Incoming Webhook)\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@v2',\n // by default, post steps run only when drift is detected; you can override `if`\n if: \"always() && steps.drift.outcome == 'failure'\",\n // If you omit `with.payload`, this library will automatically wire\n // the prepared payload: ${{ steps.notify.outputs.result }}\n // You can also use the v2 inputs like `markdown` directly if preferred.\n with: {\n markdown: [\n `## ${stack} has drifted!`,\n 'Please investigate the drift detected in the stack.',\n 'For more details, visit the AWS CloudFormation console:',\n 'Stack ARN: `${{ steps.drift.outputs.stack-arn }}`',\n 'Related issue: #${{ steps.issue.outputs.result }}',\n ],\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\nOption B: slackapi/slack-github-action (Webhook to Slack Workflow Builder)\n\nRefer to Slack’s docs for sending via webhook to start a Slack workflow:\nhttps://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-webhook-slack-workflow/\n\nProvide a flattened payload for your Workflow Builder, for example:\n\n```yaml\n- name: Notify Slack (webhook)\n uses: slackapi/slack-github-action@v2\n with:\n payload: |\n { \"stack\": \"${{ env.STACK_NAME }}\", \"status\": \"${{ steps.drift.outcome }}\", \"stackArn\": \"${{ steps.drift.outputs.stack-arn }}\", \"issue\": \"${{ steps.issue.outputs.result }}\" }\n env:\n SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}\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 and is available at `${{ steps.notify.outputs.result }}`.\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.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`\n - `${{ steps.drift.outcome }}` — success/failure of the detect step\n - `${{ steps.drift.outputs.stack-arn }}` — Stack ARN resolved at runtime\n - `${{ steps.issue.outputs.result }}` — Issue number if the workflow created/found one (empty when not applicable)\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\n### Manual dispatch\n- The workflow exposes an input named `stack` with choices including each configured stack and an `all` option.\n- Choose a specific stack to run drift detection for that stack only, or select `all` (or leave the input empty) to run all stacks.\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`.\nProvide your own Slack payload/markdown (this library no longer generates a payload step for you).\n\nOption A: slackapi/slack-github-action (Incoming Webhook, official syntax)\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@v2.1.1',\n // by default, post steps run only when drift is detected; you can override `if`\n if: \"always() && steps.drift.outcome == 'failure'\",\n // Use official inputs: webhook + webhook-type, and a YAML payload with blocks\n with: {\n webhook: '${{ secrets.CDK_NOTIFICATIONS_SLACK_WEBHOOK }}',\n 'webhook-type': 'incoming-webhook',\n payload: [\n `text: \"** ${stack} ** has drifted!\"`,\n 'blocks:',\n ' - type: \"section\"',\n ' text:',\n ' type: \"mrkdwn\"',\n ' text: \"*Stack:* ${stack} (region `${{ env.AWS_REGION }}`)\"',\n ' - type: \"section\"',\n ' fields:',\n ' - type: \"mrkdwn\"',\n ' text: \"*Stack ARN*\\\\n${{ steps.drift.outputs.stack-arn }}\"',\n ' - type: \"mrkdwn\"',\n ' text: \"*Issue*\\\\n<${{ github.server_url }}/${{ github.repository }}/issues/${{ steps.issue.outputs.result }}|#${{ steps.issue.outputs.result }}>\"',\n ].join('\\n'),\n },\n };\n return [step];\n },\n});\n```\n\nNote: The Issue link requires `createIssues: true` (default) so that the `Create Issue on Drift` step runs before this Slack step and exposes `steps.issue.outputs.result`. This library orders the steps accordingly.\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.\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.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`\n - `${{ steps.drift.outcome }}` — success/failure of the detect step\n - `${{ steps.drift.outputs.stack-arn }}` — Stack ARN resolved at runtime\n - `${{ steps.issue.outputs.result }}` — Issue number if the workflow created/found one (empty when not applicable)\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": 61
|
|
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": 58
|
|
3970
3970
|
},
|
|
3971
3971
|
"name": "CdkDriftDetectionWorkflow",
|
|
3972
3972
|
"symbolId": "src/CdkDriftDetectionWorkflow:CdkDriftDetectionWorkflow"
|
|
@@ -4085,14 +4085,14 @@
|
|
|
4085
4085
|
{
|
|
4086
4086
|
"abstract": true,
|
|
4087
4087
|
"docs": {
|
|
4088
|
-
"remarks": "These steps
|
|
4088
|
+
"remarks": "These steps run after results are uploaded for each stack. You can include\nany notifications you like (e.g., Slack). Provide explicit inputs (e.g., payload/markdown)\ndirectly in your step without relying on a pre-generated payload.",
|
|
4089
4089
|
"stability": "experimental",
|
|
4090
4090
|
"summary": "Optional additional GitHub Action steps to run after drift detection for each stack."
|
|
4091
4091
|
},
|
|
4092
4092
|
"immutable": true,
|
|
4093
4093
|
"locationInModule": {
|
|
4094
4094
|
"filename": "src/CdkDriftDetectionWorkflow.ts",
|
|
4095
|
-
"line":
|
|
4095
|
+
"line": 43
|
|
4096
4096
|
},
|
|
4097
4097
|
"name": "postGitHubSteps",
|
|
4098
4098
|
"optional": true,
|
|
@@ -4355,5 +4355,5 @@
|
|
|
4355
4355
|
}
|
|
4356
4356
|
},
|
|
4357
4357
|
"version": "0.0.0",
|
|
4358
|
-
"fingerprint": "
|
|
4358
|
+
"fingerprint": "V4ZorVAcHJaWo+h/52NapWT/1bIPqDHxg7kP5emFsBs="
|
|
4359
4359
|
}
|
package/README.md
CHANGED
|
@@ -207,14 +207,18 @@ project.synth();
|
|
|
207
207
|
- Each stack job uploads `drift-results-<stack>.json` (if produced).
|
|
208
208
|
- A final `Drift Detection Summary` job downloads all artifacts and prints a consolidated summary.
|
|
209
209
|
|
|
210
|
+
### Manual dispatch
|
|
211
|
+
- The workflow exposes an input named `stack` with choices including each configured stack and an `all` option.
|
|
212
|
+
- Choose a specific stack to run drift detection for that stack only, or select `all` (or leave the input empty) to run all stacks.
|
|
213
|
+
|
|
210
214
|
Note: The default workflow does not post PR comments for drift. It can create/update an Issue on scheduled runs when `createIssues` is `true`.
|
|
211
215
|
|
|
212
216
|
### Post-notification steps (e.g., Slack)
|
|
213
217
|
|
|
214
218
|
You can add your own GitHub Action steps to run after the drift detection step for each stack using `postGitHubSteps`.
|
|
215
|
-
|
|
219
|
+
Provide your own Slack payload/markdown (this library no longer generates a payload step for you).
|
|
216
220
|
|
|
217
|
-
Option A: slackapi/slack-github-action (Incoming Webhook)
|
|
221
|
+
Option A: slackapi/slack-github-action (Incoming Webhook, official syntax)
|
|
218
222
|
|
|
219
223
|
```ts
|
|
220
224
|
new CdkDriftDetectionWorkflow({
|
|
@@ -227,24 +231,27 @@ new CdkDriftDetectionWorkflow({
|
|
|
227
231
|
const name = `Notify Slack (${stack} post-drift)`;
|
|
228
232
|
const step = {
|
|
229
233
|
name,
|
|
230
|
-
uses: 'slackapi/slack-github-action@v2',
|
|
234
|
+
uses: 'slackapi/slack-github-action@v2.1.1',
|
|
231
235
|
// by default, post steps run only when drift is detected; you can override `if`
|
|
232
236
|
if: "always() && steps.drift.outcome == 'failure'",
|
|
233
|
-
//
|
|
234
|
-
// the prepared payload: ${{ steps.notify.outputs.result }}
|
|
235
|
-
// You can also use the v2 inputs like `markdown` directly if preferred.
|
|
237
|
+
// Use official inputs: webhook + webhook-type, and a YAML payload with blocks
|
|
236
238
|
with: {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
'
|
|
242
|
-
'
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
239
|
+
webhook: '${{ secrets.CDK_NOTIFICATIONS_SLACK_WEBHOOK }}',
|
|
240
|
+
'webhook-type': 'incoming-webhook',
|
|
241
|
+
payload: [
|
|
242
|
+
`text: "** ${stack} ** has drifted!"`,
|
|
243
|
+
'blocks:',
|
|
244
|
+
' - type: "section"',
|
|
245
|
+
' text:',
|
|
246
|
+
' type: "mrkdwn"',
|
|
247
|
+
' text: "*Stack:* ${stack} (region `${{ env.AWS_REGION }}`)"',
|
|
248
|
+
' - type: "section"',
|
|
249
|
+
' fields:',
|
|
250
|
+
' - type: "mrkdwn"',
|
|
251
|
+
' text: "*Stack ARN*\\n${{ steps.drift.outputs.stack-arn }}"',
|
|
252
|
+
' - type: "mrkdwn"',
|
|
253
|
+
' text: "*Issue*\\n<${{ github.server_url }}/${{ github.repository }}/issues/${{ steps.issue.outputs.result }}|#${{ steps.issue.outputs.result }}>"',
|
|
254
|
+
].join('\n'),
|
|
248
255
|
},
|
|
249
256
|
};
|
|
250
257
|
return [step];
|
|
@@ -252,36 +259,19 @@ new CdkDriftDetectionWorkflow({
|
|
|
252
259
|
});
|
|
253
260
|
```
|
|
254
261
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
Refer to Slack’s docs for sending via webhook to start a Slack workflow:
|
|
258
|
-
https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-webhook-slack-workflow/
|
|
259
|
-
|
|
260
|
-
Provide a flattened payload for your Workflow Builder, for example:
|
|
261
|
-
|
|
262
|
-
```yaml
|
|
263
|
-
- name: Notify Slack (webhook)
|
|
264
|
-
uses: slackapi/slack-github-action@v2
|
|
265
|
-
with:
|
|
266
|
-
payload: |
|
|
267
|
-
{ "stack": "${{ env.STACK_NAME }}", "status": "${{ steps.drift.outcome }}", "stackArn": "${{ steps.drift.outputs.stack-arn }}", "issue": "${{ steps.issue.outputs.result }}" }
|
|
268
|
-
env:
|
|
269
|
-
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
270
|
-
```
|
|
262
|
+
Note: The Issue link requires `createIssues: true` (default) so that the `Create Issue on Drift` step runs before this Slack step and exposes `steps.issue.outputs.result`. This library orders the steps accordingly.
|
|
271
263
|
|
|
272
264
|
Details:
|
|
273
265
|
- `postGitHubSteps` can be:
|
|
274
266
|
- an array of step objects, or
|
|
275
267
|
- a factory function `({ stack }) => step | step[]`.
|
|
276
|
-
- Each step you provide is inserted after the results are uploaded
|
|
277
|
-
- The prepared payload is a Slack Block Kit JSON string summarizing results for that stack and is available at `${{ steps.notify.outputs.result }}`.
|
|
268
|
+
- Each step you provide is inserted after the results are uploaded.
|
|
278
269
|
- Default condition: if you do not set `if` on your step, it will default to `always() && steps.drift.outcome == 'failure'`.
|
|
279
270
|
- Available context/env you can use:
|
|
280
271
|
- `${{ env.STACK_NAME }}`, `${{ env.DRIFT_DETECTION_OUTPUT }}`
|
|
281
272
|
- `${{ steps.drift.outcome }}` — success/failure of the detect step
|
|
282
273
|
- `${{ steps.drift.outputs.stack-arn }}` — Stack ARN resolved at runtime
|
|
283
274
|
- `${{ steps.issue.outputs.result }}` — Issue number if the workflow created/found one (empty when not applicable)
|
|
284
|
-
- `${{ steps.notify.outputs.result }}` — Slack payload JSON
|
|
285
275
|
```
|
|
286
276
|
|
|
287
277
|
## Usage: CdkDriftIamTemplate
|
|
@@ -20,8 +20,9 @@ export interface CdkDriftDetectionWorkflowProps {
|
|
|
20
20
|
*/
|
|
21
21
|
/**
|
|
22
22
|
* Optional additional GitHub Action steps to run after drift detection for each stack.
|
|
23
|
-
* These steps
|
|
24
|
-
*
|
|
23
|
+
* These steps run after results are uploaded for each stack. You can include
|
|
24
|
+
* any notifications you like (e.g., Slack). Provide explicit inputs (e.g., payload/markdown)
|
|
25
|
+
* directly in your step without relying on a pre-generated payload.
|
|
25
26
|
*/
|
|
26
27
|
readonly postGitHubSteps?: any;
|
|
27
28
|
}
|
|
@@ -31,13 +31,13 @@ class CdkDriftDetectionWorkflow {
|
|
|
31
31
|
const gh = project.github ?? new github_1.GitHub(project);
|
|
32
32
|
const workflow = new github_1.GithubWorkflow(gh, name, { fileName });
|
|
33
33
|
// triggers: schedule + manual dispatch with stack choice
|
|
34
|
-
const stackChoices = props.stacks.map((s) => s.stackName);
|
|
34
|
+
const stackChoices = ['all', ...props.stacks.map((s) => s.stackName)];
|
|
35
35
|
workflow.on({
|
|
36
36
|
schedule: props.schedule ? [{ cron: props.schedule }] : undefined,
|
|
37
37
|
workflowDispatch: {
|
|
38
38
|
inputs: {
|
|
39
39
|
stack: {
|
|
40
|
-
description:
|
|
40
|
+
description: "Stack to check for drift ('all' to run every stack)",
|
|
41
41
|
required: false,
|
|
42
42
|
type: 'choice',
|
|
43
43
|
options: stackChoices,
|
|
@@ -52,7 +52,7 @@ class CdkDriftDetectionWorkflow {
|
|
|
52
52
|
const originalStackName = stack.stackName;
|
|
53
53
|
const jobId = `drift-${sanitizedStackName}`;
|
|
54
54
|
const resultsFile = `drift-results-${sanitizedStackName}.json`;
|
|
55
|
-
const innerCond = "github.event_name == 'schedule' || !github.event.inputs.stack || github.event.inputs.stack == '" + sanitizedStackName + "' || github.event.inputs.stack == '" + originalStackName + "'";
|
|
55
|
+
const innerCond = "github.event_name == 'schedule' || !github.event.inputs.stack || github.event.inputs.stack == 'all' || github.event.inputs.stack == '" + sanitizedStackName + "' || github.event.inputs.stack == '" + originalStackName + "'";
|
|
56
56
|
const condExpr = '${{ ' + innerCond + ' }}';
|
|
57
57
|
const notCondExpr = '${{ !(' + innerCond + ') }}';
|
|
58
58
|
const rawPost = props.postGitHubSteps;
|
|
@@ -134,31 +134,6 @@ class CdkDriftDetectionWorkflow {
|
|
|
134
134
|
uses: `actions/upload-artifact@${githubActionsUploadArtifactVersion}`,
|
|
135
135
|
with: { 'name': `drift-results-${sanitizedStackName}`, 'path': resultsFile, 'if-no-files-found': 'ignore' },
|
|
136
136
|
},
|
|
137
|
-
{
|
|
138
|
-
name: 'Prepare notification payload',
|
|
139
|
-
if: condExpr,
|
|
140
|
-
id: 'notify',
|
|
141
|
-
uses: `actions/github-script@${githubActionsGithubScriptVersion}`,
|
|
142
|
-
with: {
|
|
143
|
-
'result-encoding': 'string',
|
|
144
|
-
'script': notificationScript(sanitizedStackName, stack.driftDetectionRoleToAssumeRegion, resultsFile),
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
...postSteps.map((step) => {
|
|
148
|
-
const s = { ...step };
|
|
149
|
-
// By default, only run extra notification steps when drift occurs
|
|
150
|
-
s.if = s.if ?? "always() && steps.drift.outcome == 'failure'";
|
|
151
|
-
// If this is the Slack GitHub Action and no payload is provided, wire the prepared payload
|
|
152
|
-
const uses = (s.uses ?? '').toString().toLowerCase();
|
|
153
|
-
const isSlackAction = uses.includes('slackapi/slack-github-action');
|
|
154
|
-
if (isSlackAction) {
|
|
155
|
-
s.with = { ...(s.with ?? {}) };
|
|
156
|
-
if (s.with.payload == null) {
|
|
157
|
-
s.with.payload = '${{ steps.notify.outputs.result }}';
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return s;
|
|
161
|
-
}),
|
|
162
137
|
...(createIssues
|
|
163
138
|
? [
|
|
164
139
|
{
|
|
@@ -170,6 +145,12 @@ class CdkDriftDetectionWorkflow {
|
|
|
170
145
|
},
|
|
171
146
|
]
|
|
172
147
|
: []),
|
|
148
|
+
...postSteps.map((step) => {
|
|
149
|
+
const s = { ...step };
|
|
150
|
+
// By default, only run extra notification steps when drift occurs
|
|
151
|
+
s.if = s.if ?? "always() && steps.drift.outcome == 'failure'";
|
|
152
|
+
return s;
|
|
153
|
+
}),
|
|
173
154
|
],
|
|
174
155
|
};
|
|
175
156
|
}
|
|
@@ -234,46 +215,6 @@ function issueScript(stack, region, resultsFile) {
|
|
|
234
215
|
];
|
|
235
216
|
return lines.join('\n');
|
|
236
217
|
}
|
|
237
|
-
function notificationScript(stack, region, resultsFile) {
|
|
238
|
-
const lines = [
|
|
239
|
-
"const fs = require('fs');",
|
|
240
|
-
`const resultsFile = '${resultsFile}';`,
|
|
241
|
-
'let payload;',
|
|
242
|
-
'if (!fs.existsSync(resultsFile)) {',
|
|
243
|
-
` payload = { text: 'Drift Detection (${stack}) - No results found', blocks: [`,
|
|
244
|
-
` { type: 'section', text: { type: 'mrkdwn', text: '*Drift Detection (${stack})*' } },`,
|
|
245
|
-
" { type: 'section', text: { type: 'mrkdwn', text: 'No results file found. The detection step may have been skipped.' } }",
|
|
246
|
-
' ] };',
|
|
247
|
-
' return JSON.stringify(payload);',
|
|
248
|
-
'}',
|
|
249
|
-
"const results = JSON.parse(fs.readFileSync(resultsFile, 'utf8'));",
|
|
250
|
-
"const drifted = results.filter(r => r.driftStatus === 'DRIFTED');",
|
|
251
|
-
'const errors = results.filter(r => r.error);',
|
|
252
|
-
`const header = '*Drift Detection (${stack})* — Region: ${region}';`,
|
|
253
|
-
'const summary = "Total stacks: " + results.length + " | Drifted: " + drifted.length + " | Errors: " + errors.length;',
|
|
254
|
-
'const linesArr: string[] = [];',
|
|
255
|
-
'for (const s of drifted) {',
|
|
256
|
-
' const count = (s.driftedResources || []).length;',
|
|
257
|
-
" linesArr.push('• ' + s.stackName + ' — ' + count + ' resource(s) drifted');",
|
|
258
|
-
'}',
|
|
259
|
-
'payload = {',
|
|
260
|
-
` text: 'Drift Detection (${stack})',`,
|
|
261
|
-
' blocks: [',
|
|
262
|
-
" { type: 'section', text: { type: 'mrkdwn', text: header } },",
|
|
263
|
-
" { type: 'context', elements: [{ type: 'mrkdwn', text: summary }] },",
|
|
264
|
-
' ...(drifted.length > 0 ? [',
|
|
265
|
-
" { type: 'divider' },",
|
|
266
|
-
" { type: 'section', text: { type: 'mrkdwn', text: '*Drifted Stacks:*\\n' + linesArr.join('\\n') } }",
|
|
267
|
-
' ] : [',
|
|
268
|
-
" { type: 'divider' },",
|
|
269
|
-
" { type: 'section', text: { type: 'mrkdwn', text: 'No drift detected.' } }",
|
|
270
|
-
' ])',
|
|
271
|
-
' ]',
|
|
272
|
-
'};',
|
|
273
|
-
'return JSON.stringify(payload);',
|
|
274
|
-
];
|
|
275
|
-
return lines.join('\n');
|
|
276
|
-
}
|
|
277
218
|
function summaryScript() {
|
|
278
219
|
return [
|
|
279
220
|
'#!/bin/bash',
|
|
@@ -335,4 +276,4 @@ function toGithubJobId(s) {
|
|
|
335
276
|
}
|
|
336
277
|
return out;
|
|
337
278
|
}
|
|
338
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9DZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsOENBQTJEO0FBQzNELHVFQUFrRTtBQUNsRSxpRkFBMkU7QUFFM0UsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSxvQ0FBb0MsR0FBRyxJQUFJLENBQUM7QUFDbEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLENBQUM7QUErQzlDLE1BQWEseUJBQXlCO0lBR3BDLFlBQVksS0FBcUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxpQkFBaUIsQ0FBQztRQUNyRCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQzVDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDO1FBQ2hELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDOUIsTUFBTSxnQkFBZ0IsR0FBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksMkNBQTJDLENBQUM7UUFFOUYsa0VBQWtFO1FBQ2xFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM3QyxJQUFJLG9EQUF1QixDQUFDO2dCQUMxQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7YUFDN0IsQ0FBQyxDQUFDO1lBQ0gseUJBQXlCLENBQUMsYUFBYSxH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Q0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN4QixrREFBa0Q7SUFDbEQsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxHQUFHLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgR2l0SHViLCBHaXRodWJXb3JrZmxvdyB9IGZyb20gJ3Byb2plbi9saWIvZ2l0aHViJztcbmltcG9ydCB7IEpvYlBlcm1pc3Npb24gfSBmcm9tICdwcm9qZW4vbGliL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWwnO1xuaW1wb3J0IHsgQ2RrRHJpZnREZXRlY3Rpb25TY3JpcHQgfSBmcm9tICcuL2Jpbi9jZGstZHJpZnQtZGV0ZWN0aW9uLXNjcmlwdCc7XG5cbmNvbnN0IGdpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb24gPSAndjUnO1xuY29uc3QgZ2l0aHViQWN0aW9uc0NoZWNrb3V0VmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zVXBsb2FkQXJ0aWZhY3RWZXJzaW9uID0gJ3Y0JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNEb3dubG9hZEFydGlmYWN0VmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zR2l0aHViU2NyaXB0VmVyc2lvbiA9ICd2OCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2sge1xuICByZWFkb25seSBzdGFja05hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb246IHN0cmluZztcbiAgcmVhZG9ubHkgZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm46IHN0cmluZztcbiAgcmVhZG9ubHkgZmFpbE9uRHJpZnQ/OiBib29sZWFuOyAvLyBpZiB0cnVlLCBmYWlsIGpvYiB3aGVuIGRyaWZ0IGRldGVjdGVkIChkZWZhdWx0IHRydWUpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvd1Byb3BzIHtcbiAgcmVhZG9ubHkgc2NyaXB0T3V0cHV0UGF0aD86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvamVjdDogYW55OyAvLyBhdm9pZCBleHBvcnRpbmcgcHJvamVuIHR5cGVzIGluIHB1YmxpYyBBUElcbiAgcmVhZG9ubHkgd29ya2Zsb3dOYW1lPzogc3RyaW5nOyAvLyB3b3JrZmxvdyB3b3JrZmxvd05hbWUgKGFsc28gdXNlZCB0byBkZXJpdmUgZmlsZSB3b3JrZmxvd05hbWUpXG4gIHJlYWRvbmx5IHNjaGVkdWxlPzogc3RyaW5nOyAvLyBjcm9uIGV4cHJlc3Npb24sIGUuZy4gJzAgMCAqICogKidcbiAgcmVhZG9ubHkgY3JlYXRlSXNzdWVzPzogYm9vbGVhbjsgLy8gY3JlYXRlL3VwZGF0ZSBpc3N1ZSB3aGVuIGRyaWZ0IGRldGVjdGVkIG9uIHNjaGVkdWxlIChkZWZhdWx0IHRydWUpXG4gIHJlYWRvbmx5IG9pZGNSb2xlQXJuOiBzdHJpbmc7IC8vIGRlZmF1bHQgT0lEQyByb2xlIEFSTiB0byBhc3N1bWUgZm9yIGFsbCBzdGFja3NcbiAgcmVhZG9ubHkgb2lkY1JlZ2lvbjogc3RyaW5nOyAvLyBkZWZhdWx0IE9JREMgcmVnaW9uIHRvIGFzc3VtZSBmb3IgYWxsIHN0YWNrc1xuICByZWFkb25seSBzdGFja3M6IFN0YWNrW107XG4gIHJlYWRvbmx5IG5vZGVWZXJzaW9uPzogc3RyaW5nOyAvLyBlLmcuLCAnMjQueCdcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGhvb2sgdG8gYXBwZW5kIGFkZGl0aW9uYWwgR2l0SHViIEFjdGlvbnMgc3RlcHMgYWZ0ZXIgZHJpZnQgZGV0ZWN0aW9uIHBlciBzdGFjay5cbiAgICogWW91IGNhbiBzdXBwbHkgYSBzdGF0aWMgYXJyYXkgb2Ygc3RlcHMsIG9yIGEgZmFjdG9yeSB0aGF0IHJlY2VpdmVzIGNvbnRleHQgYW5kIHJldHVybnMgc3RlcHMuXG4gICAqL1xuICAvKipcbiAgICogT3B0aW9uYWwgYWRkaXRpb25hbCBHaXRIdWIgQWN0aW9uIHN0ZXBzIHRvIHJ1biBhZnRlciBkcmlmdCBkZXRlY3Rpb24gZm9yIGVhY2ggc3RhY2suXG4gICAqIFRoZXNlIHN0ZXBzIGFyZSBpbnNlcnRlZCBhZnRlciBhICdQcmVwYXJlIG5vdGlmaWNhdGlvbiBwYXlsb2FkJyBzdGVwIHdoaWNoIGV4cG9zZXNcbiAgICogYSBTbGFjay1jb21wYXRpYmxlIEpTT04gcGF5bG9hZCBhdCBgJHt7IHN0ZXBzLm5vdGlmeS5vdXRwdXRzLnJlc3VsdCB9fWAuXG4gICAqL1xuICAvLyBOT1RFOiBqc2lpIGRvZXMgbm90IHN1cHBvcnQgZnVuY3Rpb24gdHlwZXMgaW4gcHVibGljIEFQSXM7IHVzZSAnYW55JyBoZXJlIGFuZCBhY2NlcHQgZWl0aGVyOlxuICAvLyAtIEFuIGFycmF5IG9mIEdpdEh1YiBzdGVwcywgb3JcbiAgLy8gLSBBIGZ1bmN0aW9uIChjdHg6IHsgc3RhY2s6IHN0cmluZyB9KSA9PiBHaXRIdWJTdGVwW11cbiAgLy8gVGhlIGNvbnN0cnVjdG9yIGhhbmRsZXMgYm90aCBhdCBydW50aW1lLlxuICByZWFkb25seSBwb3N0R2l0SHViU3RlcHM/OiBhbnk7XG59XG5cbnR5cGUgR2l0SHViU3RlcCA9IHtcbiAgbmFtZT86IHN0cmluZztcbiAgaWQ/OiBzdHJpbmc7XG4gIGlmPzogc3RyaW5nO1xuICB1c2VzPzogc3RyaW5nO1xuICBydW4/OiBzdHJpbmc7XG4gIHdpdGg/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBjb250aW51ZU9uRXJyb3I/OiBib29sZWFuO1xuICBzaGVsbD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjbGFzcyBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93IHtcbiAgcHJpdmF0ZSBzdGF0aWMgc2NyaXB0Q3JlYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93UHJvcHMpIHtcbiAgICBjb25zdCBuYW1lID0gcHJvcHMud29ya2Zsb3dOYW1lID8/ICdkcmlmdC1kZXRlY3Rpb24nO1xuICAgIGNvbnN0IGZpbGVOYW1lID0gdG9LZWJhYkNhc2UobmFtZSkgKyAnLnltbCc7XG4gICAgY29uc3Qgbm9kZVZlcnNpb24gPSBwcm9wcy5ub2RlVmVyc2lvbiA/PyAnMjQueCc7XG4gICAgY29uc3QgY3JlYXRlSXNzdWVzID0gcHJvcHMuY3JlYXRlSXNzdWVzID8/IHRydWU7XG4gICAgY29uc3QgcHJvamVjdCA9IHByb3BzLnByb2plY3Q7XG4gICAgY29uc3Qgc2NyaXB0T3V0cHV0UGF0aD0gcHJvcHMuc2NyaXB0T3V0cHV0UGF0aCA/PyAnLmdpdGh1Yi93b3JrZmxvd3Mvc2NyaXB0cy9kZXRlY3QtZHJpZnQudHMnO1xuXG4gICAgLy8gT25seSBjcmVhdGUgdGhlIGRyaWZ0IGRldGVjdGlvbiBzY3JpcHQgb25jZSB0byBhdm9pZCBjb2xsaXNpb25zXG4gICAgaWYgKCFDZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnNjcmlwdENyZWF0ZWQpIHtcbiAgICAgIG5ldyBDZGtEcmlmdERldGVjdGlvblNjcmlwdCh7XG4gICAgICAgIHByb2plY3Q6IHByb3BzLnByb2plY3QsXG4gICAgICAgIG91dHB1dFBhdGg6IHNjcmlwdE91dHB1dFBhdGgsXG4gICAgICB9KTtcbiAgICAgIENka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3cuc2NyaXB0Q3JlYXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgZ2ggPSAocHJvamVjdCBhcyBhbnkpLmdpdGh1YiA/PyBuZXcgR2l0SHViKHByb2plY3QpO1xuICAgIGNvbnN0IHdvcmtmbG93ID0gbmV3IEdpdGh1YldvcmtmbG93KGdoLCBuYW1lLCB7IGZpbGVOYW1lIH0pO1xuXG4gICAgLy8gdHJpZ2dlcnM6IHNjaGVkdWxlICsgbWFudWFsIGRpc3BhdGNoIHdpdGggc3RhY2sgY2hvaWNlXG4gICAgY29uc3Qgc3RhY2tDaG9pY2VzID0gcHJvcHMuc3RhY2tzLm1hcCgocykgPT4gcy5zdGFja05hbWUpO1xuICAgIHdvcmtmbG93Lm9uKHtcbiAgICAgIHNjaGVkdWxlOiBwcm9wcy5zY2hlZHVsZSA/IFt7IGNyb246IHByb3BzLnNjaGVkdWxlIH1dIDogdW5kZWZpbmVkLFxuICAgICAgd29ya2Zsb3dEaXNwYXRjaDoge1xuICAgICAgICBpbnB1dHM6IHtcbiAgICAgICAgICBzdGFjazoge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdTdGFjayB0byBjaGVjayBmb3IgZHJpZnQgKGxlYXZlIGVtcHR5IGZvciBhbGwpJyxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIHR5cGU6ICdjaG9pY2UnLFxuICAgICAgICAgICAgb3B0aW9uczogc3RhY2tDaG9pY2VzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gT25lIGpvYiBwZXIgc3RhY2tcbiAgICBjb25zdCBqb2JzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IHN0YWNrIG9mIHByb3BzLnN0YWNrcykge1xuICAgICAgY29uc3Qgc2FuaXRpemVkU3RhY2tOYW1lID0gdG9LZWJhYkNhc2UodG9HaXRodWJKb2JJZChzdGFjay5zdGFja05hbWUpKTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsU3RhY2tOYW1lID0gc3RhY2suc3RhY2tOYW1lO1xuICAgICAgY29uc3Qgam9iSWQgPSBgZHJpZnQtJHtzYW5pdGl6ZWRTdGFja05hbWV9YDtcbiAgICAgIGNvbnN0IHJlc3VsdHNGaWxlID0gYGRyaWZ0LXJlc3VsdHMtJHtzYW5pdGl6ZWRTdGFja05hbWV9Lmpzb25gO1xuICAgICAgY29uc3QgaW5uZXJDb25kID0gXCJnaXRodWIuZXZlbnRfbmFtZSA9PSAnc2NoZWR1bGUnIHx8ICFnaXRodWIuZXZlbnQuaW5wdXRzLnN0YWNrIHx8IGdpdGh1Yi5ldmVudC5pbnB1dHMuc3RhY2sgPT0gJ1wiICsgc2FuaXRpemVkU3RhY2tOYW1lICsgXCInIHx8IGdpdGh1Yi5ldmVudC5pbnB1dHMuc3RhY2sgPT0gJ1wiICsgb3JpZ2luYWxTdGFja05hbWUgKyBcIidcIjtcbiAgICAgIGNvbnN0IGNvbmRFeHByID0gJyR7eyAnICsgaW5uZXJDb25kICsgJyB9fSc7XG4gICAgICBjb25zdCBub3RDb25kRXhwciA9ICcke3sgISgnICsgaW5uZXJDb25kICsgJykgfX0nO1xuXG4gICAgICBjb25zdCByYXdQb3N0ID0gcHJvcHMucG9zdEdpdEh1YlN0ZXBzO1xuICAgICAgY29uc3QgcG9zdFN0ZXBzOiBHaXRIdWJTdGVwW10gPSB0eXBlb2YgcmF3UG9zdCA9PT0gJ2Z1bmN0aW9uJyA/IChyYXdQb3N0IGFzIChjdHg6IHsgc3RhY2s6IHN0cmluZyB9KSA9PiBHaXRIdWJTdGVwW10pKHsgc3RhY2s6IHNhbml0aXplZFN0YWNrTmFtZSB9KSA6IChyYXdQb3N0ID8/IFtdKTtcblxuICAgICAgam9ic1tqb2JJZF0gPSB7XG4gICAgICAgIG5hbWU6IGBEcmlmdCBEZXRlY3Rpb24gLSAke3Nhbml0aXplZFN0YWNrTmFtZX1gLFxuICAgICAgICBydW5zT246IFsndWJ1bnR1LWxhdGVzdCddLFxuICAgICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICAgIGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLlJFQUQsXG4gICAgICAgICAgaWRUb2tlbjogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgICAgICBpc3N1ZXM6IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgIH0sXG4gICAgICAgIGVudjoge1xuICAgICAgICAgIEFXU19ERUZBVUxUX1JFR0lPTjogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sXG4gICAgICAgICAgQVdTX1JFR0lPTjogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sXG4gICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgU1RBQ0tfSUQ6IHNhbml0aXplZFN0YWNrTmFtZSxcbiAgICAgICAgICBTVEFDS19OQU1FOiBzdGFjay5zdGFja05hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIC8vIE5vIGpvYi1sZXZlbCBjb25kaXRpb247IHdlIGdhdGUgc3RlcHMgc28gdGhlIGpvYiBhbHdheXMgY29tcGxldGVzIGFuZCBzdW1tYXJ5IGNhbiBydW5cbiAgICAgICAgc3RlcHM6IFtcbiAgICAgICAgICB7IG5hbWU6ICdTa2lwIChzdGFjayBub3Qgc2VsZWN0ZWQpJywgaWY6IG5vdENvbmRFeHByLCBydW46ICdlY2hvIFwiU3RhY2sgbm90IHNlbGVjdGVkOyBza2lwcGluZyBkcmlmdCBkZXRlY3Rpb24gZm9yIHRoaXMgam9iLlwiJyB9LFxuICAgICAgICAgIHsgbmFtZTogJ0NoZWNrb3V0JywgaWY6IGNvbmRFeHByLCB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke2dpdGh1YkFjdGlvbnNDaGVja291dFZlcnNpb259YCB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3NldHVwLW5vZGVAJHtnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbn1gLFxuICAgICAgICAgICAgd2l0aDogeyAnbm9kZS12ZXJzaW9uJzogbm9kZVZlcnNpb24gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbmFtZTogJ0luc3RhbGwgZGVwZW5kZW5jaWVzJywgaWY6IGNvbmRFeHByLCBydW46ICd5YXJuIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGUgfHwgbnBtIGNpJywgZW52OiB7IEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdBV1MgQ3JlZGVudGlhbHMnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdjcmVkcycsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogcHJvcHMub2lkY1JvbGVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLXNlc3Npb24tbmFtZSc6ICdHaXRIdWJBY3Rpb24nLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHByb3BzLm9pZGNSZWdpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0Fzc3VtZSBEcmlmdCBEZXRlY3Rpb24gUm9sZScsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLWNoYWluaW5nJzogdHJ1ZSxcbiAgICAgICAgICAgICAgJ3JvbGUtc2tpcC1zZXNzaW9uLXRhZ2dpbmcnOiB0cnVlLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgICAgICAnYXdzLWFjY2Vzcy1rZXktaWQnOiAnJHt7IHN0ZXBzLmNyZWRzLm91dHB1dHMuYXdzLWFjY2Vzcy1rZXktaWQgfX0nLFxuICAgICAgICAgICAgICAnYXdzLXNlY3JldC1hY2Nlc3Mta2V5JzogJyR7eyBzdGVwcy5jcmVkcy5vdXRwdXRzLmF3cy1zZWNyZXQtYWNjZXNzLWtleSB9fScsXG4gICAgICAgICAgICAgICdhd3Mtc2Vzc2lvbi10b2tlbic6ICcke3sgc3RlcHMuY3JlZHMub3V0cHV0cy5hd3Mtc2Vzc2lvbi10b2tlbiB9fScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0RldGVjdCBkcmlmdCcsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICBpZDogJ2RyaWZ0JyxcbiAgICAgICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSwgLy8gYWxsb3cgYXJ0aWZhY3QgdXBsb2FkIGFuZCBpc3N1ZSBjcmVhdGlvbiBldmVuIHdoZW4gZHJpZnQgaXMgZGV0ZWN0ZWRcbiAgICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgICAnc2V0IC1lJyxcbiAgICAgICAgICAgICAgLy8gVXNlIHRoZSBidW5kbGVkIHNjcmlwdCBmcm9tIHRoaXMgcGFja2FnZVxuICAgICAgICAgICAgICAnbm9kZSAuL25vZGVfbW9kdWxlcy9AampyYXdsaW5zL2Nkay1kaWZmLXByLWdpdGh1Yi1hY3Rpb24vbGliL2Jpbi9kZXRlY3QtZHJpZnQuanMnLFxuICAgICAgICAgICAgICAnaWYgWyAtZiBcIiREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCIgXTsgdGhlbiBlY2hvIFwiUmVzdWx0cyBmaWxlIGNyZWF0ZWQ6ICREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCI7IGZpJyxcbiAgICAgICAgICAgICAgLy8gRXhwb3NlIHVzZWZ1bCBvdXRwdXRzIGZvciBkb3duc3RyZWFtIHN0ZXBzXG4gICAgICAgICAgICAgIFwiU1RBQ0tfQVJOPSQoYXdzIGNsb3VkZm9ybWF0aW9uIGRlc2NyaWJlLXN0YWNrcyAtLXN0YWNrLW5hbWUgXFxcIiRTVEFDS19OQU1FXFxcIiAtLXF1ZXJ5ICdTdGFja3NbMF0uU3RhY2tJZCcgLS1vdXRwdXQgdGV4dCAyPi9kZXYvbnVsbCB8fCB0cnVlKVwiLFxuICAgICAgICAgICAgICAnZWNobyBcInN0YWNrLWFybj0kU1RBQ0tfQVJOXCIgPj4gXCIkR0lUSFVCX09VVFBVVFwiJyxcbiAgICAgICAgICAgIF0uam9pbignXFxuJyksXG4gICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgU1RBQ0tfTkFNRTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICAgICAgICBBV1NfUkVHSU9OOiBzdGFjay5kcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbixcbiAgICAgICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1VwbG9hZCByZXN1bHRzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3VwbG9hZC1hcnRpZmFjdEAke2dpdGh1YkFjdGlvbnNVcGxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHsgJ25hbWUnOiBgZHJpZnQtcmVzdWx0cy0ke3Nhbml0aXplZFN0YWNrTmFtZX1gLCAncGF0aCc6IHJlc3VsdHNGaWxlLCAnaWYtbm8tZmlsZXMtZm91bmQnOiAnaWdub3JlJyB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1ByZXBhcmUgbm90aWZpY2F0aW9uIHBheWxvYWQnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdub3RpZnknLFxuICAgICAgICAgICAgdXNlczogYGFjdGlvbnMvZ2l0aHViLXNjcmlwdEAke2dpdGh1YkFjdGlvbnNHaXRodWJTY3JpcHRWZXJzaW9ufWAsXG4gICAgICAgICAgICB3aXRoOiB7XG4gICAgICAgICAgICAgICdyZXN1bHQtZW5jb2RpbmcnOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgJ3NjcmlwdCc6IG5vdGlmaWNhdGlvblNjcmlwdChzYW5pdGl6ZWRTdGFja05hbWUsIHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLCByZXN1bHRzRmlsZSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4ucG9zdFN0ZXBzLm1hcCgoc3RlcCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgczogYW55ID0geyAuLi4oc3RlcCBhcyBhbnkpIH07XG4gICAgICAgICAgICAvLyBCeSBkZWZhdWx0LCBvbmx5IHJ1biBleHRyYSBub3RpZmljYXRpb24gc3RlcHMgd2hlbiBkcmlmdCBvY2N1cnNcbiAgICAgICAgICAgIHMuaWYgPSBzLmlmID8/IFwiYWx3YXlzKCkgJiYgc3RlcHMuZHJpZnQub3V0Y29tZSA9PSAnZmFpbHVyZSdcIjtcbiAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgdGhlIFNsYWNrIEdpdEh1YiBBY3Rpb24gYW5kIG5vIHBheWxvYWQgaXMgcHJvdmlkZWQsIHdpcmUgdGhlIHByZXBhcmVkIHBheWxvYWRcbiAgICAgICAgICAgIGNvbnN0IHVzZXMgPSAocy51c2VzID8/ICcnKS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICBjb25zdCBpc1NsYWNrQWN0aW9uID0gdXNlcy5pbmNsdWRlcygnc2xhY2thcGkvc2xhY2stZ2l0aHViLWFjdGlvbicpO1xuICAgICAgICAgICAgaWYgKGlzU2xhY2tBY3Rpb24pIHtcbiAgICAgICAgICAgICAgcy53aXRoID0geyAuLi4ocy53aXRoID8/IHt9KSB9O1xuICAgICAgICAgICAgICBpZiAocy53aXRoLnBheWxvYWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHMud2l0aC5wYXlsb2FkID0gJyR7eyBzdGVwcy5ub3RpZnkub3V0cHV0cy5yZXN1bHQgfX0nO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcztcbiAgICAgICAgICB9KSxcbiAgICAgICAgICAuLi4oXG4gICAgICAgICAgICBjcmVhdGVJc3N1ZXNcbiAgICAgICAgICAgICAgPyBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgbmFtZTogJ0NyZWF0ZSBJc3N1ZSBvbiBEcmlmdCcsXG4gICAgICAgICAgICAgICAgICBpZjogXCJhbHdheXMoKSAmJiBzdGVwcy5kcmlmdC5vdXRjb21lID09ICdmYWlsdXJlJ1wiLFxuICAgICAgICAgICAgICAgICAgaWQ6ICdpc3N1ZScsXG4gICAgICAgICAgICAgICAgICB1c2VzOiBgYWN0aW9ucy9naXRodWItc2NyaXB0QCR7Z2l0aHViQWN0aW9uc0dpdGh1YlNjcmlwdFZlcnNpb259YCxcbiAgICAgICAgICAgICAgICAgIHdpdGg6IHsgJ3Jlc3VsdC1lbmNvZGluZyc6ICdzdHJpbmcnLCAnc2NyaXB0JzogaXNzdWVTY3JpcHQoc2FuaXRpemVkU3RhY2tOYW1lLCBzdGFjay5kcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbiwgcmVzdWx0c0ZpbGUpIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICA6IFtdXG4gICAgICAgICAgKSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gc3VtbWFyeSBhZ2dyZWdhdG9yIGpvYlxuICAgIGpvYnNbJ2RyaWZ0LXN1bW1hcnknXSA9IHtcbiAgICAgIG5hbWU6ICdEcmlmdCBEZXRlY3Rpb24gU3VtbWFyeScsXG4gICAgICBuZWVkczogT2JqZWN0LmtleXMoam9icykuZmlsdGVyKChqKSA9PiBqLnN0YXJ0c1dpdGgoJ2RyaWZ0LScpICYmIGogIT09ICdkcmlmdC1zdW1tYXJ5JyksXG4gICAgICBydW5zT246IFsndWJ1bnR1LWxhdGVzdCddLFxuICAgICAgcGVybWlzc2lvbnM6IHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uUkVBRCB9LFxuICAgICAgc3RlcHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdEb3dubG9hZCBhbGwgYXJ0aWZhY3RzJyxcbiAgICAgICAgICB1c2VzOiBgYWN0aW9ucy9kb3dubG9hZC1hcnRpZmFjdEAke2dpdGh1YkFjdGlvbnNEb3dubG9hZEFydGlmYWN0VmVyc2lvbn1gLFxuICAgICAgICAgIHdpdGg6IHsgcGF0aDogJ2RyaWZ0LXJlc3VsdHMnIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHsgbmFtZTogJ0dlbmVyYXRlIHN1bW1hcnknLCBzaGVsbDogJ2Jhc2gnLCBydW46IHN1bW1hcnlTY3JpcHQoKSB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgd29ya2Zsb3cuYWRkSm9icyhqb2JzKTtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIGlzc3VlU2NyaXB0KHN0YWNrOiBzdHJpbmcsIHJlZ2lvbjogc3RyaW5nLCByZXN1bHRzRmlsZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gQ29uc3RydWN0IGEgcGxhaW4gSlMgc2NyaXB0IHN0cmluZyAobm8gdGVtcGxhdGUgc3RyaW5nIG5lc3RpbmcgbWlzaGFwcylcbiAgY29uc3QgbGluZXMgPSBbXG4gICAgXCJjb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJyk7XCIsXG4gICAgYGNvbnN0IHJlc3VsdHNGaWxlID0gJyR7cmVzdWx0c0ZpbGV9JztgLFxuICAgIFwiaWYgKCFmcy5leGlzdHNTeW5jKHJlc3VsdHNGaWxlKSkgeyBjb25zb2xlLmxvZygnTm8gcmVzdWx0cyBmaWxlIGZvdW5kJyk7IHJldHVybiAnTk9fUkVTVUxUUyc7IH1cIixcbiAgICBcImNvbnN0IHJlc3VsdHMgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhyZXN1bHRzRmlsZSwgJ3V0ZjgnKSk7XCIsXG4gICAgXCJjb25zdCBkcmlmdGVkU3RhY2tzID0gcmVzdWx0cy5maWx0ZXIociA9PiByLmRyaWZ0U3RhdHVzID09PSAnRFJJRlRFRCcpO1wiLFxuICAgIFwiaWYgKGRyaWZ0ZWRTdGFja3MubGVuZ3RoID09PSAwKSB7IGNvbnNvbGUubG9nKCdObyBkcmlmdCBkZXRlY3RlZCcpOyByZXR1cm4gJ05PX0RSSUZUJzsgfVwiLFxuICAgIGBjb25zdCB0aXRsZSA9ICdEcmlmdCBEZXRlY3RlZCBpbiAke3N0YWNrfSc7YCxcbiAgICBgbGV0IGJvZHkgPSAnIyMgRHJpZnQgRGV0ZWN0aW9uIFJlcG9ydFxcXFxuXFxcXG4nICsgJyoqU3RhY2s6KiogJHtzdGFja31cXFxcbicgKyAnKipSZWdpb246KiogJHtyZWdpb259XFxcXG4nICsgJyoqVGltZToqKiAnICsgbmV3IERhdGUoKS50b0lTT1N0cmluZygpICsgJ1xcXFxuXFxcXG4nO2AsXG4gICAgXCJib2R5ICs9ICcjIyMgU3VtbWFyeVxcXFxuJztcIixcbiAgICBcImJvZHkgKz0gJy0gVG90YWwgc3RhY2tzIGNoZWNrZWQ6ICcgKyByZXN1bHRzLmxlbmd0aCArICdcXFxcbic7XCIsXG4gICAgXCJib2R5ICs9ICctIERyaWZ0ZWQgc3RhY2tzOiAnICsgZHJpZnRlZFN0YWNrcy5sZW5ndGggKyAnXFxcXG5cXFxcbic7XCIsXG4gICAgXCJib2R5ICs9ICcjIyMgRHJpZnRlZCBTdGFja3NcXFxcbic7XCIsXG4gICAgJ2ZvciAoY29uc3QgcyBvZiBkcmlmdGVkU3RhY2tzKSB7JyxcbiAgICAnICBjb25zdCByZXNvdXJjZXMgPSBzLmRyaWZ0ZWRSZXNvdXJjZXMgfHwgW107JyxcbiAgICBcIiAgYm9keSArPSAnIyMjIyAnICsgcy5zdGFja05hbWUgKyAnXFxcXG4nO1wiLFxuICAgIFwiICBib2R5ICs9ICctIERyaWZ0ZWQgcmVzb3VyY2VzOiAnICsgcmVzb3VyY2VzLmxlbmd0aCArICdcXFxcbic7XCIsXG4gICAgXCIgIGZvciAoY29uc3QgciBvZiByZXNvdXJjZXMpIHsgYm9keSArPSAnICAtICcgKyByLmxvZ2ljYWxSZXNvdXJjZUlkICsgJyAoJyArIHIucmVzb3VyY2VUeXBlICsgJylcXFxcbic7IH1cIixcbiAgICBcIiAgYm9keSArPSAnXFxcXG4nO1wiLFxuICAgICd9JyxcbiAgICBcImJvZHkgKz0gJyMjIyBBY3Rpb24gUmVxdWlyZWRcXFxcbicgKyAnUGxlYXNlIHJldmlldyB0aGUgZHJpZnRlZCByZXNvdXJjZXMgYW5kIGVpdGhlcjpcXFxcbjEuIFVwZGF0ZSB0aGUgaW5mcmFzdHJ1Y3R1cmUgY29kZSB0byBtYXRjaCB0aGUgYWN0dWFsIHN0YXRlXFxcXG4yLiBSZXN0b3JlIHRoZSByZXNvdXJjZXMgdG8gbWF0Y2ggdGhlIGV4cGVjdGVkIHN0YXRlXFxcXG5cXFxcbic7XCIsXG4gICAgJ2JvZHkgKz0gYFtWaWV3IHdvcmtmbG93IHJ1bl0oJHtjb250ZXh0LnNlcnZlclVybH0vJHtjb250ZXh0LnJlcG8ub3duZXJ9LyR7Y29udGV4dC5yZXBvLnJlcG99L2FjdGlvbnMvcnVucy8ke2NvbnRleHQucnVuSWR9KWA7JyxcbiAgICAvLyBMaXN0IG9yIHVwZGF0ZSBhbiBpc3N1ZSB3aXRoIGxhYmVsc1xuICAgIGBjb25zdCBpc3N1ZXMgPSBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMubGlzdEZvclJlcG8oeyBvd25lcjogY29udGV4dC5yZXBvLm93bmVyLCByZXBvOiBjb250ZXh0LnJlcG8ucmVwbywgc3RhdGU6ICdvcGVuJywgbGFiZWxzOiBbJ2RyaWZ0LWRldGVjdGlvbicsICcke3N0YWNrfSddIH0pO2AsXG4gICAgJ2xldCBpc3N1ZU51bWJlcjsnLFxuICAgICdpZiAoaXNzdWVzLmRhdGEubGVuZ3RoID09PSAwKSB7JyxcbiAgICBgICBjb25zdCBjcmVhdGVkID0gYXdhaXQgZ2l0aHViLnJlc3QuaXNzdWVzLmNyZWF0ZSh7IG93bmVyOiBjb250ZXh0LnJlcG8ub3duZXIsIHJlcG86IGNvbnRleHQucmVwby5yZXBvLCB0aXRsZSwgYm9keSwgbGFiZWxzOiBbJ2RyaWZ0LWRldGVjdGlvbicsICcke3N0YWNrfSddIH0pO2AsXG4gICAgJyAgaXNzdWVOdW1iZXIgPSBjcmVhdGVkLmRhdGEubnVtYmVyOycsXG4gICAgJ30gZWxzZSB7JyxcbiAgICAnICBjb25zdCBpc3N1ZSA9IGlzc3Vlcy5kYXRhWzBdOycsXG4gICAgJyAgaXNzdWVOdW1iZXIgPSBpc3N1ZS5udW1iZXI7JyxcbiAgICAnICBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlQ29tbWVudCh7IG93bmVyOiBjb250ZXh0LnJlcG8ub3duZXIsIHJlcG86IGNvbnRleHQucmVwby5yZXBvLCBpc3N1ZV9udW1iZXI6IGlzc3VlLm51bWJlciwgYm9keSB9KTsnLFxuICAgICd9JyxcbiAgICAncmV0dXJuIFN0cmluZyhpc3N1ZU51bWJlciA/PyBcIlwiKTsnLFxuICBdO1xuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbmZ1bmN0aW9uIG5vdGlmaWNhdGlvblNjcmlwdChzdGFjazogc3RyaW5nLCByZWdpb246IHN0cmluZywgcmVzdWx0c0ZpbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGxpbmVzID0gW1xuICAgIFwiY29uc3QgZnMgPSByZXF1aXJlKCdmcycpO1wiLFxuICAgIGBjb25zdCByZXN1bHRzRmlsZSA9ICcke3Jlc3VsdHNGaWxlfSc7YCxcbiAgICAnbGV0IHBheWxvYWQ7JyxcbiAgICAnaWYgKCFmcy5leGlzdHNTeW5jKHJlc3VsdHNGaWxlKSkgeycsXG4gICAgYCAgcGF5bG9hZCA9IHsgdGV4dDogJ0RyaWZ0IERldGVjdGlvbiAoJHtzdGFja30pIC0gTm8gcmVzdWx0cyBmb3VuZCcsIGJsb2NrczogW2AsXG4gICAgYCAgICB7IHR5cGU6ICdzZWN0aW9uJywgdGV4dDogeyB0eXBlOiAnbXJrZHduJywgdGV4dDogJypEcmlmdCBEZXRlY3Rpb24gKCR7c3RhY2t9KSonIH0gfSxgLFxuICAgIFwiICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiAnTm8gcmVzdWx0cyBmaWxlIGZvdW5kLiBUaGUgZGV0ZWN0aW9uIHN0ZXAgbWF5IGhhdmUgYmVlbiBza2lwcGVkLicgfSB9XCIsXG4gICAgJyAgXSB9OycsXG4gICAgJyAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOycsXG4gICAgJ30nLFxuICAgIFwiY29uc3QgcmVzdWx0cyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHJlc3VsdHNGaWxlLCAndXRmOCcpKTtcIixcbiAgICBcImNvbnN0IGRyaWZ0ZWQgPSByZXN1bHRzLmZpbHRlcihyID0+IHIuZHJpZnRTdGF0dXMgPT09ICdEUklGVEVEJyk7XCIsXG4gICAgJ2NvbnN0IGVycm9ycyA9IHJlc3VsdHMuZmlsdGVyKHIgPT4gci5lcnJvcik7JyxcbiAgICBgY29uc3QgaGVhZGVyID0gJypEcmlmdCBEZXRlY3Rpb24gKCR7c3RhY2t9KSog4oCUIFJlZ2lvbjogJHtyZWdpb259JztgLFxuICAgICdjb25zdCBzdW1tYXJ5ID0gXCJUb3RhbCBzdGFja3M6IFwiICsgcmVzdWx0cy5sZW5ndGggKyBcIiB8IERyaWZ0ZWQ6IFwiICsgZHJpZnRlZC5sZW5ndGggKyBcIiB8IEVycm9yczogXCIgKyBlcnJvcnMubGVuZ3RoOycsXG4gICAgJ2NvbnN0IGxpbmVzQXJyOiBzdHJpbmdbXSA9IFtdOycsXG4gICAgJ2ZvciAoY29uc3QgcyBvZiBkcmlmdGVkKSB7JyxcbiAgICAnICBjb25zdCBjb3VudCA9IChzLmRyaWZ0ZWRSZXNvdXJjZXMgfHwgW10pLmxlbmd0aDsnLFxuICAgIFwiICBsaW5lc0Fyci5wdXNoKCfigKIgJyArIHMuc3RhY2tOYW1lICsgJyDigJQgJyArIGNvdW50ICsgJyByZXNvdXJjZShzKSBkcmlmdGVkJyk7XCIsXG4gICAgJ30nLFxuICAgICdwYXlsb2FkID0geycsXG4gICAgYCAgdGV4dDogJ0RyaWZ0IERldGVjdGlvbiAoJHtzdGFja30pJyxgLFxuICAgICcgIGJsb2NrczogWycsXG4gICAgXCIgICAgeyB0eXBlOiAnc2VjdGlvbicsIHRleHQ6IHsgdHlwZTogJ21ya2R3bicsIHRleHQ6IGhlYWRlciB9IH0sXCIsXG4gICAgXCIgICAgeyB0eXBlOiAnY29udGV4dCcsIGVsZW1lbnRzOiBbeyB0eXBlOiAnbXJrZHduJywgdGV4dDogc3VtbWFyeSB9XSB9LFwiLFxuICAgICcgICAgLi4uKGRyaWZ0ZWQubGVuZ3RoID4gMCA/IFsnLFxuICAgIFwiICAgICAgeyB0eXBlOiAnZGl2aWRlcicgfSxcIixcbiAgICBcIiAgICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiAnKkRyaWZ0ZWQgU3RhY2tzOipcXFxcbicgKyBsaW5lc0Fyci5qb2luKCdcXFxcbicpIH0gfVwiLFxuICAgICcgICAgXSA6IFsnLFxuICAgIFwiICAgICAgeyB0eXBlOiAnZGl2aWRlcicgfSxcIixcbiAgICBcIiAgICAgIHsgdHlwZTogJ3NlY3Rpb24nLCB0ZXh0OiB7IHR5cGU6ICdtcmtkd24nLCB0ZXh0OiAnTm8gZHJpZnQgZGV0ZWN0ZWQuJyB9IH1cIixcbiAgICAnICAgIF0pJyxcbiAgICAnICBdJyxcbiAgICAnfTsnLFxuICAgICdyZXR1cm4gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCk7JyxcbiAgXTtcbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuXG5mdW5jdGlvbiBzdW1tYXJ5U2NyaXB0KCk6IHN0cmluZyB7XG4gIHJldHVybiBbXG4gICAgJyMhL2Jpbi9iYXNoJyxcbiAgICAnc2V0IC1lJyxcbiAgICAnZWNobyBcIiMjIERyaWZ0IERldGVjdGlvbiBTdW1tYXJ5XCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcnLFxuICAgICd0b3RhbF9zdGFja3M9MCcsXG4gICAgJ3RvdGFsX2RyaWZ0ZWQ9MCcsXG4gICAgJ3RvdGFsX2Vycm9ycz0wJyxcbiAgICAnJyxcbiAgICAnc2hvcHQgLXMgbnVsbGdsb2InLFxuICAgICdmb3IgZmlsZSBpbiBkcmlmdC1yZXN1bHRzLSouanNvbiBkcmlmdC1yZXN1bHRzLyovZHJpZnQtcmVzdWx0cy0qLmpzb247IGRvJyxcbiAgICAnICBpZiBbWyAtZiBcIiRmaWxlXCIgXV07IHRoZW4nLFxuICAgICcgICAgc3RhY2s9JChiYXNlbmFtZSBcIiRmaWxlXCIgfCBzZWQgLUUgXFxcInMvXmRyaWZ0LXJlc3VsdHMtKFteLl0rKVxcXFwuanNvbiQvXFxcXDEvXFxcIiknLFxuICAgICcgICAgZWNobyBcIiMjIyBTdGFjazogJHN0YWNrXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgICAganEgLXIgXFwnJyArXG4gICAgICAnLiBhcyAkcmVzdWx0cyB8XFxuJyArXG4gICAgICAnXCItIFRvdGFsIHN0YWNrczogXCIgKyAoJHJlc3VsdHMgfCBsZW5ndGggfCB0b3N0cmluZykgKyBcIlxcXFxuXCIgK1xcbicgK1xuICAgICAgJ1wiLSBEcmlmdGVkOiBcIiArIChbLltdIHwgc2VsZWN0KC5kcmlmdFN0YXR1cyA9PSBcIkRSSUZURURcIildIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICdcIi0gRXJyb3JzOiBcIiArIChbLltdIHwgc2VsZWN0KC5lcnJvcildIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICcoWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXCJEUklGVEVEXCIpXSB8IGlmIGxlbmd0aCA+IDAgdGhlbiBcIlxcXFxuKipEcmlmdGVkIHN0YWNrczoqKlxcXFxuXCIgKyAobWFwKFwiICAtIFwiICsgLnN0YWNrTmFtZSArIFwiIChcIiArICgoLmRyaWZ0ZWRSZXNvdXJjZXMgLy8gW10pIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCIgcmVzb3VyY2VzKVwiKSB8IGpvaW4oXCJcXFxcblwiKSkgZWxzZSBcIlwiIGVuZClcXG4nICtcbiAgICAnXFwnJyArXG4gICAgJyBcIiRmaWxlXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgICAgZWNobyBcIlwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIHRvdGFsX3N0YWNrcz0kKCh0b3RhbF9zdGFja3MgKyAkKGpxIFxcXCJsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgICAgdG90YWxfZHJpZnRlZD0kKCh0b3RhbF9kcmlmdGVkICsgJChqcSBcXFwiWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXFxcXFxcXCJEUklGVEVEXFxcXFxcXCIpXSB8IGxlbmd0aFxcXCIgXFxcIiRmaWxlXFxcIikpKScsXG4gICAgJyAgICB0b3RhbF9lcnJvcnM9JCgodG90YWxfZXJyb3JzICsgJChqcSBcXFwiWy5bXSB8IHNlbGVjdCguZXJyb3IpXSB8IGxlbmd0aFxcXCIgXFxcIiRmaWxlXFxcIikpKScsXG4gICAgJyAgZmknLFxuICAgICdkb25lJyxcbiAgICAnJyxcbiAgICAnZWNobyBcIiMjIyBPdmVyYWxsIFN1bW1hcnlcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2VjaG8gXCItIFRvdGFsIHN0YWNrcyBjaGVja2VkOiAkdG90YWxfc3RhY2tzXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBkcmlmdGVkIHN0YWNrczogJHRvdGFsX2RyaWZ0ZWRcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2VjaG8gXCItIFRvdGFsIGVycm9yczogJHRvdGFsX2Vycm9yc1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnJyxcbiAgICAnaWYgW1sgJHRvdGFsX2RyaWZ0ZWQgLWd0IDAgXV07IHRoZW4nLFxuICAgICcgIGVjaG8gXCJcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJyAgZWNobyBcIuKaoO+4jyAqKkFjdGlvbiByZXF1aXJlZDoqKiBEcmlmdCBkZXRlY3RlZCBpbiAkdG90YWxfZHJpZnRlZCBzdGFja3NcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2ZpJyxcbiAgXS5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gdG9LZWJhYkNhc2Uoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHMucmVwbGFjZSgvW15hLXpBLVowLTldKy9nLCAnLScpLnJlcGxhY2UoL14tK3wtKyQvZywgJycpLnRvTG93ZXJDYXNlKCk7XG59XG5cblxuZnVuY3Rpb24gdG9HaXRodWJKb2JJZChzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBHaXRIdWIgam9iX2lkIG11c3Qgc3RhcnQgd2l0aCBhIGxldHRlciBvciB1bmRlcnNjb3JlIGFuZCBjb250YWluIG9ubHkgQS1aYS16MC05LCAnLScsICdfJ1xuICAvLyAxKSBSZXBsYWNlIGFueSBkaXNhbGxvd2VkIGNoYXJzIHdpdGggJy0nXG4gIGxldCBvdXQgPSBzLnJlcGxhY2UoL1teQS1aYS16MC05Xy1dKy9nLCAnLScpO1xuICAvLyAyKSBDb2xsYXBzZSBjb25zZWN1dGl2ZSBkYXNoZXNcbiAgb3V0ID0gb3V0LnJlcGxhY2UoLy0rL2csICctJyk7XG4gIC8vIDMpIFRyaW0gbGVhZGluZy90cmFpbGluZyBkYXNoZXMgKHVuZGVyc2NvcmVzIGFyZSBhbGxvd2VkIGF0IHN0YXJ0KVxuICBvdXQgPSBvdXQucmVwbGFjZSgvXi0rfC0rJC9nLCAnJyk7XG4gIC8vIDQpIExvd2VyY2FzZSBmb3IgY29uc2lzdGVuY3kgKG5vdCByZXF1aXJlZCBieSBHaXRIdWIgYnV0IGtlZXBzIHRoaW5ncyBzdGFibGUpXG4gIG91dCA9IG91dC50b0xvd2VyQ2FzZSgpO1xuICAvLyA1KSBFbnN1cmUgaXQgc3RhcnRzIHdpdGggYSBsZXR0ZXIgb3IgdW5kZXJzY29yZVxuICBpZiAoIW91dCB8fCAhL15bYS16X10vaS50ZXN0KG91dCkpIHtcbiAgICBvdXQgPSBgcy0ke291dH1gO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=
|
|
279
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2RrRHJpZnREZXRlY3Rpb25Xb3JrZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9DZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsOENBQTJEO0FBQzNELHVFQUFrRTtBQUNsRSxpRkFBMkU7QUFFM0UsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSw2QkFBNkIsR0FBRyxJQUFJLENBQUM7QUFDM0MsTUFBTSxrQ0FBa0MsR0FBRyxJQUFJLENBQUM7QUFDaEQsTUFBTSxvQ0FBb0MsR0FBRyxJQUFJLENBQUM7QUFDbEQsTUFBTSxnQ0FBZ0MsR0FBRyxJQUFJLENBQUM7QUFnRDlDLE1BQWEseUJBQXlCO0lBR3BDLFlBQVksS0FBcUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxpQkFBaUIsQ0FBQztRQUNyRCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQzVDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDO1FBQ2hELE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDOUIsTUFBTSxnQkFBZ0IsR0FBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksMkNBQTJDLENBQUM7UUFFOUYsa0VBQWtFO1FBQ2xFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM3QyxJQUFJLG9EQUF1QixDQUFDO2dCQUMxQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87Z0JBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7YUFDN0IsQ0FBQyxDQUFDO1lBQ0gseUJBQXlCLENBQUMsYUFBYSxH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dUU7UUFDdkUsOERBQThEO1FBQzlELEVBQUU7UUFDRixxQ0FBcUM7UUFDckMsbUNBQW1DO1FBQ25DLGtHQUFrRztRQUNsRyxJQUFJO0tBQ0wsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDZixDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsQ0FBUztJQUM1QixPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUNoRixDQUFDO0FBR0QsU0FBUyxhQUFhLENBQUMsQ0FBUztJQUM5Qiw0RkFBNEY7SUFDNUYsMkNBQTJDO0lBQzNDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDN0MsaUNBQWlDO0lBQ2pDLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5QixxRUFBcUU7SUFDckUsR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLGdGQUFnRjtJQUNoRixHQUFHLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3hCLGtEQUFrRDtJQUNsRCxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2xDLEdBQUcsR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBHaXRIdWIsIEdpdGh1YldvcmtmbG93IH0gZnJvbSAncHJvamVuL2xpYi9naXRodWInO1xuaW1wb3J0IHsgSm9iUGVybWlzc2lvbiB9IGZyb20gJ3Byb2plbi9saWIvZ2l0aHViL3dvcmtmbG93cy1tb2RlbCc7XG5pbXBvcnQgeyBDZGtEcmlmdERldGVjdGlvblNjcmlwdCB9IGZyb20gJy4vYmluL2Nkay1kcmlmdC1kZXRlY3Rpb24tc2NyaXB0JztcblxuY29uc3QgZ2l0aHViQWN0aW9uc0F3c0NyZWRlbnRpYWxzVmVyc2lvbiA9ICd2NSc7XG5jb25zdCBnaXRodWJBY3Rpb25zQ2hlY2tvdXRWZXJzaW9uID0gJ3Y1JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNTZXR1cE5vZGVWZXJzaW9uID0gJ3Y1JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNVcGxvYWRBcnRpZmFjdFZlcnNpb24gPSAndjQnO1xuY29uc3QgZ2l0aHViQWN0aW9uc0Rvd25sb2FkQXJ0aWZhY3RWZXJzaW9uID0gJ3Y1JztcbmNvbnN0IGdpdGh1YkFjdGlvbnNHaXRodWJTY3JpcHRWZXJzaW9uID0gJ3Y4JztcblxuZXhwb3J0IGludGVyZmFjZSBTdGFjayB7XG4gIHJlYWRvbmx5IHN0YWNrTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBkcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbjogc3RyaW5nO1xuICByZWFkb25seSBkcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZUFybjogc3RyaW5nO1xuICByZWFkb25seSBmYWlsT25EcmlmdD86IGJvb2xlYW47IC8vIGlmIHRydWUsIGZhaWwgam9iIHdoZW4gZHJpZnQgZGV0ZWN0ZWQgKGRlZmF1bHQgdHJ1ZSlcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93UHJvcHMge1xuICByZWFkb25seSBzY3JpcHRPdXRwdXRQYXRoPzogc3RyaW5nO1xuICByZWFkb25seSBwcm9qZWN0OiBhbnk7IC8vIGF2b2lkIGV4cG9ydGluZyBwcm9qZW4gdHlwZXMgaW4gcHVibGljIEFQSVxuICByZWFkb25seSB3b3JrZmxvd05hbWU/OiBzdHJpbmc7IC8vIHdvcmtmbG93IHdvcmtmbG93TmFtZSAoYWxzbyB1c2VkIHRvIGRlcml2ZSBmaWxlIHdvcmtmbG93TmFtZSlcbiAgcmVhZG9ubHkgc2NoZWR1bGU/OiBzdHJpbmc7IC8vIGNyb24gZXhwcmVzc2lvbiwgZS5nLiAnMCAwICogKiAqJ1xuICByZWFkb25seSBjcmVhdGVJc3N1ZXM/OiBib29sZWFuOyAvLyBjcmVhdGUvdXBkYXRlIGlzc3VlIHdoZW4gZHJpZnQgZGV0ZWN0ZWQgb24gc2NoZWR1bGUgKGRlZmF1bHQgdHJ1ZSlcbiAgcmVhZG9ubHkgb2lkY1JvbGVBcm46IHN0cmluZzsgLy8gZGVmYXVsdCBPSURDIHJvbGUgQVJOIHRvIGFzc3VtZSBmb3IgYWxsIHN0YWNrc1xuICByZWFkb25seSBvaWRjUmVnaW9uOiBzdHJpbmc7IC8vIGRlZmF1bHQgT0lEQyByZWdpb24gdG8gYXNzdW1lIGZvciBhbGwgc3RhY2tzXG4gIHJlYWRvbmx5IHN0YWNrczogU3RhY2tbXTtcbiAgcmVhZG9ubHkgbm9kZVZlcnNpb24/OiBzdHJpbmc7IC8vIGUuZy4sICcyNC54J1xuICAvKipcbiAgICogT3B0aW9uYWwgaG9vayB0byBhcHBlbmQgYWRkaXRpb25hbCBHaXRIdWIgQWN0aW9ucyBzdGVwcyBhZnRlciBkcmlmdCBkZXRlY3Rpb24gcGVyIHN0YWNrLlxuICAgKiBZb3UgY2FuIHN1cHBseSBhIHN0YXRpYyBhcnJheSBvZiBzdGVwcywgb3IgYSBmYWN0b3J5IHRoYXQgcmVjZWl2ZXMgY29udGV4dCBhbmQgcmV0dXJucyBzdGVwcy5cbiAgICovXG4gIC8qKlxuICAgKiBPcHRpb25hbCBhZGRpdGlvbmFsIEdpdEh1YiBBY3Rpb24gc3RlcHMgdG8gcnVuIGFmdGVyIGRyaWZ0IGRldGVjdGlvbiBmb3IgZWFjaCBzdGFjay5cbiAgICogVGhlc2Ugc3RlcHMgcnVuIGFmdGVyIHJlc3VsdHMgYXJlIHVwbG9hZGVkIGZvciBlYWNoIHN0YWNrLiBZb3UgY2FuIGluY2x1ZGVcbiAgICogYW55IG5vdGlmaWNhdGlvbnMgeW91IGxpa2UgKGUuZy4sIFNsYWNrKS4gUHJvdmlkZSBleHBsaWNpdCBpbnB1dHMgKGUuZy4sIHBheWxvYWQvbWFya2Rvd24pXG4gICAqIGRpcmVjdGx5IGluIHlvdXIgc3RlcCB3aXRob3V0IHJlbHlpbmcgb24gYSBwcmUtZ2VuZXJhdGVkIHBheWxvYWQuXG4gICAqL1xuICAvLyBOT1RFOiBqc2lpIGRvZXMgbm90IHN1cHBvcnQgZnVuY3Rpb24gdHlwZXMgaW4gcHVibGljIEFQSXM7IHVzZSAnYW55JyBoZXJlIGFuZCBhY2NlcHQgZWl0aGVyOlxuICAvLyAtIEFuIGFycmF5IG9mIEdpdEh1YiBzdGVwcywgb3JcbiAgLy8gLSBBIGZ1bmN0aW9uIChjdHg6IHsgc3RhY2s6IHN0cmluZyB9KSA9PiBHaXRIdWJTdGVwW11cbiAgLy8gVGhlIGNvbnN0cnVjdG9yIGhhbmRsZXMgYm90aCBhdCBydW50aW1lLlxuICByZWFkb25seSBwb3N0R2l0SHViU3RlcHM/OiBhbnk7XG59XG5cbnR5cGUgR2l0SHViU3RlcCA9IHtcbiAgbmFtZT86IHN0cmluZztcbiAgaWQ/OiBzdHJpbmc7XG4gIGlmPzogc3RyaW5nO1xuICB1c2VzPzogc3RyaW5nO1xuICBydW4/OiBzdHJpbmc7XG4gIHdpdGg/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBjb250aW51ZU9uRXJyb3I/OiBib29sZWFuO1xuICBzaGVsbD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjbGFzcyBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93IHtcbiAgcHJpdmF0ZSBzdGF0aWMgc2NyaXB0Q3JlYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBDZGtEcmlmdERldGVjdGlvbldvcmtmbG93UHJvcHMpIHtcbiAgICBjb25zdCBuYW1lID0gcHJvcHMud29ya2Zsb3dOYW1lID8/ICdkcmlmdC1kZXRlY3Rpb24nO1xuICAgIGNvbnN0IGZpbGVOYW1lID0gdG9LZWJhYkNhc2UobmFtZSkgKyAnLnltbCc7XG4gICAgY29uc3Qgbm9kZVZlcnNpb24gPSBwcm9wcy5ub2RlVmVyc2lvbiA/PyAnMjQueCc7XG4gICAgY29uc3QgY3JlYXRlSXNzdWVzID0gcHJvcHMuY3JlYXRlSXNzdWVzID8/IHRydWU7XG4gICAgY29uc3QgcHJvamVjdCA9IHByb3BzLnByb2plY3Q7XG4gICAgY29uc3Qgc2NyaXB0T3V0cHV0UGF0aD0gcHJvcHMuc2NyaXB0T3V0cHV0UGF0aCA/PyAnLmdpdGh1Yi93b3JrZmxvd3Mvc2NyaXB0cy9kZXRlY3QtZHJpZnQudHMnO1xuXG4gICAgLy8gT25seSBjcmVhdGUgdGhlIGRyaWZ0IGRldGVjdGlvbiBzY3JpcHQgb25jZSB0byBhdm9pZCBjb2xsaXNpb25zXG4gICAgaWYgKCFDZGtEcmlmdERldGVjdGlvbldvcmtmbG93LnNjcmlwdENyZWF0ZWQpIHtcbiAgICAgIG5ldyBDZGtEcmlmdERldGVjdGlvblNjcmlwdCh7XG4gICAgICAgIHByb2plY3Q6IHByb3BzLnByb2plY3QsXG4gICAgICAgIG91dHB1dFBhdGg6IHNjcmlwdE91dHB1dFBhdGgsXG4gICAgICB9KTtcbiAgICAgIENka0RyaWZ0RGV0ZWN0aW9uV29ya2Zsb3cuc2NyaXB0Q3JlYXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgZ2ggPSAocHJvamVjdCBhcyBhbnkpLmdpdGh1YiA/PyBuZXcgR2l0SHViKHByb2plY3QpO1xuICAgIGNvbnN0IHdvcmtmbG93ID0gbmV3IEdpdGh1YldvcmtmbG93KGdoLCBuYW1lLCB7IGZpbGVOYW1lIH0pO1xuXG4gICAgLy8gdHJpZ2dlcnM6IHNjaGVkdWxlICsgbWFudWFsIGRpc3BhdGNoIHdpdGggc3RhY2sgY2hvaWNlXG4gICAgY29uc3Qgc3RhY2tDaG9pY2VzID0gWydhbGwnLCAuLi5wcm9wcy5zdGFja3MubWFwKChzKSA9PiBzLnN0YWNrTmFtZSldO1xuICAgIHdvcmtmbG93Lm9uKHtcbiAgICAgIHNjaGVkdWxlOiBwcm9wcy5zY2hlZHVsZSA/IFt7IGNyb246IHByb3BzLnNjaGVkdWxlIH1dIDogdW5kZWZpbmVkLFxuICAgICAgd29ya2Zsb3dEaXNwYXRjaDoge1xuICAgICAgICBpbnB1dHM6IHtcbiAgICAgICAgICBzdGFjazoge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IFwiU3RhY2sgdG8gY2hlY2sgZm9yIGRyaWZ0ICgnYWxsJyB0byBydW4gZXZlcnkgc3RhY2spXCIsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICB0eXBlOiAnY2hvaWNlJyxcbiAgICAgICAgICAgIG9wdGlvbnM6IHN0YWNrQ2hvaWNlcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIE9uZSBqb2IgcGVyIHN0YWNrXG4gICAgY29uc3Qgam9iczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBzdGFjayBvZiBwcm9wcy5zdGFja3MpIHtcbiAgICAgIGNvbnN0IHNhbml0aXplZFN0YWNrTmFtZSA9IHRvS2ViYWJDYXNlKHRvR2l0aHViSm9iSWQoc3RhY2suc3RhY2tOYW1lKSk7XG4gICAgICBjb25zdCBvcmlnaW5hbFN0YWNrTmFtZSA9IHN0YWNrLnN0YWNrTmFtZTtcbiAgICAgIGNvbnN0IGpvYklkID0gYGRyaWZ0LSR7c2FuaXRpemVkU3RhY2tOYW1lfWA7XG4gICAgICBjb25zdCByZXN1bHRzRmlsZSA9IGBkcmlmdC1yZXN1bHRzLSR7c2FuaXRpemVkU3RhY2tOYW1lfS5qc29uYDtcbiAgICAgIGNvbnN0IGlubmVyQ29uZCA9IFwiZ2l0aHViLmV2ZW50X25hbWUgPT0gJ3NjaGVkdWxlJyB8fCAhZ2l0aHViLmV2ZW50LmlucHV0cy5zdGFjayB8fCBnaXRodWIuZXZlbnQuaW5wdXRzLnN0YWNrID09ICdhbGwnIHx8IGdpdGh1Yi5ldmVudC5pbnB1dHMuc3RhY2sgPT0gJ1wiICsgc2FuaXRpemVkU3RhY2tOYW1lICsgXCInIHx8IGdpdGh1Yi5ldmVudC5pbnB1dHMuc3RhY2sgPT0gJ1wiICsgb3JpZ2luYWxTdGFja05hbWUgKyBcIidcIjtcbiAgICAgIGNvbnN0IGNvbmRFeHByID0gJyR7eyAnICsgaW5uZXJDb25kICsgJyB9fSc7XG4gICAgICBjb25zdCBub3RDb25kRXhwciA9ICcke3sgISgnICsgaW5uZXJDb25kICsgJykgfX0nO1xuXG4gICAgICBjb25zdCByYXdQb3N0ID0gcHJvcHMucG9zdEdpdEh1YlN0ZXBzO1xuICAgICAgY29uc3QgcG9zdFN0ZXBzOiBHaXRIdWJTdGVwW10gPSB0eXBlb2YgcmF3UG9zdCA9PT0gJ2Z1bmN0aW9uJyA/IChyYXdQb3N0IGFzIChjdHg6IHsgc3RhY2s6IHN0cmluZyB9KSA9PiBHaXRIdWJTdGVwW10pKHsgc3RhY2s6IHNhbml0aXplZFN0YWNrTmFtZSB9KSA6IChyYXdQb3N0ID8/IFtdKTtcblxuICAgICAgam9ic1tqb2JJZF0gPSB7XG4gICAgICAgIG5hbWU6IGBEcmlmdCBEZXRlY3Rpb24gLSAke3Nhbml0aXplZFN0YWNrTmFtZX1gLFxuICAgICAgICBydW5zT246IFsndWJ1bnR1LWxhdGVzdCddLFxuICAgICAgICBwZXJtaXNzaW9uczoge1xuICAgICAgICAgIGNvbnRlbnRzOiBKb2JQZXJtaXNzaW9uLlJFQUQsXG4gICAgICAgICAgaWRUb2tlbjogSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgICAgICBpc3N1ZXM6IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgIH0sXG4gICAgICAgIGVudjoge1xuICAgICAgICAgIEFXU19ERUZBVUxUX1JFR0lPTjogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sXG4gICAgICAgICAgQVdTX1JFR0lPTjogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sXG4gICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgU1RBQ0tfSUQ6IHNhbml0aXplZFN0YWNrTmFtZSxcbiAgICAgICAgICBTVEFDS19OQU1FOiBzdGFjay5zdGFja05hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIC8vIE5vIGpvYi1sZXZlbCBjb25kaXRpb247IHdlIGdhdGUgc3RlcHMgc28gdGhlIGpvYiBhbHdheXMgY29tcGxldGVzIGFuZCBzdW1tYXJ5IGNhbiBydW5cbiAgICAgICAgc3RlcHM6IFtcbiAgICAgICAgICB7IG5hbWU6ICdTa2lwIChzdGFjayBub3Qgc2VsZWN0ZWQpJywgaWY6IG5vdENvbmRFeHByLCBydW46ICdlY2hvIFwiU3RhY2sgbm90IHNlbGVjdGVkOyBza2lwcGluZyBkcmlmdCBkZXRlY3Rpb24gZm9yIHRoaXMgam9iLlwiJyB9LFxuICAgICAgICAgIHsgbmFtZTogJ0NoZWNrb3V0JywgaWY6IGNvbmRFeHByLCB1c2VzOiBgYWN0aW9ucy9jaGVja291dEAke2dpdGh1YkFjdGlvbnNDaGVja291dFZlcnNpb259YCB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdTZXR1cCBOb2RlLmpzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3NldHVwLW5vZGVAJHtnaXRodWJBY3Rpb25zU2V0dXBOb2RlVmVyc2lvbn1gLFxuICAgICAgICAgICAgd2l0aDogeyAnbm9kZS12ZXJzaW9uJzogbm9kZVZlcnNpb24gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbmFtZTogJ0luc3RhbGwgZGVwZW5kZW5jaWVzJywgaWY6IGNvbmRFeHByLCBydW46ICd5YXJuIGluc3RhbGwgLS1mcm96ZW4tbG9ja2ZpbGUgfHwgbnBtIGNpJywgZW52OiB7IEdJVEhVQl9UT0tFTjogJyR7eyBzZWNyZXRzLkdJVEhVQl9UT0tFTiB9fScgfSB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdBV1MgQ3JlZGVudGlhbHMnLFxuICAgICAgICAgICAgaWY6IGNvbmRFeHByLFxuICAgICAgICAgICAgaWQ6ICdjcmVkcycsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogcHJvcHMub2lkY1JvbGVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLXNlc3Npb24tbmFtZSc6ICdHaXRIdWJBY3Rpb24nLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHByb3BzLm9pZGNSZWdpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0Fzc3VtZSBEcmlmdCBEZXRlY3Rpb24gUm9sZScsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICB1c2VzOiBgYXdzLWFjdGlvbnMvY29uZmlndXJlLWF3cy1jcmVkZW50aWFsc0Ake2dpdGh1YkFjdGlvbnNBd3NDcmVkZW50aWFsc1ZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHtcbiAgICAgICAgICAgICAgJ3JvbGUtdG8tYXNzdW1lJzogc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVBcm4sXG4gICAgICAgICAgICAgICdyb2xlLWNoYWluaW5nJzogdHJ1ZSxcbiAgICAgICAgICAgICAgJ3JvbGUtc2tpcC1zZXNzaW9uLXRhZ2dpbmcnOiB0cnVlLFxuICAgICAgICAgICAgICAnYXdzLXJlZ2lvbic6IHN0YWNrLmRyaWZ0RGV0ZWN0aW9uUm9sZVRvQXNzdW1lUmVnaW9uLFxuICAgICAgICAgICAgICAnYXdzLWFjY2Vzcy1rZXktaWQnOiAnJHt7IHN0ZXBzLmNyZWRzLm91dHB1dHMuYXdzLWFjY2Vzcy1rZXktaWQgfX0nLFxuICAgICAgICAgICAgICAnYXdzLXNlY3JldC1hY2Nlc3Mta2V5JzogJyR7eyBzdGVwcy5jcmVkcy5vdXRwdXRzLmF3cy1zZWNyZXQtYWNjZXNzLWtleSB9fScsXG4gICAgICAgICAgICAgICdhd3Mtc2Vzc2lvbi10b2tlbic6ICcke3sgc3RlcHMuY3JlZHMub3V0cHV0cy5hd3Mtc2Vzc2lvbi10b2tlbiB9fScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ0RldGVjdCBkcmlmdCcsXG4gICAgICAgICAgICBpZjogY29uZEV4cHIsXG4gICAgICAgICAgICBpZDogJ2RyaWZ0JyxcbiAgICAgICAgICAgIGNvbnRpbnVlT25FcnJvcjogdHJ1ZSwgLy8gYWxsb3cgYXJ0aWZhY3QgdXBsb2FkIGFuZCBpc3N1ZSBjcmVhdGlvbiBldmVuIHdoZW4gZHJpZnQgaXMgZGV0ZWN0ZWRcbiAgICAgICAgICAgIHJ1bjogW1xuICAgICAgICAgICAgICAnc2V0IC1lJyxcbiAgICAgICAgICAgICAgLy8gVXNlIHRoZSBidW5kbGVkIHNjcmlwdCBmcm9tIHRoaXMgcGFja2FnZVxuICAgICAgICAgICAgICAnbm9kZSAuL25vZGVfbW9kdWxlcy9AampyYXdsaW5zL2Nkay1kaWZmLXByLWdpdGh1Yi1hY3Rpb24vbGliL2Jpbi9kZXRlY3QtZHJpZnQuanMnLFxuICAgICAgICAgICAgICAnaWYgWyAtZiBcIiREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCIgXTsgdGhlbiBlY2hvIFwiUmVzdWx0cyBmaWxlIGNyZWF0ZWQ6ICREUklGVF9ERVRFQ1RJT05fT1VUUFVUXCI7IGZpJyxcbiAgICAgICAgICAgICAgLy8gRXhwb3NlIHVzZWZ1bCBvdXRwdXRzIGZvciBkb3duc3RyZWFtIHN0ZXBzXG4gICAgICAgICAgICAgIFwiU1RBQ0tfQVJOPSQoYXdzIGNsb3VkZm9ybWF0aW9uIGRlc2NyaWJlLXN0YWNrcyAtLXN0YWNrLW5hbWUgXFxcIiRTVEFDS19OQU1FXFxcIiAtLXF1ZXJ5ICdTdGFja3NbMF0uU3RhY2tJZCcgLS1vdXRwdXQgdGV4dCAyPi9kZXYvbnVsbCB8fCB0cnVlKVwiLFxuICAgICAgICAgICAgICAnZWNobyBcInN0YWNrLWFybj0kU1RBQ0tfQVJOXCIgPj4gXCIkR0lUSFVCX09VVFBVVFwiJyxcbiAgICAgICAgICAgIF0uam9pbignXFxuJyksXG4gICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgU1RBQ0tfTkFNRTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICAgICAgICBBV1NfUkVHSU9OOiBzdGFjay5kcmlmdERldGVjdGlvblJvbGVUb0Fzc3VtZVJlZ2lvbixcbiAgICAgICAgICAgICAgRFJJRlRfREVURUNUSU9OX09VVFBVVDogcmVzdWx0c0ZpbGUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ1VwbG9hZCByZXN1bHRzJyxcbiAgICAgICAgICAgIGlmOiBjb25kRXhwcixcbiAgICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL3VwbG9hZC1hcnRpZmFjdEAke2dpdGh1YkFjdGlvbnNVcGxvYWRBcnRpZmFjdFZlcnNpb259YCxcbiAgICAgICAgICAgIHdpdGg6IHsgJ25hbWUnOiBgZHJpZnQtcmVzdWx0cy0ke3Nhbml0aXplZFN0YWNrTmFtZX1gLCAncGF0aCc6IHJlc3VsdHNGaWxlLCAnaWYtbm8tZmlsZXMtZm91bmQnOiAnaWdub3JlJyB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4uKFxuICAgICAgICAgICAgY3JlYXRlSXNzdWVzXG4gICAgICAgICAgICAgID8gW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG5hbWU6ICdDcmVhdGUgSXNzdWUgb24gRHJpZnQnLFxuICAgICAgICAgICAgICAgICAgaWY6IFwiYWx3YXlzKCkgJiYgc3RlcHMuZHJpZnQub3V0Y29tZSA9PSAnZmFpbHVyZSdcIixcbiAgICAgICAgICAgICAgICAgIGlkOiAnaXNzdWUnLFxuICAgICAgICAgICAgICAgICAgdXNlczogYGFjdGlvbnMvZ2l0aHViLXNjcmlwdEAke2dpdGh1YkFjdGlvbnNHaXRodWJTY3JpcHRWZXJzaW9ufWAsXG4gICAgICAgICAgICAgICAgICB3aXRoOiB7ICdyZXN1bHQtZW5jb2RpbmcnOiAnc3RyaW5nJywgJ3NjcmlwdCc6IGlzc3VlU2NyaXB0KHNhbml0aXplZFN0YWNrTmFtZSwgc3RhY2suZHJpZnREZXRlY3Rpb25Sb2xlVG9Bc3N1bWVSZWdpb24sIHJlc3VsdHNGaWxlKSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgOiBbXVxuICAgICAgICAgICksXG4gICAgICAgICAgLi4ucG9zdFN0ZXBzLm1hcCgoc3RlcCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgczogYW55ID0geyAuLi4oc3RlcCBhcyBhbnkpIH07XG4gICAgICAgICAgICAvLyBCeSBkZWZhdWx0LCBvbmx5IHJ1biBleHRyYSBub3RpZmljYXRpb24gc3RlcHMgd2hlbiBkcmlmdCBvY2N1cnNcbiAgICAgICAgICAgIHMuaWYgPSBzLmlmID8/IFwiYWx3YXlzKCkgJiYgc3RlcHMuZHJpZnQub3V0Y29tZSA9PSAnZmFpbHVyZSdcIjtcbiAgICAgICAgICAgIHJldHVybiBzO1xuICAgICAgICAgIH0pLFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBzdW1tYXJ5IGFnZ3JlZ2F0b3Igam9iXG4gICAgam9ic1snZHJpZnQtc3VtbWFyeSddID0ge1xuICAgICAgbmFtZTogJ0RyaWZ0IERldGVjdGlvbiBTdW1tYXJ5JyxcbiAgICAgIG5lZWRzOiBPYmplY3Qua2V5cyhqb2JzKS5maWx0ZXIoKGopID0+IGouc3RhcnRzV2l0aCgnZHJpZnQtJykgJiYgaiAhPT0gJ2RyaWZ0LXN1bW1hcnknKSxcbiAgICAgIHJ1bnNPbjogWyd1YnVudHUtbGF0ZXN0J10sXG4gICAgICBwZXJtaXNzaW9uczogeyBjb250ZW50czogSm9iUGVybWlzc2lvbi5SRUFEIH0sXG4gICAgICBzdGVwczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ0Rvd25sb2FkIGFsbCBhcnRpZmFjdHMnLFxuICAgICAgICAgIHVzZXM6IGBhY3Rpb25zL2Rvd25sb2FkLWFydGlmYWN0QCR7Z2l0aHViQWN0aW9uc0Rvd25sb2FkQXJ0aWZhY3RWZXJzaW9ufWAsXG4gICAgICAgICAgd2l0aDogeyBwYXRoOiAnZHJpZnQtcmVzdWx0cycgfSxcbiAgICAgICAgfSxcbiAgICAgICAgeyBuYW1lOiAnR2VuZXJhdGUgc3VtbWFyeScsIHNoZWxsOiAnYmFzaCcsIHJ1bjogc3VtbWFyeVNjcmlwdCgpIH0sXG4gICAgICBdLFxuICAgIH07XG5cbiAgICB3b3JrZmxvdy5hZGRKb2JzKGpvYnMpO1xuICB9XG59XG5cblxuZnVuY3Rpb24gaXNzdWVTY3JpcHQoc3RhY2s6IHN0cmluZywgcmVnaW9uOiBzdHJpbmcsIHJlc3VsdHNGaWxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBDb25zdHJ1Y3QgYSBwbGFpbiBKUyBzY3JpcHQgc3RyaW5nIChubyB0ZW1wbGF0ZSBzdHJpbmcgbmVzdGluZyBtaXNoYXBzKVxuICBjb25zdCBsaW5lcyA9IFtcbiAgICBcImNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTtcIixcbiAgICBgY29uc3QgcmVzdWx0c0ZpbGUgPSAnJHtyZXN1bHRzRmlsZX0nO2AsXG4gICAgXCJpZiAoIWZzLmV4aXN0c1N5bmMocmVzdWx0c0ZpbGUpKSB7IGNvbnNvbGUubG9nKCdObyByZXN1bHRzIGZpbGUgZm91bmQnKTsgcmV0dXJuICdOT19SRVNVTFRTJzsgfVwiLFxuICAgIFwiY29uc3QgcmVzdWx0cyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHJlc3VsdHNGaWxlLCAndXRmOCcpKTtcIixcbiAgICBcImNvbnN0IGRyaWZ0ZWRTdGFja3MgPSByZXN1bHRzLmZpbHRlcihyID0+IHIuZHJpZnRTdGF0dXMgPT09ICdEUklGVEVEJyk7XCIsXG4gICAgXCJpZiAoZHJpZnRlZFN0YWNrcy5sZW5ndGggPT09IDApIHsgY29uc29sZS5sb2coJ05vIGRyaWZ0IGRldGVjdGVkJyk7IHJldHVybiAnTk9fRFJJRlQnOyB9XCIsXG4gICAgYGNvbnN0IHRpdGxlID0gJ0RyaWZ0IERldGVjdGVkIGluICR7c3RhY2t9JztgLFxuICAgIGBsZXQgYm9keSA9ICcjIyBEcmlmdCBEZXRlY3Rpb24gUmVwb3J0XFxcXG5cXFxcbicgKyAnKipTdGFjazoqKiAke3N0YWNrfVxcXFxuJyArICcqKlJlZ2lvbjoqKiAke3JlZ2lvbn1cXFxcbicgKyAnKipUaW1lOioqICcgKyBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgKyAnXFxcXG5cXFxcbic7YCxcbiAgICBcImJvZHkgKz0gJyMjIyBTdW1tYXJ5XFxcXG4nO1wiLFxuICAgIFwiYm9keSArPSAnLSBUb3RhbCBzdGFja3MgY2hlY2tlZDogJyArIHJlc3VsdHMubGVuZ3RoICsgJ1xcXFxuJztcIixcbiAgICBcImJvZHkgKz0gJy0gRHJpZnRlZCBzdGFja3M6ICcgKyBkcmlmdGVkU3RhY2tzLmxlbmd0aCArICdcXFxcblxcXFxuJztcIixcbiAgICBcImJvZHkgKz0gJyMjIyBEcmlmdGVkIFN0YWNrc1xcXFxuJztcIixcbiAgICAnZm9yIChjb25zdCBzIG9mIGRyaWZ0ZWRTdGFja3MpIHsnLFxuICAgICcgIGNvbnN0IHJlc291cmNlcyA9IHMuZHJpZnRlZFJlc291cmNlcyB8fCBbXTsnLFxuICAgIFwiICBib2R5ICs9ICcjIyMjICcgKyBzLnN0YWNrTmFtZSArICdcXFxcbic7XCIsXG4gICAgXCIgIGJvZHkgKz0gJy0gRHJpZnRlZCByZXNvdXJjZXM6ICcgKyByZXNvdXJjZXMubGVuZ3RoICsgJ1xcXFxuJztcIixcbiAgICBcIiAgZm9yIChjb25zdCByIG9mIHJlc291cmNlcykgeyBib2R5ICs9ICcgIC0gJyArIHIubG9naWNhbFJlc291cmNlSWQgKyAnICgnICsgci5yZXNvdXJjZVR5cGUgKyAnKVxcXFxuJzsgfVwiLFxuICAgIFwiICBib2R5ICs9ICdcXFxcbic7XCIsXG4gICAgJ30nLFxuICAgIFwiYm9keSArPSAnIyMjIEFjdGlvbiBSZXF1aXJlZFxcXFxuJyArICdQbGVhc2UgcmV2aWV3IHRoZSBkcmlmdGVkIHJlc291cmNlcyBhbmQgZWl0aGVyOlxcXFxuMS4gVXBkYXRlIHRoZSBpbmZyYXN0cnVjdHVyZSBjb2RlIHRvIG1hdGNoIHRoZSBhY3R1YWwgc3RhdGVcXFxcbjIuIFJlc3RvcmUgdGhlIHJlc291cmNlcyB0byBtYXRjaCB0aGUgZXhwZWN0ZWQgc3RhdGVcXFxcblxcXFxuJztcIixcbiAgICAnYm9keSArPSBgW1ZpZXcgd29ya2Zsb3cgcnVuXSgke2NvbnRleHQuc2VydmVyVXJsfS8ke2NvbnRleHQucmVwby5vd25lcn0vJHtjb250ZXh0LnJlcG8ucmVwb30vYWN0aW9ucy9ydW5zLyR7Y29udGV4dC5ydW5JZH0pYDsnLFxuICAgIC8vIExpc3Qgb3IgdXBkYXRlIGFuIGlzc3VlIHdpdGggbGFiZWxzXG4gICAgYGNvbnN0IGlzc3VlcyA9IGF3YWl0IGdpdGh1Yi5yZXN0Lmlzc3Vlcy5saXN0Rm9yUmVwbyh7IG93bmVyOiBjb250ZXh0LnJlcG8ub3duZXIsIHJlcG86IGNvbnRleHQucmVwby5yZXBvLCBzdGF0ZTogJ29wZW4nLCBsYWJlbHM6IFsnZHJpZnQtZGV0ZWN0aW9uJywgJyR7c3RhY2t9J10gfSk7YCxcbiAgICAnbGV0IGlzc3VlTnVtYmVyOycsXG4gICAgJ2lmIChpc3N1ZXMuZGF0YS5sZW5ndGggPT09IDApIHsnLFxuICAgIGAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCBnaXRodWIucmVzdC5pc3N1ZXMuY3JlYXRlKHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIHRpdGxlLCBib2R5LCBsYWJlbHM6IFsnZHJpZnQtZGV0ZWN0aW9uJywgJyR7c3RhY2t9J10gfSk7YCxcbiAgICAnICBpc3N1ZU51bWJlciA9IGNyZWF0ZWQuZGF0YS5udW1iZXI7JyxcbiAgICAnfSBlbHNlIHsnLFxuICAgICcgIGNvbnN0IGlzc3VlID0gaXNzdWVzLmRhdGFbMF07JyxcbiAgICAnICBpc3N1ZU51bWJlciA9IGlzc3VlLm51bWJlcjsnLFxuICAgICcgIGF3YWl0IGdpdGh1Yi5yZXN0Lmlzc3Vlcy5jcmVhdGVDb21tZW50KHsgb3duZXI6IGNvbnRleHQucmVwby5vd25lciwgcmVwbzogY29udGV4dC5yZXBvLnJlcG8sIGlzc3VlX251bWJlcjogaXNzdWUubnVtYmVyLCBib2R5IH0pOycsXG4gICAgJ30nLFxuICAgICdyZXR1cm4gU3RyaW5nKGlzc3VlTnVtYmVyID8/IFwiXCIpOycsXG4gIF07XG4gIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcbn1cblxuXG5mdW5jdGlvbiBzdW1tYXJ5U2NyaXB0KCk6IHN0cmluZyB7XG4gIHJldHVybiBbXG4gICAgJyMhL2Jpbi9iYXNoJyxcbiAgICAnc2V0IC1lJyxcbiAgICAnZWNobyBcIiMjIERyaWZ0IERldGVjdGlvbiBTdW1tYXJ5XCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcnLFxuICAgICd0b3RhbF9zdGFja3M9MCcsXG4gICAgJ3RvdGFsX2RyaWZ0ZWQ9MCcsXG4gICAgJ3RvdGFsX2Vycm9ycz0wJyxcbiAgICAnJyxcbiAgICAnc2hvcHQgLXMgbnVsbGdsb2InLFxuICAgICdmb3IgZmlsZSBpbiBkcmlmdC1yZXN1bHRzLSouanNvbiBkcmlmdC1yZXN1bHRzLyovZHJpZnQtcmVzdWx0cy0qLmpzb247IGRvJyxcbiAgICAnICBpZiBbWyAtZiBcIiRmaWxlXCIgXV07IHRoZW4nLFxuICAgICcgICAgc3RhY2s9JChiYXNlbmFtZSBcIiRmaWxlXCIgfCBzZWQgLUUgXFxcInMvXmRyaWZ0LXJlc3VsdHMtKFteLl0rKVxcXFwuanNvbiQvXFxcXDEvXFxcIiknLFxuICAgICcgICAgZWNobyBcIiMjIyBTdGFjazogJHN0YWNrXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgICAganEgLXIgXFwnJyArXG4gICAgICAnLiBhcyAkcmVzdWx0cyB8XFxuJyArXG4gICAgICAnXCItIFRvdGFsIHN0YWNrczogXCIgKyAoJHJlc3VsdHMgfCBsZW5ndGggfCB0b3N0cmluZykgKyBcIlxcXFxuXCIgK1xcbicgK1xuICAgICAgJ1wiLSBEcmlmdGVkOiBcIiArIChbLltdIHwgc2VsZWN0KC5kcmlmdFN0YXR1cyA9PSBcIkRSSUZURURcIildIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICdcIi0gRXJyb3JzOiBcIiArIChbLltdIHwgc2VsZWN0KC5lcnJvcildIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCJcXFxcblwiICtcXG4nICtcbiAgICAgICcoWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXCJEUklGVEVEXCIpXSB8IGlmIGxlbmd0aCA+IDAgdGhlbiBcIlxcXFxuKipEcmlmdGVkIHN0YWNrczoqKlxcXFxuXCIgKyAobWFwKFwiICAtIFwiICsgLnN0YWNrTmFtZSArIFwiIChcIiArICgoLmRyaWZ0ZWRSZXNvdXJjZXMgLy8gW10pIHwgbGVuZ3RoIHwgdG9zdHJpbmcpICsgXCIgcmVzb3VyY2VzKVwiKSB8IGpvaW4oXCJcXFxcblwiKSkgZWxzZSBcIlwiIGVuZClcXG4nICtcbiAgICAnXFwnJyArXG4gICAgJyBcIiRmaWxlXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICcgICAgZWNobyBcIlwiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnICAgIHRvdGFsX3N0YWNrcz0kKCh0b3RhbF9zdGFja3MgKyAkKGpxIFxcXCJsZW5ndGhcXFwiIFxcXCIkZmlsZVxcXCIpKSknLFxuICAgICcgICAgdG90YWxfZHJpZnRlZD0kKCh0b3RhbF9kcmlmdGVkICsgJChqcSBcXFwiWy5bXSB8IHNlbGVjdCguZHJpZnRTdGF0dXMgPT0gXFxcXFxcXCJEUklGVEVEXFxcXFxcXCIpXSB8IGxlbmd0aFxcXCIgXFxcIiRmaWxlXFxcIikpKScsXG4gICAgJyAgICB0b3RhbF9lcnJvcnM9JCgodG90YWxfZXJyb3JzICsgJChqcSBcXFwiWy5bXSB8IHNlbGVjdCguZXJyb3IpXSB8IGxlbmd0aFxcXCIgXFxcIiRmaWxlXFxcIikpKScsXG4gICAgJyAgZmknLFxuICAgICdkb25lJyxcbiAgICAnJyxcbiAgICAnZWNobyBcIiMjIyBPdmVyYWxsIFN1bW1hcnlcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2VjaG8gXCItIFRvdGFsIHN0YWNrcyBjaGVja2VkOiAkdG90YWxfc3RhY2tzXCIgPj4gJEdJVEhVQl9TVEVQX1NVTU1BUlknLFxuICAgICdlY2hvIFwiLSBUb3RhbCBkcmlmdGVkIHN0YWNrczogJHRvdGFsX2RyaWZ0ZWRcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2VjaG8gXCItIFRvdGFsIGVycm9yczogJHRvdGFsX2Vycm9yc1wiID4+ICRHSVRIVUJfU1RFUF9TVU1NQVJZJyxcbiAgICAnJyxcbiAgICAnaWYgW1sgJHRvdGFsX2RyaWZ0ZWQgLWd0IDAgXV07IHRoZW4nLFxuICAgICcgIGVjaG8gXCJcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJyAgZWNobyBcIuKaoO+4jyAqKkFjdGlvbiByZXF1aXJlZDoqKiBEcmlmdCBkZXRlY3RlZCBpbiAkdG90YWxfZHJpZnRlZCBzdGFja3NcIiA+PiAkR0lUSFVCX1NURVBfU1VNTUFSWScsXG4gICAgJ2ZpJyxcbiAgXS5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gdG9LZWJhYkNhc2Uoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHMucmVwbGFjZSgvW15hLXpBLVowLTldKy9nLCAnLScpLnJlcGxhY2UoL14tK3wtKyQvZywgJycpLnRvTG93ZXJDYXNlKCk7XG59XG5cblxuZnVuY3Rpb24gdG9HaXRodWJKb2JJZChzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBHaXRIdWIgam9iX2lkIG11c3Qgc3RhcnQgd2l0aCBhIGxldHRlciBvciB1bmRlcnNjb3JlIGFuZCBjb250YWluIG9ubHkgQS1aYS16MC05LCAnLScsICdfJ1xuICAvLyAxKSBSZXBsYWNlIGFueSBkaXNhbGxvd2VkIGNoYXJzIHdpdGggJy0nXG4gIGxldCBvdXQgPSBzLnJlcGxhY2UoL1teQS1aYS16MC05Xy1dKy9nLCAnLScpO1xuICAvLyAyKSBDb2xsYXBzZSBjb25zZWN1dGl2ZSBkYXNoZXNcbiAgb3V0ID0gb3V0LnJlcGxhY2UoLy0rL2csICctJyk7XG4gIC8vIDMpIFRyaW0gbGVhZGluZy90cmFpbGluZyBkYXNoZXMgKHVuZGVyc2NvcmVzIGFyZSBhbGxvd2VkIGF0IHN0YXJ0KVxuICBvdXQgPSBvdXQucmVwbGFjZSgvXi0rfC0rJC9nLCAnJyk7XG4gIC8vIDQpIExvd2VyY2FzZSBmb3IgY29uc2lzdGVuY3kgKG5vdCByZXF1aXJlZCBieSBHaXRIdWIgYnV0IGtlZXBzIHRoaW5ncyBzdGFibGUpXG4gIG91dCA9IG91dC50b0xvd2VyQ2FzZSgpO1xuICAvLyA1KSBFbnN1cmUgaXQgc3RhcnRzIHdpdGggYSBsZXR0ZXIgb3IgdW5kZXJzY29yZVxuICBpZiAoIW91dCB8fCAhL15bYS16X10vaS50ZXN0KG91dCkpIHtcbiAgICBvdXQgPSBgcy0ke291dH1gO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=
|