UNPKG

projen

Version:

CDK for software projects

585 lines • 107 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), environment: options.githubEnvironment ?? branchOptions.environment, run: this.githubReleaseCommand(options, branchOptions), workflowEnv: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}", }, }; }); } /** * 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 ?? [], environment: options.githubEnvironment ?? branchOptions.environment, 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 ?? [], environment: options.githubEnvironment ?? branchOptions.environment, 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 ?? [], environment: options.githubEnvironment ?? branchOptions.environment, 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 ?? [], environment: options.githubEnvironment ?? branchOptions.environment, 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 ?? [], environment: options.githubEnvironment ?? branchOptions.environment, 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]: { ...(opts.environment ? { environment: opts.environment } : {}), 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.2" }; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbGVhc2UvcHVibGlzaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFtd0NBLDhEQUVDOztBQXB3Q0QsNENBQXlDO0FBQ3pDLG1EQUk2QjtBQUM3QiwrREFNbUM7QUFDbkMsNkRBQTZEO0FBRTdELHNEQUE4RTtBQUM5RSx3Q0FBd0Q7QUFFeEQsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDO0FBQ2hDLE1BQU0sd0JBQXdCLEdBQUcsb0JBQW9CLENBQUM7QUFDdEQsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLENBQUM7QUFDdEMsTUFBTSxnQ0FBZ0MsR0FBRyw4QkFBOEIsQ0FBQztBQUN4RSxNQUFNLGdDQUFnQyxHQUFHLDhCQUE4QixDQUFDO0FBQ3hFLE1BQU0sK0JBQStCLEdBQUcsK0JBQStCLENBQUM7QUFDeEUsTUFBTSxnQkFBZ0IsR0FBRztJQUN2QixFQUFFLEVBQUUsRUFBRTtJQUNOLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRTtJQUNqQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUU7SUFDdEMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFO0lBQ2xDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtDQUN2QyxDQUFDO0FBQ0YsTUFBTSxrQkFBa0IsR0FBRyxVQUFVLENBQUM7QUF5R3RDOzs7O0dBSUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxxQkFBUztJQWdDdEMsWUFBWSxPQUFnQixFQUFFLE9BQXlCO1FBQ3JELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQWhCakIsK0RBQStEO1FBQzlDLGtCQUFhLEdBQXdCLEVBQUUsQ0FBQztRQUV4Qyx5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TSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQztJQUM3QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQnJhbmNoT3B0aW9ucyB9IGZyb20gXCIuL3JlbGVhc2VcIjtcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnRcIjtcbmltcG9ydCB7XG4gIEJVSUxEX0FSVElGQUNUX05BTUUsXG4gIERFRkFVTFRfR0lUSFVCX0FDVElPTlNfVVNFUixcbiAgUEVSTUlTU0lPTl9CQUNLVVBfRklMRSxcbn0gZnJvbSBcIi4uL2dpdGh1Yi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIEpvYixcbiAgSm9iUGVybWlzc2lvbixcbiAgSm9iUGVybWlzc2lvbnMsXG4gIEpvYlN0ZXAsXG4gIFRvb2xzLFxufSBmcm9tIFwiLi4vZ2l0aHViL3dvcmtmbG93cy1tb2RlbFwiO1xuaW1wb3J0IHsgZGVmYXVsdE5wbVRva2VuIH0gZnJvbSBcIi4uL2phdmFzY3JpcHQvbm9kZS1wYWNrYWdlXCI7XG5pbXBvcnQgeyBQcm9qZWN0IH0gZnJvbSBcIi4uL3Byb2plY3RcIjtcbmltcG9ydCB7IEdyb3VwUnVubmVyT3B0aW9ucywgZmlsdGVyZWRSdW5zT25PcHRpb25zIH0gZnJvbSBcIi4uL3J1bm5lci1vcHRpb25zXCI7XG5pbXBvcnQgeyBDSEFOR0VTX1NJTkNFX0xBU1RfUkVMRUFTRSB9IGZyb20gXCIuLi92ZXJzaW9uXCI7XG5cbmNvbnN0IFBVQkxJQl9WRVJTSU9OID0gXCJsYXRlc3RcIjtcbmNvbnN0IEdJVEhVQl9QQUNLQUdFU19SRUdJU1RSWSA9IFwibnBtLnBrZy5naXRodWIuY29tXCI7XG5jb25zdCBBUlRJRkFDVFNfRE9XTkxPQURfRElSID0gXCJkaXN0XCI7XG5jb25zdCBHSVRIVUJfUEFDS0FHRVNfTUFWRU5fUkVQT1NJVE9SWSA9IFwiaHR0cHM6Ly9tYXZlbi5wa2cuZ2l0aHViLmNvbVwiO1xuY29uc3QgR0lUSFVCX1BBQ0tBR0VTX05VR0VUX1JFUE9TSVRPUlkgPSBcImh0dHBzOi8vbnVnZXQucGtnLmdpdGh1Yi5jb21cIjtcbmNvbnN0IEFXU19DT0RFQVJUSUZBQ1RfUkVHSVNUUllfUkVHRVggPSAvLmNvZGVhcnRpZmFjdC4qLmFtYXpvbmF3cy5jb20vO1xuY29uc3QgUFVCTElCX1RPT0xD