@xpertss/projen-types 0.0.7 → 0.0.9
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 +28 -138
- package/API.md +3 -305
- package/README.md +16 -1
- package/lib/actions/action-build-workflow.js +1 -1
- package/lib/actions/action-dogfood-workflow.js +1 -1
- package/lib/actions/action-sonar-workflow.js +1 -1
- package/lib/actions/github-action-project.d.ts +4 -4
- package/lib/actions/github-action-project.js +5 -7
- package/lib/cdk/app-runtime-scaffold.js +1 -1
- package/lib/cdk/cdk-app-project.js +1 -1
- package/lib/cdk/cdk-infra-project.js +1 -1
- package/lib/cdk/cdk-typescript-base.js +2 -4
- package/lib/cdk/components/ecr-ecs-constructs.js +1 -1
- package/lib/cdk/components/edge-networking-constructs.js +1 -1
- package/lib/cdk/database-component.js +1 -1
- package/lib/common/internal-actions.d.ts +7 -4
- package/lib/common/internal-actions.js +27 -10
- package/lib/common/manual-deploy-workflow.js +2 -2
- package/lib/common/projen-drift-check-workflow.js +4 -4
- package/lib/common/workflow-change-notice-workflow.js +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +1 -2
- package/lib/java/components/cdk-deploy-hook.js +1 -1
- package/lib/java/components/code-index-workflow.js +1 -1
- package/lib/java/components/docker-publish.js +1 -1
- package/lib/java/components/flyway-migration.js +1 -1
- package/lib/java/components/github-packages-publish.js +1 -1
- package/lib/java/components/maven-central-publish.js +1 -1
- package/lib/java/java-app-project.js +1 -1
- package/lib/java/java-library-project.js +1 -1
- package/lib/java/java-maven-base.js +2 -4
- package/lib/java/java-service-project.js +1 -1
- package/package.json +1 -1
- package/lib/common/actions-allowlist-guard.d.ts +0 -37
- package/lib/common/actions-allowlist-guard.js +0 -72
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ActionsAllowlistGuard = void 0;
|
|
4
|
-
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
-
const projen_1 = require("projen");
|
|
6
|
-
const constants_1 = require("./constants");
|
|
7
|
-
const workflow_purpose_1 = require("./workflow-purpose");
|
|
8
|
-
class ActionsAllowlistGuard extends projen_1.Component {
|
|
9
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "@xpertss/projen-types.ActionsAllowlistGuard", version: "0.0.7" };
|
|
10
|
-
workflow;
|
|
11
|
-
constructor(scope, options = {}) {
|
|
12
|
-
super(scope, 'ActionsAllowlistGuard');
|
|
13
|
-
const gh = scope.github;
|
|
14
|
-
if (!gh) {
|
|
15
|
-
throw new Error('ActionsAllowlistGuard requires GitHub integration to be enabled');
|
|
16
|
-
}
|
|
17
|
-
const gheTokenSecret = options.gheTokenSecret ?? constants_1.DEFAULT_GHE_TOKEN_SECRET;
|
|
18
|
-
this.workflow = new projen_1.github.GithubWorkflow(gh, options.workflowName ?? 'actions-allowlist-guard');
|
|
19
|
-
(0, workflow_purpose_1.noteWorkflowPurpose)(this.workflow.file, 'Block PRs that reference a GitHub Action outside the org allow-list.');
|
|
20
|
-
this.workflow.on({ pullRequestTarget: {} });
|
|
21
|
-
this.workflow.addJob('check', {
|
|
22
|
-
runsOn: ['ubuntu-latest'],
|
|
23
|
-
permissions: {
|
|
24
|
-
contents: projen_1.github.workflows.JobPermission.READ,
|
|
25
|
-
pullRequests: projen_1.github.workflows.JobPermission.WRITE,
|
|
26
|
-
},
|
|
27
|
-
env: { GH_TOKEN: `\${{ secrets.${gheTokenSecret} }}` },
|
|
28
|
-
steps: [
|
|
29
|
-
{
|
|
30
|
-
name: 'Enforce action allow-list',
|
|
31
|
-
run: `set -uo pipefail
|
|
32
|
-
head_sha="\${{ github.event.pull_request.head.sha }}"
|
|
33
|
-
pr_number="\${{ github.event.number }}"
|
|
34
|
-
repo="\${GITHUB_REPOSITORY}"
|
|
35
|
-
# All files at the PR head (recursive tree), narrowed to workflow and
|
|
36
|
-
# composite-action files.
|
|
37
|
-
files="$(gh api "repos/$repo/git/trees/$head_sha?recursive=1" --jq '.tree[] | select(.type=="blob") | .path' | grep -E '^\\.github/(workflows/[^/]+\\.(yml|yaml)|actions/[^/]+/action\\.(yml|yaml))$' || true)"
|
|
38
|
-
violations=()
|
|
39
|
-
while IFS= read -r path; do
|
|
40
|
-
[ -z "$path" ] && continue
|
|
41
|
-
content="$(gh api "repos/$repo/contents/$path?ref=$head_sha" --jq -r '.content' 2>/dev/null | base64 -d 2>/dev/null || true)"
|
|
42
|
-
lineno=0
|
|
43
|
-
while IFS= read -r line; do
|
|
44
|
-
lineno=$((lineno + 1))
|
|
45
|
-
value="$(printf '%s\\n' "$line" | sed -n 's/^[[:space:]]*uses:[[:space:]]*//p' | tr -d '\\\"')"
|
|
46
|
-
[ -z "$value" ] && continue
|
|
47
|
-
case "$value" in
|
|
48
|
-
actions/*|docker/*|xpertss/*|.|./*) ;;
|
|
49
|
-
*) violations+=(" - $path:$lineno — uses: $value") ;;
|
|
50
|
-
esac
|
|
51
|
-
done <<< "$content"
|
|
52
|
-
done <<< "$files"
|
|
53
|
-
if [ "\${#violations[@]}" -gt 0 ]; then
|
|
54
|
-
{
|
|
55
|
-
echo "❌ Disallowed GitHub Action reference"
|
|
56
|
-
echo ""
|
|
57
|
-
echo "This PR references an action outside the allow-list:"
|
|
58
|
-
echo ""
|
|
59
|
-
printf '%s\\n' "\${violations[@]}"
|
|
60
|
-
echo ""
|
|
61
|
-
echo "Org policy trusts only actions/*, docker/*, and xpertss/*. Use an equivalent internal action, or ask its maintainers to add one."
|
|
62
|
-
} | gh pr comment "$pr_number" --body-file - || echo "::warning::could not post PR comment (fork PR or missing token)"
|
|
63
|
-
exit 1
|
|
64
|
-
fi
|
|
65
|
-
`,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
exports.ActionsAllowlistGuard = ActionsAllowlistGuard;
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9ucy1hbGxvd2xpc3QtZ3VhcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbW9uL2FjdGlvbnMtYWxsb3dsaXN0LWd1YXJkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxtQ0FBMkM7QUFDM0MsMkNBQXVEO0FBQ3ZELHlEQUF5RDtBQW9DekQsTUFBYSxxQkFBc0IsU0FBUSxrQkFBUzs7SUFDbEMsUUFBUSxDQUF3QjtJQUVoRCxZQUNFLEtBQTJCLEVBQzNCLFVBQXdDLEVBQUU7UUFFMUMsS0FBSyxDQUFDLEtBQUssRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBRXRDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDeEIsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ1IsTUFBTSxJQUFJLEtBQUssQ0FDYixpRUFBaUUsQ0FDbEUsQ0FBQztRQUNKLENBQUM7UUFFRCxNQUFNLGNBQWMsR0FDbEIsT0FBTyxDQUFDLGNBQWMsSUFBSSxvQ0FBd0IsQ0FBQztRQUVyRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksZUFBTSxDQUFDLGNBQWMsQ0FDdkMsRUFBRSxFQUNGLE9BQU8sQ0FBQyxZQUFZLElBQUkseUJBQXlCLENBQ2xELENBQUM7UUFDRixJQUFBLHNDQUFtQixFQUNqQixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFDbEIsc0VBQXNFLENBQ3ZFLENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQzVCLE1BQU0sRUFBRSxDQUFDLGVBQWUsQ0FBQztZQUN6QixXQUFXLEVBQUU7Z0JBQ1gsUUFBUSxFQUFFLGVBQU0sQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUk7Z0JBQzdDLFlBQVksRUFBRSxlQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLO2FBQ25EO1lBQ0QsR0FBRyxFQUFFLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixjQUFjLEtBQUssRUFBRTtZQUN0RCxLQUFLLEVBQUU7Z0JBQ0w7b0JBQ0UsSUFBSSxFQUFFLDJCQUEyQjtvQkFDakMsR0FBRyxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBa0NkO2lCQUNRO2FBQ0Y7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDOztBQTVFSCxzREE2RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIGdpdGh1YiB9IGZyb20gJ3Byb2plbic7XG5pbXBvcnQgeyBERUZBVUxUX0dIRV9UT0tFTl9TRUNSRVQgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBub3RlV29ya2Zsb3dQdXJwb3NlIH0gZnJvbSAnLi93b3JrZmxvdy1wdXJwb3NlJztcblxuLyoqXG4gKiBCbG9ja2luZywgdGFtcGVyLXByb29mIFBSIGNoZWNrIHRoYXQgc3RvcHMgYSBkaXNhbGxvd2VkIEdpdEh1YiBBY3Rpb25cbiAqIHJlZmVyZW5jZSBmcm9tIGV2ZXIgKHJlKWFwcGVhcmluZyBpbiBhIHJlcG8ncyB3b3JrZmxvdyBvciBjb21wb3NpdGUtYWN0aW9uXG4gKiBmaWxlcy5cbiAqXG4gKiBSdW5zIG9uIGBwdWxsX3JlcXVlc3RfdGFyZ2V0YCBzbyBpdCBhbHdheXMgZXhlY3V0ZXMgdGhlIGNvcHkgb2YgdGhpc1xuICogd29ya2Zsb3cgY29tbWl0dGVkIG9uIHRoZSBiYXNlIGJyYW5jaCAtIGEgUFIgY2Fubm90IGVkaXQgdGhpcyBmaWxlIHRvXG4gKiBkaXNhYmxlIG9yIHdlYWtlbiB0aGUgY2hlY2suIEl0IGNoZWNrcyBvdXQgYW5kIGV4ZWN1dGVzIG5vdGhpbmcgZnJvbSB0aGVcbiAqIFBSOyBpdCBvbmx5IHJlYWRzIHRoZSBQUiBoZWFkJ3MgZmlsZSBjb250ZW50IHZpYSB0aGUgR2l0SHViIEFQSS4gQmVjYXVzZVxuICogYHB1bGxfcmVxdWVzdF90YXJnZXRgIHJ1bnMgd2l0aCB0aGUgYmFzZSByZXBvJ3MgdG9rZW4gZXZlbiBmb3JcbiAqIGZvcmstb3JpZ2luYXRlZCBQUnMsIHRoZSBmYWlsdXJlIGNvbW1lbnQgcG9zdHMgcmVsaWFibHkuXG4gKlxuICAqIEl0IHBlcmZvcm1zIGEgZmxhdCwgdW5jb25kaXRpb25hbCBzY2FuIG9mIHRoZSBQUidzIGhlYWQgcmVmIChub1xuICAqIGJhc2UtdnMtaGVhZCBjb21wYXJpc29uKTogZmV0Y2ggdGhlIGNvbnRlbnQgb2YgZXZlcnkgR2l0SHViIHdvcmtmbG93IGFuZFxuICAqIGNvbXBvc2l0ZS1hY3Rpb24gZmlsZSwgZXh0cmFjdCBldmVyeSBgdXNlczpgIHZhbHVlLCBhbmQgZmFpbCBpZiBhbnkgZG9lc1xuICAqIG5vdCBzdGFydCB3aXRoIG9uZSBvZiB0aGUgdGhyZWUgdHJ1c3RlZCBuYW1lc3BhY2VzIGZyb20gQUQtMDAxXG4gICogKGBhY3Rpb25zL2AsIGBkb2NrZXIvYCwgYHhwZXJ0c3MvYCkuIFRoZSBzaW5nbGVcbiAqIGV4ZW1wdGlvbiBpcyBhIGxvY2FsIHNhbWUtcmVwbyByZWZlcmVuY2UgKGB1c2VzOiAuYCBvclxuICogYHVzZXM6IC4vLmdpdGh1Yi9hY3Rpb25zLzxuYW1lPmApIC0gdGhlIHJlcG8ncyBvd24gaGFuZC1jb21taXR0ZWQgYWN0aW9uLFxuICogdG8gd2hpY2ggdGhlIG9yZyBwb2xpY3kncyBcImFsbG93IHNlbGVjdCBhY3Rpb25zXCIgc2V0dGluZyBkb2VzIG5vdCBhcHBseS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBY3Rpb25zQWxsb3dsaXN0R3VhcmRPcHRpb25zIHtcbiAgLyoqXG4gICAqIEdpdEh1YiBzZWNyZXQgaG9sZGluZyBhIHRva2VuIHdpdGggcGVybWlzc2lvbiB0byBjb21tZW50IG9uIFBScywgdXNlZFxuICAgKiBmb3IgdGhlIGZhaWx1cmUgY29tbWVudC4gVGhlIGNoZWNrIHN0aWxsIGZhaWxzIHdpdGhvdXQgaXQsIHNvIGZvcmsgUFJzIC1cbiAgICogd2hpY2ggZ2V0IG5vIHNlY3JldHMgLSBhcmUgb25seSBtaXNzaW5nIHRoZSBleHRyYSBjb21tZW50LlxuICAgKiBAZGVmYXVsdCBcIlBST0pFTl9HSVRIVUJfVE9LRU5cIlxuICAgKi9cbiAgcmVhZG9ubHkgZ2hlVG9rZW5TZWNyZXQ/OiBzdHJpbmc7XG5cbiAgLyoqIEBkZWZhdWx0IFwiYWN0aW9ucy1hbGxvd2xpc3QtZ3VhcmRcIiAqL1xuICByZWFkb25seSB3b3JrZmxvd05hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBBY3Rpb25zQWxsb3dsaXN0R3VhcmQgZXh0ZW5kcyBDb21wb25lbnQge1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3c6IGdpdGh1Yi5HaXRodWJXb3JrZmxvdztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogZ2l0aHViLkdpdEh1YlByb2plY3QsXG4gICAgb3B0aW9uczogQWN0aW9uc0FsbG93bGlzdEd1YXJkT3B0aW9ucyA9IHt9LFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgJ0FjdGlvbnNBbGxvd2xpc3RHdWFyZCcpO1xuXG4gICAgY29uc3QgZ2ggPSBzY29wZS5naXRodWI7XG4gICAgaWYgKCFnaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQWN0aW9uc0FsbG93bGlzdEd1YXJkIHJlcXVpcmVzIEdpdEh1YiBpbnRlZ3JhdGlvbiB0byBiZSBlbmFibGVkJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgZ2hlVG9rZW5TZWNyZXQgPVxuICAgICAgb3B0aW9ucy5naGVUb2tlblNlY3JldCA/PyBERUZBVUxUX0dIRV9UT0tFTl9TRUNSRVQ7XG5cbiAgICB0aGlzLndvcmtmbG93ID0gbmV3IGdpdGh1Yi5HaXRodWJXb3JrZmxvdyhcbiAgICAgIGdoLFxuICAgICAgb3B0aW9ucy53b3JrZmxvd05hbWUgPz8gJ2FjdGlvbnMtYWxsb3dsaXN0LWd1YXJkJyxcbiAgICApO1xuICAgIG5vdGVXb3JrZmxvd1B1cnBvc2UoXG4gICAgICB0aGlzLndvcmtmbG93LmZpbGUsXG4gICAgICAnQmxvY2sgUFJzIHRoYXQgcmVmZXJlbmNlIGEgR2l0SHViIEFjdGlvbiBvdXRzaWRlIHRoZSBvcmcgYWxsb3ctbGlzdC4nLFxuICAgICk7XG4gICAgdGhpcy53b3JrZmxvdy5vbih7IHB1bGxSZXF1ZXN0VGFyZ2V0OiB7fSB9KTtcbiAgICB0aGlzLndvcmtmbG93LmFkZEpvYignY2hlY2snLCB7XG4gICAgICBydW5zT246IFsndWJ1bnR1LWxhdGVzdCddLFxuICAgICAgcGVybWlzc2lvbnM6IHtcbiAgICAgICAgY29udGVudHM6IGdpdGh1Yi53b3JrZmxvd3MuSm9iUGVybWlzc2lvbi5SRUFELFxuICAgICAgICBwdWxsUmVxdWVzdHM6IGdpdGh1Yi53b3JrZmxvd3MuSm9iUGVybWlzc2lvbi5XUklURSxcbiAgICAgIH0sXG4gICAgICBlbnY6IHsgR0hfVE9LRU46IGBcXCR7eyBzZWNyZXRzLiR7Z2hlVG9rZW5TZWNyZXR9IH19YCB9LFxuICAgICAgc3RlcHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdFbmZvcmNlIGFjdGlvbiBhbGxvdy1saXN0JyxcbiAgICAgICAgICBydW46IGBzZXQgLXVvIHBpcGVmYWlsXG5oZWFkX3NoYT1cIlxcJHt7IGdpdGh1Yi5ldmVudC5wdWxsX3JlcXVlc3QuaGVhZC5zaGEgfX1cIlxucHJfbnVtYmVyPVwiXFwke3sgZ2l0aHViLmV2ZW50Lm51bWJlciB9fVwiXG5yZXBvPVwiXFwke0dJVEhVQl9SRVBPU0lUT1JZfVwiXG4jIEFsbCBmaWxlcyBhdCB0aGUgUFIgaGVhZCAocmVjdXJzaXZlIHRyZWUpLCBuYXJyb3dlZCB0byB3b3JrZmxvdyBhbmRcbiMgY29tcG9zaXRlLWFjdGlvbiBmaWxlcy5cbmZpbGVzPVwiJChnaCBhcGkgXCJyZXBvcy8kcmVwby9naXQvdHJlZXMvJGhlYWRfc2hhP3JlY3Vyc2l2ZT0xXCIgLS1qcSAnLnRyZWVbXSB8IHNlbGVjdCgudHlwZT09XCJibG9iXCIpIHwgLnBhdGgnIHwgZ3JlcCAtRSAnXlxcXFwuZ2l0aHViLyh3b3JrZmxvd3MvW14vXStcXFxcLih5bWx8eWFtbCl8YWN0aW9ucy9bXi9dKy9hY3Rpb25cXFxcLih5bWx8eWFtbCkpJCcgfHwgdHJ1ZSlcIlxudmlvbGF0aW9ucz0oKVxud2hpbGUgSUZTPSByZWFkIC1yIHBhdGg7IGRvXG4gIFsgLXogXCIkcGF0aFwiIF0gJiYgY29udGludWVcbiAgY29udGVudD1cIiQoZ2ggYXBpIFwicmVwb3MvJHJlcG8vY29udGVudHMvJHBhdGg/cmVmPSRoZWFkX3NoYVwiIC0tanEgLXIgJy5jb250ZW50JyAyPi9kZXYvbnVsbCB8IGJhc2U2NCAtZCAyPi9kZXYvbnVsbCB8fCB0cnVlKVwiXG4gIGxpbmVubz0wXG4gIHdoaWxlIElGUz0gcmVhZCAtciBsaW5lOyBkb1xuICAgIGxpbmVubz0kKChsaW5lbm8gKyAxKSlcbiAgICB2YWx1ZT1cIiQocHJpbnRmICclc1xcXFxuJyBcIiRsaW5lXCIgfCBzZWQgLW4gJ3MvXltbOnNwYWNlOl1dKnVzZXM6W1s6c3BhY2U6XV0qLy9wJyB8IHRyIC1kICdcXFxcXFxcIicpXCJcbiAgICBbIC16IFwiJHZhbHVlXCIgXSAmJiBjb250aW51ZVxuICAgIGNhc2UgXCIkdmFsdWVcIiBpblxuICAgICAgYWN0aW9ucy8qfGRvY2tlci8qfHhwZXJ0c3MvKnwufC4vKikgOztcbiAgICAgICopIHZpb2xhdGlvbnMrPShcIiAgLSAkcGF0aDokbGluZW5vIOKAlCB1c2VzOiAkdmFsdWVcIikgOztcbiAgICBlc2FjXG4gIGRvbmUgPDw8IFwiJGNvbnRlbnRcIlxuZG9uZSA8PDwgXCIkZmlsZXNcIlxuaWYgWyBcIlxcJHsjdmlvbGF0aW9uc1tAXX1cIiAtZ3QgMCBdOyB0aGVuXG4gIHtcbiAgICBlY2hvIFwi4p2MIERpc2FsbG93ZWQgR2l0SHViIEFjdGlvbiByZWZlcmVuY2VcIlxuICAgIGVjaG8gXCJcIlxuICAgIGVjaG8gXCJUaGlzIFBSIHJlZmVyZW5jZXMgYW4gYWN0aW9uIG91dHNpZGUgdGhlIGFsbG93LWxpc3Q6XCJcbiAgICBlY2hvIFwiXCJcbiAgICBwcmludGYgJyVzXFxcXG4nIFwiXFwke3Zpb2xhdGlvbnNbQF19XCJcbiAgICBlY2hvIFwiXCJcbiAgICBlY2hvIFwiT3JnIHBvbGljeSB0cnVzdHMgb25seSBhY3Rpb25zLyosIGRvY2tlci8qLCBhbmQgeHBlcnRzcy8qLiBVc2UgYW4gZXF1aXZhbGVudCBpbnRlcm5hbCBhY3Rpb24sIG9yIGFzayBpdHMgbWFpbnRhaW5lcnMgdG8gYWRkIG9uZS5cIlxuICB9IHwgZ2ggcHIgY29tbWVudCBcIiRwcl9udW1iZXJcIiAtLWJvZHktZmlsZSAtIHx8IGVjaG8gXCI6Ondhcm5pbmc6OmNvdWxkIG5vdCBwb3N0IFBSIGNvbW1lbnQgKGZvcmsgUFIgb3IgbWlzc2luZyB0b2tlbilcIlxuICBleGl0IDFcbmZpXG5gLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxufVxuIl19
|