UNPKG

projen

Version:

CDK for software projects

578 lines • 104 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeArtifactAuthProvider = exports.Publisher = void 0; exports.isAwsCodeArtifactRegistry = isAwsCodeArtifactRegistry; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const component_1 = require("../component"); const constants_1 = require("../github/constants"); const workflows_model_1 = require("../github/workflows-model"); const node_package_1 = require("../javascript/node-package"); const runner_options_1 = require("../runner-options"); const version_1 = require("../version"); const PUBLIB_VERSION = "latest"; const GITHUB_PACKAGES_REGISTRY = "npm.pkg.github.com"; const ARTIFACTS_DOWNLOAD_DIR = "dist"; const GITHUB_PACKAGES_MAVEN_REPOSITORY = "https://maven.pkg.github.com"; const GITHUB_PACKAGES_NUGET_REPOSITORY = "https://nuget.pkg.github.com"; const AWS_CODEARTIFACT_REGISTRY_REGEX = /.codeartifact.*.amazonaws.com/; const PUBLIB_TOOLCHAIN = { js: {}, java: { java: { version: "11" } }, python: { python: { version: "3.x" } }, go: { go: { version: "^1.18.0" } }, dotnet: { dotnet: { version: "6.x" } }, }; const PUBLISH_JOB_PREFIX = "release_"; /** * Implements GitHub jobs for publishing modules to package managers. * * Under the hood, it uses https://github.com/aws/publib */ class Publisher extends component_1.Component { constructor(project, options) { super(project); // functions that create jobs associated with a specific branch this._jobFactories = []; this._gitHubPrePublishing = []; this._gitHubPostPublishing = []; // List of publish jobs added to the publisher // Maps between the basename and the jobname this.publishJobs = {}; this.buildJobId = options.buildJobId; this.artifactName = options.artifactName; this.publibVersion = options.publibVersion ?? options.jsiiReleaseVersion ?? PUBLIB_VERSION; this.jsiiReleaseVersion = this.publibVersion; this.condition = options.condition; this.dryRun = options.dryRun ?? false; this.workflowNodeVersion = options.workflowNodeVersion ?? "lts/*"; this.workflowContainerImage = options.workflowContainerImage; this.failureIssue = options.failureIssue ?? false; this.failureIssueLabel = options.failureIssueLabel ?? "failed-release"; this.publishTasks = options.publishTasks ?? false; this.runsOn = options.workflowRunsOn; this.runsOnGroup = options.workflowRunsOnGroup; } /** * Called by `Release` to add the publishing jobs to a release workflow * associated with a specific branch. * @param branch The branch name * @param options Branch options * * @internal */ _renderJobsForBranch(branch, options) { let jobs = {}; for (const factory of this._jobFactories) { jobs = { ...jobs, ...factory(branch, options), }; } return jobs; } /** * Adds pre publishing steps for the GitHub release job. * * @param steps The steps. */ addGitHubPrePublishingSteps(...steps) { this._gitHubPrePublishing.push(...steps); } /** * Adds post publishing steps for the GitHub release job. * * @param steps The steps. */ addGitHubPostPublishingSteps(...steps) { this._gitHubPostPublishing.push(...steps); } /** * Publish to git. * * This includes generating a project-level changelog and release tags. * * @param options Options */ publishToGit(options) { const releaseTagFile = options.releaseTagFile; const versionFile = options.versionFile; const changelog = options.changelogFile; const projectChangelogFile = options.projectChangelogFile; const gitBranch = options.gitBranch ?? "main"; const taskName = gitBranch === "main" || gitBranch === "master" ? Publisher.PUBLISH_GIT_TASK_NAME : `${Publisher.PUBLISH_GIT_TASK_NAME}:${gitBranch}`; const publishTask = this.project.addTask(taskName, { description: "Prepends the release changelog onto the project changelog, creates a release commit, and tags the release", env: { CHANGELOG: changelog, RELEASE_TAG_FILE: releaseTagFile, PROJECT_CHANGELOG_FILE: projectChangelogFile ?? "", VERSION_FILE: versionFile, }, condition: version_1.CHANGES_SINCE_LAST_RELEASE, }); if (projectChangelogFile) { publishTask.builtin("release/update-changelog"); } publishTask.builtin("release/tag-version"); if (options.gitPushCommand !== "") { const gitPushCommand = options.gitPushCommand || `git push --follow-tags origin ${gitBranch}`; publishTask.exec(gitPushCommand); } return publishTask; } /** * Creates a GitHub Release. * @param options Options */ publishToGitHubReleases(options) { const jobName = "github"; this.addPublishJob(jobName, (_branch, branchOptions) => { return { registryName: "GitHub Releases", prePublishSteps: options.prePublishSteps ?? this._gitHubPrePublishing, postPublishSteps: options.postPublishSteps ?? this._gitHubPostPublishing, publishTools: options.publishTools, permissions: { contents: workflows_model_1.JobPermission.WRITE, }, needs: Object.entries(this.publishJobs) .filter(([name, _]) => name != jobName) .map(([_, job]) => job), workflowEnv: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}", }, run: this.githubReleaseCommand(options, branchOptions), }; }); } /** * Publishes artifacts from `js/**` to npm. * @param options Options */ publishToNpm(options = {}) { const isGitHubPackages = options.registry?.startsWith(GITHUB_PACKAGES_REGISTRY); const isAwsCodeArtifact = isAwsCodeArtifactRegistry(options.registry); const isAwsCodeArtifactWithOidc = isAwsCodeArtifact && options.codeArtifactOptions?.authProvider === CodeArtifactAuthProvider.GITHUB_OIDC; const npmToken = (0, node_package_1.defaultNpmToken)(options.npmTokenSecret, options.registry); if (options.distTag) { this.project.logger.warn("The `distTag` option is deprecated. Use the npmDistTag option instead."); } const prePublishSteps = options.prePublishSteps ?? []; if (isAwsCodeArtifactWithOidc) { if (options.codeArtifactOptions?.accessKeyIdSecret || options.codeArtifactOptions?.secretAccessKeySecret) { throw new Error("access and secret key pair should not be provided when using GITHUB_OIDC auth provider for AWS CodeArtifact"); } else if (!options.codeArtifactOptions?.roleToAssume) { throw new Error('"roleToAssume" property is required when using GITHUB_OIDC for AWS CodeArtifact options'); } const regionCaptureRegex = /codeartifact\.(.+)\.amazonaws\.com/; const region = options.registry?.match(regionCaptureRegex)?.[1]; prePublishSteps.push({ name: "Configure AWS Credentials via GitHub OIDC Provider", uses: "aws-actions/configure-aws-credentials@v4", with: { "role-to-assume": options.codeArtifactOptions.roleToAssume, "aws-region": region, }, }); } this.addPublishJob("npm", (_branch, branchOptions) => { if (branchOptions.npmDistTag && options.distTag) { throw new Error("cannot set branch-level npmDistTag and npmDistTag in publishToNpm()"); } const npmProvenance = options.npmProvenance ? "true" : undefined; const needsIdTokenWrite = isAwsCodeArtifactWithOidc || npmProvenance; return { publishTools: PUBLIB_TOOLCHAIN.js, prePublishSteps, postPublishSteps: options.postPublishSteps ?? [], run: this.publibCommand("publib-npm"), registryName: "npm", env: { NPM_DIST_TAG: branchOptions.npmDistTag ?? options.distTag ?? "latest", NPM_REGISTRY: options.registry, NPM_CONFIG_PROVENANCE: npmProvenance, }, permissions: { idToken: needsIdTokenWrite ? workflows_model_1.JobPermission.WRITE : undefined, contents: workflows_model_1.JobPermission.READ, packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined, }, workflowEnv: { NPM_TOKEN: npmToken ? secret(npmToken) : undefined, // if we are publishing to AWS CodeArtifact, pass AWS access keys that will be used to generate NPM_TOKEN using AWS CLI. AWS_ACCESS_KEY_ID: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc ? secret(options.codeArtifactOptions?.accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID") : undefined, AWS_SECRET_ACCESS_KEY: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc ? secret(options.codeArtifactOptions?.secretAccessKeySecret ?? "AWS_SECRET_ACCESS_KEY") : undefined, AWS_ROLE_TO_ASSUME: isAwsCodeArtifact && !isAwsCodeArtifactWithOidc ? options.codeArtifactOptions?.roleToAssume : undefined, }, }; }); } /** * Publishes artifacts from `dotnet/**` to NuGet Gallery. * @param options Options */ publishToNuget(options = {}) { const isGitHubPackages = options.nugetServer?.startsWith(GITHUB_PACKAGES_NUGET_REPOSITORY); this.addPublishJob("nuget", (_branch, _branchOptions) => ({ publishTools: PUBLIB_TOOLCHAIN.dotnet, prePublishSteps: options.prePublishSteps ?? [], postPublishSteps: options.postPublishSteps ?? [], run: this.publibCommand("publib-nuget"), registryName: "NuGet Gallery", permissions: { contents: workflows_model_1.JobPermission.READ, packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined, }, workflowEnv: { NUGET_API_KEY: secret(isGitHubPackages ? "GITHUB_TOKEN" : options.nugetApiKeySecret ?? "NUGET_API_KEY"), NUGET_SERVER: options.nugetServer ?? undefined, }, })); } /** * Publishes artifacts from `java/**` to Maven. * @param options Options */ publishToMaven(options = {}) { const isGitHubPackages = options.mavenRepositoryUrl?.startsWith(GITHUB_PACKAGES_MAVEN_REPOSITORY); const isGitHubActor = isGitHubPackages && options.mavenUsername == undefined; const mavenServerId = options.mavenServerId ?? (isGitHubPackages ? "github" : undefined); if (isGitHubPackages && mavenServerId != "github") { throw new Error('publishing to GitHub Packages requires the "mavenServerId" to be "github"'); } if (mavenServerId === "central-ossrh" && options.mavenEndpoint != null) { throw new Error('Custom endpoints are not supported when publishing to Maven Central (mavenServerId: "central-ossrh"). Please remove "mavenEndpoint" from the options.'); } this.addPublishJob("maven", (_branch, _branchOptions) => ({ registryName: "Maven Central", publishTools: PUBLIB_TOOLCHAIN.java, prePublishSteps: options.prePublishSteps ?? [], postPublishSteps: options.postPublishSteps ?? [], run: this.publibCommand("publib-maven"), env: { MAVEN_ENDPOINT: options.mavenEndpoint, MAVEN_SERVER_ID: mavenServerId, MAVEN_REPOSITORY_URL: options.mavenRepositoryUrl, }, workflowEnv: { MAVEN_GPG_PRIVATE_KEY: isGitHubPackages ? undefined : secret(options.mavenGpgPrivateKeySecret ?? "MAVEN_GPG_PRIVATE_KEY"), MAVEN_GPG_PRIVATE_KEY_PASSPHRASE: isGitHubPackages ? undefined : secret(options.mavenGpgPrivateKeyPassphrase ?? "MAVEN_GPG_PRIVATE_KEY_PASSPHRASE"), MAVEN_PASSWORD: secret(options.mavenPassword ?? (isGitHubPackages ? "GITHUB_TOKEN" : "MAVEN_PASSWORD")), MAVEN_USERNAME: isGitHubActor ? "${{ github.actor }}" : secret(options.mavenUsername ?? "MAVEN_USERNAME"), MAVEN_STAGING_PROFILE_ID: isGitHubPackages ? undefined : secret(options.mavenStagingProfileId ?? "MAVEN_STAGING_PROFILE_ID"), }, permissions: { contents: workflows_model_1.JobPermission.READ, packages: isGitHubPackages ? workflows_model_1.JobPermission.WRITE : undefined, }, })); } /** * Publishes wheel artifacts from `python` to PyPI. * @param options Options */ publishToPyPi(options = {}) { let permissions = { contents: workflows_model_1.JobPermission.READ }; const prePublishSteps = options.prePublishSteps ?? []; let workflowEnv = {}; const isAwsCodeArtifact = isAwsCodeArtifactRegistry(options.twineRegistryUrl); if (isAwsCodeArtifact) { const { domain, account, region } = awsCodeArtifactInfoFromUrl(options.twineRegistryUrl); const { authProvider, roleToAssume, accessKeyIdSecret, secretAccessKeySecret, } = options.codeArtifactOptions ?? {}; const useOidcAuth = authProvider === CodeArtifactAuthProvider.GITHUB_OIDC; if (useOidcAuth) { if (!roleToAssume) { throw new Error('"roleToAssume" property is required when using GITHUB_OIDC for AWS CodeArtifact options'); } permissions = { ...permissions, idToken: workflows_model_1.JobPermission.WRITE }; prePublishSteps.push({ name: "Configure AWS Credentials via GitHub OIDC Provider", uses: "aws-actions/configure-aws-credentials@v4", with: { "role-to-assume": roleToAssume, "aws-region": region, }, }); } prePublishSteps.push({ name: "Generate CodeArtifact Token", run: `echo "TWINE_PASSWORD=$(aws codeartifact get-authorization-token --domain ${domain} --domain-owner ${account} --region ${region} --query authorizationToken --output text)" >> $GITHUB_ENV`, env: useOidcAuth ? undefined : { AWS_ACCESS_KEY_ID: secret(accessKeyIdSecret ?? "AWS_ACCESS_KEY_ID"), AWS_SECRET_ACCESS_KEY: secret(secretAccessKeySecret ?? "AWS_SECRET_ACCESS_KEY"), }, }); workflowEnv = { TWINE_USERNAME: "aws" }; } else { workflowEnv = { TWINE_USERNAME: secret(options.twineUsernameSecret ?? "TWINE_USERNAME"), TWINE_PASSWORD: secret(options.twinePasswordSecret ?? "TWINE_PASSWORD"), }; } this.addPublishJob("pypi", (_branch, _branchOptions) => ({ registryName: "PyPI", publishTools: PUBLIB_TOOLCHAIN.python, permissions, prePublishSteps, postPublishSteps: options.postPublishSteps ?? [], run: this.publibCommand("publib-pypi"), env: { TWINE_REPOSITORY_URL: options.twineRegistryUrl, }, workflowEnv, })); } /** * Adds a go publishing job. * @param options Options */ publishToGo(options = {}) { const prePublishSteps = options.prePublishSteps ?? []; const workflowEnv = {}; if (options.githubUseSsh) { workflowEnv.GITHUB_USE_SSH = "true"; workflowEnv.SSH_AUTH_SOCK = "/tmp/ssh_agent.sock"; prePublishSteps.push({ name: "Setup GitHub deploy key", run: 'ssh-agent -a ${SSH_AUTH_SOCK} && ssh-add - <<< "${GITHUB_DEPLOY_KEY}"', env: { GITHUB_DEPLOY_KEY: secret(options.githubDeployKeySecret ?? "GO_GITHUB_DEPLOY_KEY"), SSH_AUTH_SOCK: workflowEnv.SSH_AUTH_SOCK, }, }); } else { workflowEnv.GITHUB_TOKEN = secret(options.githubTokenSecret ?? "GO_GITHUB_TOKEN"); } this.addPublishJob("golang", (_branch, _branchOptions) => ({ publishTools: PUBLIB_TOOLCHAIN.go, prePublishSteps: prePublishSteps, postPublishSteps: options.postPublishSteps ?? [], run: this.publibCommand("publib-golang"), registryName: "GitHub Go Module Repository", env: { GIT_BRANCH: options.gitBranch, GIT_USER_NAME: options.gitUserName ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER.name, GIT_USER_EMAIL: options.gitUserEmail ?? constants_1.DEFAULT_GITHUB_ACTIONS_USER.email, GIT_COMMIT_MESSAGE: options.gitCommitMessage, }, workflowEnv: workflowEnv, })); } addPublishJob( /** * The basename of the publish job (should be lowercase). * Will be extended with a prefix. */ basename, factory) { const jobname = `${PUBLISH_JOB_PREFIX}${basename}`; this.publishJobs[basename] = jobname; this._jobFactories.push((branch, branchOptions) => { const opts = factory(branch, branchOptions); if (jobname in this._jobFactories) { throw new Error(`Duplicate job with name "${jobname}"`); } const commandToRun = this.dryRun ? `echo "DRY RUN: ${opts.run}"` : opts.run; const requiredEnv = new Array(); // jobEnv is the env we pass to the github job (task environment + secrets/expressions). const jobEnv = { ...opts.env }; const workflowEnvEntries = Object.entries(opts.workflowEnv ?? {}).filter(([_, value]) => value != undefined); for (const [env, expression] of workflowEnvEntries) { requiredEnv.push(env); jobEnv[env] = expression; } if (this.publishTasks) { const branchSuffix = branch === "main" || branch === "master" ? "" : `:${branch}`; // define a task which can be used through `projen publish:xxx`. const task = this.project.addTask(`publish:${basename.toLocaleLowerCase()}${branchSuffix}`, { description: `Publish this package to ${opts.registryName}`, env: opts.env, requiredEnv: requiredEnv, }); // first verify that we are on the correct branch task.exec(`test "$(git branch --show-current)" = "${branch}"`); // run commands task.exec(commandToRun); } const steps = [ { name: "Download build artifacts", uses: "actions/download-artifact@v4", with: { name: constants_1.BUILD_ARTIFACT_NAME, path: ARTIFACTS_DOWNLOAD_DIR, // this must be "dist" for publib }, }, { name: "Restore build artifact permissions", continueOnError: true, run: [ `cd ${ARTIFACTS_DOWNLOAD_DIR} && setfacl --restore=${constants_1.PERMISSION_BACKUP_FILE}`, ].join("\n"), }, ...opts.prePublishSteps, { name: "Release", // it would have been nice if we could just run "projen publish:xxx" here but that is not possible because this job does not checkout sources run: commandToRun, env: jobEnv, }, ...opts.postPublishSteps, ]; const perms = opts.permissions ?? { contents: workflows_model_1.JobPermission.READ }; const container = this.workflowContainerImage ? { image: this.workflowContainerImage, } : undefined; if (this.failureIssue) { steps.push(...[ { name: "Extract Version", if: "${{ failure() }}", id: "extract-version", shell: "bash", run: 'echo "VERSION=$(cat dist/version.txt)" >> $GITHUB_OUTPUT', }, { name: "Create Issue", if: "${{ failure() }}", uses: "imjohnbo/issue-bot@v3", with: { labels: this.failureIssueLabel, title: `Publishing v\${{ steps.extract-version.outputs.VERSION }} to ${opts.registryName} failed`, body: "See https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", }, env: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}", }, }, ]); Object.assign(perms, { issues: workflows_model_1.JobPermission.WRITE }); } return { [jobname]: { tools: { node: { version: this.workflowNodeVersion }, ...opts.publishTools, }, name: `Publish to ${opts.registryName}`, permissions: perms, if: this.condition, needs: [this.buildJobId, ...(opts.needs ?? [])], ...(0, runner_options_1.filteredRunsOnOptions)(this.runsOn, this.runsOnGroup), container, steps, }, }; }); } publibCommand(command) { return `npx -p publib@${this.publibVersion} ${command}`; } githubReleaseCommand(options, branchOptions) { const changelogFile = options.changelogFile; const releaseTagFile = options.releaseTagFile; // create a github release const releaseTag = `$(cat ${releaseTagFile})`; const ghReleaseCommand = [ `gh release create ${releaseTag}`, "-R $GITHUB_REPOSITORY", `-F ${changelogFile}`, `-t ${releaseTag}`, "--target $GITHUB_SHA", ]; if (branchOptions.prerelease) { ghReleaseCommand.push("-p"); } const ghRelease = ghReleaseCommand.join(" "); // release script that does not error when re-releasing a given version const idempotentRelease = [ "errout=$(mktemp);", `${ghRelease} 2> $errout && true;`, "exitcode=$?;", 'if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then', "cat $errout;", "exit $exitcode;", "fi", ].join(" "); return idempotentRelease; } } exports.Publisher = Publisher; _a = JSII_RTTI_SYMBOL_1; Publisher[_a] = { fqn: "projen.release.Publisher", version: "0.95.1" }; Publisher.PUBLISH_GIT_TASK_NAME = "publish:git"; function secret(secretName) { return `\${{ secrets.${secretName} }}`; } /** * Options for authorizing requests to a AWS CodeArtifact npm repository. */ var CodeArtifactAuthProvider; (function (CodeArtifactAuthProvider) { /** * Fixed credentials provided via Github secrets. */ CodeArtifactAuthProvider["ACCESS_AND_SECRET_KEY_PAIR"] = "ACCESS_AND_SECRET_KEY_PAIR"; /** * Ephemeral credentials provided via Github's OIDC integration with an IAM role. * See: * https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html * https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services */ CodeArtifactAuthProvider["GITHUB_OIDC"] = "GITHUB_OIDC"; })(CodeArtifactAuthProvider || (exports.CodeArtifactAuthProvider = CodeArtifactAuthProvider = {})); /** * Evaluates if the `registryUrl` is a AWS CodeArtifact registry. * @param registryUrl url of registry * @returns true for AWS CodeArtifact */ function isAwsCodeArtifactRegistry(registryUrl) { return registryUrl && AWS_CODEARTIFACT_REGISTRY_REGEX.test(registryUrl); } /** * Parses info about code artifact domain from given AWS code artifact url * @param url Of code artifact domain * @returns domain, account, and region of code artifact domain */ function awsCodeArtifactInfoFromUrl(url) { const captureRegex = /([a-z0-9-]+)-(.+)\.d\.codeartifact\.(.+)\.amazonaws\.com/; const matches = url?.match(captureRegex) ?? []; const [_, domain, account, region] = matches; return { domain, account, region }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbGVhc2UvcHVibGlzaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUEwdUNBLDhEQUVDOztBQTN1Q0QsNENBQXlDO0FBQ3pDLG1EQUk2QjtBQUM3QiwrREFNbUM7QUFDbkMsNkRBQTZEO0FBRTdELHNEQUE4RTtBQUM5RSx3Q0FBd0Q7QUFFeEQsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDO0FBQ2hDLE1BQU0sd0JBQXdCLEdBQUcsb0JBQW9CLENBQUM7QUFDdEQsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLENBQUM7QUFDdEMsTUFBTSxnQ0FBZ0MsR0FBRyw4QkFBOEIsQ0FBQztBQUN4RSxNQUFNLGdDQUFnQyxHQUFHLDhCQUE4QixDQUFDO0FBQ3hFLE1BQU0sK0JBQStCLEdBQUcsK0JBQStCLENBQUM7QUFDeEUsTUFBTSxnQkFBZ0IsR0FBRztJQUN2QixFQUFFLEVBQUUsRUFBRTtJQUNOLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRTtJQUNqQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUU7SUFDdEMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtDQUN2QyxDQUFDO0FBQ0YsTUFBTSxrQkFBa0IsR0FBRyxVQUFVLENBQUM7QUF5R3RDOzs7O0dBSUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxxQkFBUztJQWdDdEMsWUFBWSxPQUFnQixFQUFFLE9BQXlCO1FBQ3JELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQWhCakIsK0RBQStEO1FBQzlDLGtCQUFhLEdBQXdCLEVBQUUsQ0FBQztRQUV4Qyx5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QVMsTUFBTSxDQUFDLFVBQWtCO0lBQ2hDLE9BQU8sZ0JBQWdCLFVBQVUsS0FBSyxDQUFDO0FBQ3pDLENBQUM7QUFvSkQ7O0dBRUc7QUFDSCxJQUFZLHdCQWFYO0FBYkQsV0FBWSx3QkFBd0I7SUFDbEM7O09BRUc7SUFDSCxxRkFBeUQsQ0FBQTtJQUV6RDs7Ozs7T0FLRztJQUNILHVEQUEyQixDQUFBO0FBQzdCLENBQUMsRUFiVyx3QkFBd0Isd0NBQXhCLHdCQUF3QixRQWFuQztBQXFSRDs7OztHQUlHO0FBQ0gsU0FBZ0IseUJBQXlCLENBQUMsV0FBK0I7SUFDdkUsT0FBTyxXQUFXLElBQUksK0JBQStCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzFFLENBQUM7QUFXRDs7OztHQUlHO0FBQ0gsU0FBUywwQkFBMEIsQ0FBQyxHQUFZO0lBQzlDLE1BQU0sWUFBWSxHQUNoQiwwREFBMEQsQ0FBQztJQUM3RCxNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDO0lBQzdDLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3JDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCcmFuY2hPcHRpb25zIH0gZnJvbSBcIi4vcmVsZWFzZVwiO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudFwiO1xuaW1wb3J0IHtcbiAgQlVJTERfQVJUSUZBQ1RfTkFNRSxcbiAgREVGQVVMVF9HSVRIVUJfQUNUSU9OU19VU0VSLFxuICBQRVJNSVNTSU9OX0JBQ0tVUF9GSUxFLFxufSBmcm9tIFwiLi4vZ2l0aHViL2NvbnN0YW50c1wiO1xuaW1wb3J0IHtcbiAgSm9iLFxuICBKb2JQZXJtaXNzaW9uLFxuICBKb2JQZXJtaXNzaW9ucyxcbiAgSm9iU3RlcCxcbiAgVG9vbHMsXG59IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3dzLW1vZGVsXCI7XG5pbXBvcnQgeyBkZWZhdWx0TnBtVG9rZW4gfSBmcm9tIFwiLi4vamF2YXNjcmlwdC9ub2RlLXBhY2thZ2VcIjtcbmltcG9ydCB7IFByb2plY3QgfSBmcm9tIFwiLi4vcHJvamVjdFwiO1xuaW1wb3J0IHsgR3JvdXBSdW5uZXJPcHRpb25zLCBmaWx0ZXJlZFJ1bnNPbk9wdGlvbnMgfSBmcm9tIFwiLi4vcnVubmVyLW9wdGlvbnNcIjtcbmltcG9ydCB7IENIQU5HRVNfU0lOQ0VfTEFTVF9SRUxFQVNFIH0gZnJvbSBcIi4uL3ZlcnNpb25cIjtcblxuY29uc3QgUFVCTElCX1ZFUlNJT04gPSBcImxhdGVzdFwiO1xuY29uc3QgR0lUSFVCX1BBQ0tBR0VTX1JFR0lTVFJZID0gXCJucG0ucGtnLmdpdGh1Yi5jb21cIjtcbmNvbnN0IEFSVElGQUNUU19ET1dOTE9BRF9ESVIgPSBcImRpc3RcIjtcbmNvbnN0IEdJVEhVQl9QQUNLQUdFU19NQVZFTl9SRVBPU0lUT1JZID0gXCJodHRwczovL21hdmVuLnBrZy5naXRodWIuY29tXCI7XG5jb25zdCBHSVRIVUJfUEFDS0FHRVNfTlVHRVRfUkVQT1NJVE9SWSA9IFwiaHR0cHM6Ly9udWdldC5wa2cuZ2l0aHViLmNvbVwiO1xuY29uc3QgQVdTX0NPREVBUlRJRkFDVF9SRUdJU1RSWV9SRUdFWCA9IC8uY29kZWFydGlmYWN0LiouYW1hem9uYXdzLmNvbS87XG5jb25zdCBQVUJMSUJfVE9PTENIQUlOID0ge1xuICBqczoge30sXG4gIGphdmE6IHsgamF2YTogeyB2ZXJzaW9uOiBcIjExXCIgfSB9LFxuICBweXRob246IHsgcHl0aG9uOiB7IHZlcnNpb246IFwiMy54XCIgfSB9LFxuICBnbzogeyBnbzogeyB2ZXJzaW9uOiBcIl4xLjE4LjBcIiB9IH0sXG4gIGRvdG5ldDogeyBkb3RuZXQ6IHsgdmVyc2lvbjogXCI2LnhcIiB9IH0sXG59O1xuY29uc3QgUFVCTElTSF9KT0JfUFJFRklYID0gXCJyZWxlYXNlX1wiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBQdWJsaXNoZXJgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFB1Ymxpc2hlck9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGpvYiBJRCB0aGF0IHByb2R1Y2VzIHRoZSBidWlsZCBhcnRpZmFjdHMuIEFsbCBwdWJsaXNoIGpvYnMgd2lsbCB0YWtlIGEgZGVwZW5kZW5jeSBvbiB0aGlzIGpvYi5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkSm9iSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogQSBHaXRIdWIgd29ya2Zsb3cgZXhwcmVzc2lvbiB1c2VkIGFzIGEgY29uZGl0aW9uIGZvciBwdWJsaXNoZXJzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGNvbmRpdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgY29uZGl0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYXJ0aWZhY3QgdG8gZG93bmxvYWQgKGUuZy4gYGRpc3RgKS5cbiAgICpcbiAgICogVGhlIGFydGlmYWN0IGlzIGV4cGVjdGVkIHRvIGluY2x1ZGUgYSBzdWJkaXJlY3RvcnkgZm9yIGVhY2ggcmVsZWFzZSB0YXJnZXQ6XG4gICAqIGBnb2AgKEdpdEh1YiksIGBkb3RuZXRgIChOdUdldCksIGBqYXZhYCAoTWF2ZW4pLCBganNgIChucG0pLCBgcHl0aG9uYFxuICAgKi