UNPKG

@cloudsnorkel/cdk-github-runners

Version:

CDK construct to create GitHub Actions self-hosted runners. Creates ephemeral runners on demand. Easy to deploy and highly customizable.

181 lines 22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadOctokitRest = loadOctokitRest; exports.loadOctokitCore = loadOctokitCore; exports.loadOctokitAuthApp = loadOctokitAuthApp; exports.baseUrlFromDomain = baseUrlFromDomain; exports.getOctokit = getOctokit; exports.getAppOctokit = getAppOctokit; exports.getRunner = getRunner; exports.deleteRunner = deleteRunner; exports.redeliver = redeliver; const crypto_1 = require("crypto"); const lambda_helpers_1 = require("./lambda-helpers"); let restModulePromise; let coreModulePromise; let authAppModulePromise; function loadOctokitRest() { return (restModulePromise ?? (restModulePromise = Promise.resolve().then(() => require('@octokit/rest')))); } function loadOctokitCore() { return (coreModulePromise ?? (coreModulePromise = Promise.resolve().then(() => require('@octokit/core')))); } function loadOctokitAuthApp() { return (authAppModulePromise ?? (authAppModulePromise = Promise.resolve().then(() => require('@octokit/auth-app')))); } // ---- Other helpers ---- function baseUrlFromDomain(domain) { if (domain == 'github.com') { return 'https://api.github.com'; } return `https://${domain}/api/v3`; } const octokitCache = new Map(); async function getOctokit(installationId) { if (!process.env.GITHUB_SECRET_ARN || !process.env.GITHUB_PRIVATE_KEY_SECRET_ARN) { throw new Error('Missing environment variables'); } const [{ Octokit }, { createAppAuth }] = await Promise.all([ loadOctokitRest(), loadOctokitAuthApp(), ]); const githubSecrets = await (0, lambda_helpers_1.getSecretJsonValue)(process.env.GITHUB_SECRET_ARN); // Create cache key from installation ID and secrets (hash to avoid exposing sensitive data by accident) const cacheKey = (0, crypto_1.createHash)('sha256').update(`${installationId || 'no-install'}-${githubSecrets.domain}-${githubSecrets.appId}-${githubSecrets.personalAuthToken}`).digest('hex'); const cached = octokitCache.get(cacheKey); if (cached) { try { // Test if the cached octokit is still valid await cached.rest.meta.getOctocat(); console.log({ notice: 'Using cached octokit', }); return { octokit: cached, githubSecrets, }; } catch (e) { console.log({ notice: 'Octokit cache is invalid', error: e, }); octokitCache.delete(cacheKey); } } const baseUrl = baseUrlFromDomain(githubSecrets.domain); let token; if (githubSecrets.personalAuthToken) { token = githubSecrets.personalAuthToken; } else { const privateKey = await (0, lambda_helpers_1.getSecretValue)(process.env.GITHUB_PRIVATE_KEY_SECRET_ARN); const appOctokit = new Octokit({ baseUrl, authStrategy: createAppAuth, auth: { appId: githubSecrets.appId, privateKey: privateKey, }, }); token = (await appOctokit.auth({ type: 'installation', installationId: installationId, })).token; } const octokit = new Octokit({ baseUrl, auth: token, }); // Store in cache octokitCache.set(cacheKey, octokit); return { octokit, githubSecrets, }; } // This function is used to get the Octokit instance for the app itself, not for a specific installation. // With PAT authentication, it returns undefined. async function getAppOctokit() { if (!process.env.GITHUB_SECRET_ARN || !process.env.GITHUB_PRIVATE_KEY_SECRET_ARN) { throw new Error('Missing environment variables'); } const [{ Octokit }, { createAppAuth }] = await Promise.all([ loadOctokitRest(), loadOctokitAuthApp(), ]); const githubSecrets = await (0, lambda_helpers_1.getSecretJsonValue)(process.env.GITHUB_SECRET_ARN); const baseUrl = baseUrlFromDomain(githubSecrets.domain); if (githubSecrets.personalAuthToken || !githubSecrets.appId) { return undefined; } const privateKey = await (0, lambda_helpers_1.getSecretValue)(process.env.GITHUB_PRIVATE_KEY_SECRET_ARN); return new Octokit({ baseUrl, authStrategy: createAppAuth, auth: { appId: githubSecrets.appId, privateKey: privateKey, }, }); } async function getRunner(octokit, runnerLevel, owner, repo, name) { let page = 1; while (true) { let runners; if ((runnerLevel ?? 'repo') === 'repo') { runners = await octokit.rest.actions.listSelfHostedRunnersForRepo({ name: name, page: page, owner: owner, repo: repo, }); } else { runners = await octokit.rest.actions.listSelfHostedRunnersForOrg({ name: name, page: page, org: owner, }); } if (runners.data.runners.length == 0) { return; } for (const runner of runners.data.runners) { // we filter by name in the API call, but still double-check here // this is for backward compatibility with old GHES instances that may not support the name filter if (runner.name == name) { return runner; } } page++; } } async function deleteRunner(octokit, runnerLevel, owner, repo, runnerId) { if ((runnerLevel ?? 'repo') === 'repo') { await octokit.rest.actions.deleteSelfHostedRunnerFromRepo({ owner: owner, repo: repo, runner_id: runnerId, }); } else { await octokit.rest.actions.deleteSelfHostedRunnerFromOrg({ org: owner, runner_id: runnerId, }); } } async function redeliver(octokit, deliveryId) { const response = await octokit.rest.apps.redeliverWebhookDelivery({ delivery_id: deliveryId, }); if (response.status !== 202) { throw new Error(`Failed to redeliver webhook delivery with ID ${deliveryId}`); } console.log({ notice: 'Successfully redelivered webhook delivery', deliveryId, }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWdpdGh1Yi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9sYW1iZGEtZ2l0aHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZUEsMENBRUM7QUFFRCwwQ0FFQztBQUVELGdEQUVDO0FBSUQsOENBS0M7QUFhRCxnQ0F1RUM7QUFJRCxzQ0EyQkM7QUFFRCw4QkFrQ0M7QUFFRCxvQ0FhQztBQUVELDhCQVlDO0FBdE5ELG1DQUFvQztBQUVwQyxxREFBc0U7QUFTdEUsSUFBSSxpQkFBeUQsQ0FBQztBQUM5RCxJQUFJLGlCQUF5RCxDQUFDO0FBQzlELElBQUksb0JBQStELENBQUM7QUFFcEUsU0FBZ0IsZUFBZTtJQUM3QixPQUFPLENBQUMsaUJBQWlCLEtBQWpCLGlCQUFpQixHQUFLLHFDQUFPLGVBQWUsRUFBK0IsRUFBQyxDQUFDO0FBQ3ZGLENBQUM7QUFFRCxTQUFnQixlQUFlO0lBQzdCLE9BQU8sQ0FBQyxpQkFBaUIsS0FBakIsaUJBQWlCLEdBQUsscUNBQU8sZUFBZSxFQUErQixFQUFDLENBQUM7QUFDdkYsQ0FBQztBQUVELFNBQWdCLGtCQUFrQjtJQUNoQyxPQUFPLENBQUMsb0JBQW9CLEtBQXBCLG9CQUFvQixHQUFLLHFDQUFPLG1CQUFtQixFQUFrQyxFQUFDLENBQUM7QUFDakcsQ0FBQztBQUVELDBCQUEwQjtBQUUxQixTQUFnQixpQkFBaUIsQ0FBQyxNQUFjO0lBQzlDLElBQUksTUFBTSxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzNCLE9BQU8sd0JBQXdCLENBQUM7SUFDbEMsQ0FBQztJQUNELE9BQU8sV0FBVyxNQUFNLFNBQVMsQ0FBQztBQUNwQyxDQUFDO0FBV0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7QUFFN0MsS0FBSyxVQUFVLFVBQVUsQ0FBQyxjQUF1QjtJQUN0RCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENB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T0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsNkJBQTZCLENBQUM7WUFDdkQsR0FBRyxFQUFFLEtBQUs7WUFDVixTQUFTLEVBQUUsUUFBUTtTQUNwQixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxTQUFTLENBQUMsT0FBb0IsRUFBRSxVQUFrQjtJQUN0RSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDO1FBQ2hFLFdBQVcsRUFBRSxVQUFVO0tBQ3hCLENBQUMsQ0FBQztJQUVILElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ1YsTUFBTSxFQUFFLDJDQUEyQztRQUNuRCxVQUFVO0tBQ1gsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHR5cGUgeyBPY3Rva2l0IGFzIFJlc3RPY3Rva2l0IH0gZnJvbSAnQG9jdG9raXQvcmVzdCc7XG5pbXBvcnQgeyBnZXRTZWNyZXRKc29uVmFsdWUsIGdldFNlY3JldFZhbHVlIH0gZnJvbSAnLi9sYW1iZGEtaGVscGVycyc7XG5cbi8vIC0tLS0gT2N0b2tpdCBFU00gbG9hZGVyIGhlbHBlcnMgKGlubGluZWQpIC0tLS1cbi8vIE9jdG9raXQgcGFja2FnZXMgYXJlIEVTTSwgYnV0IG91ciBMYW1iZGEgYXNzZXRzIGFyZSBidW5kbGVkIGludG8gQ0pTLlxuLy8gVXNpbmcgZHluYW1pYyBgaW1wb3J0KClgIGhlcmUgbGV0cyBlc2J1aWxkIGluY2x1ZGUgT2N0b2tpdCBpbiB0aGUgYnVuZGxlLlxudHlwZSBPY3Rva2l0UmVzdE1vZHVsZSA9IHR5cGVvZiBpbXBvcnQoJ0BvY3Rva2l0L3Jlc3QnKTtcbnR5cGUgT2N0b2tpdENvcmVNb2R1bGUgPSB0eXBlb2YgaW1wb3J0KCdAb2N0b2tpdC9jb3JlJyk7XG50eXBlIE9jdG9raXRBdXRoQXBwTW9kdWxlID0gdHlwZW9mIGltcG9ydCgnQG9jdG9raXQvYXV0aC1hcHAnKTtcblxubGV0IHJlc3RNb2R1bGVQcm9taXNlOiBQcm9taXNlPE9jdG9raXRSZXN0TW9kdWxlPiB8IHVuZGVmaW5lZDtcbmxldCBjb3JlTW9kdWxlUHJvbWlzZTogUHJvbWlzZTxPY3Rva2l0Q29yZU1vZHVsZT4gfCB1bmRlZmluZWQ7XG5sZXQgYXV0aEFwcE1vZHVsZVByb21pc2U6IFByb21pc2U8T2N0b2tpdEF1dGhBcHBNb2R1bGU+IHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgZnVuY3Rpb24gbG9hZE9jdG9raXRSZXN0KCk6IFByb21pc2U8T2N0b2tpdFJlc3RNb2R1bGU+IHtcbiAgcmV0dXJuIChyZXN0TW9kdWxlUHJvbWlzZSA/Pz0gaW1wb3J0KCdAb2N0b2tpdC9yZXN0JykgYXMgUHJvbWlzZTxPY3Rva2l0UmVzdE1vZHVsZT4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZE9jdG9raXRDb3JlKCk6IFByb21pc2U8T2N0b2tpdENvcmVNb2R1bGU+IHtcbiAgcmV0dXJuIChjb3JlTW9kdWxlUHJvbWlzZSA/Pz0gaW1wb3J0KCdAb2N0b2tpdC9jb3JlJykgYXMgUHJvbWlzZTxPY3Rva2l0Q29yZU1vZHVsZT4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZE9jdG9raXRBdXRoQXBwKCk6IFByb21pc2U8T2N0b2tpdEF1dGhBcHBNb2R1bGU+IHtcbiAgcmV0dXJuIChhdXRoQXBwTW9kdWxlUHJvbWlzZSA/Pz0gaW1wb3J0KCdAb2N0b2tpdC9hdXRoLWFwcCcpIGFzIFByb21pc2U8T2N0b2tpdEF1dGhBcHBNb2R1bGU+KTtcbn1cblxuLy8gLS0tLSBPdGhlciBoZWxwZXJzIC0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIGJhc2VVcmxGcm9tRG9tYWluKGRvbWFpbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGRvbWFpbiA9PSAnZ2l0aHViLmNvbScpIHtcbiAgICByZXR1cm4gJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20nO1xuICB9XG4gIHJldHVybiBgaHR0cHM6Ly8ke2RvbWFpbn0vYXBpL3YzYDtcbn1cblxudHlwZSBSdW5uZXJMZXZlbCA9ICdyZXBvJyB8ICdvcmcnIHwgdW5kZWZpbmVkOyAvLyB1bmRlZmluZWQgaXMgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGFuZCBzaG91bGQgYmUgdHJlYXRlZCBhcyAncmVwbydcblxuZXhwb3J0IGludGVyZmFjZSBHaXRIdWJTZWNyZXRzIHtcbiAgZG9tYWluOiBzdHJpbmc7XG4gIGFwcElkOiBudW1iZXI7XG4gIHBlcnNvbmFsQXV0aFRva2VuOiBzdHJpbmc7XG4gIHJ1bm5lckxldmVsOiBSdW5uZXJMZXZlbDtcbn1cblxuY29uc3Qgb2N0b2tpdENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFJlc3RPY3Rva2l0PigpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0T2N0b2tpdChpbnN0YWxsYXRpb25JZD86IG51bWJlcik6IFByb21pc2U8eyBvY3Rva2l0OiBSZXN0T2N0b2tpdDsgZ2l0aHViU2VjcmV0czogR2l0SHViU2VjcmV0cyB9PiB7XG4gIGlmICghcHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4gfHwgIXByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGVudmlyb25tZW50IHZhcmlhYmxlcycpO1xuICB9XG5cbiAgY29uc3QgW3sgT2N0b2tpdCB9LCB7IGNyZWF0ZUFwcEF1dGggfV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgbG9hZE9jdG9raXRSZXN0KCksXG4gICAgbG9hZE9jdG9raXRBdXRoQXBwKCksXG4gIF0pO1xuXG4gIGNvbnN0IGdpdGh1YlNlY3JldHM6IEdpdEh1YlNlY3JldHMgPSBhd2FpdCBnZXRTZWNyZXRKc29uVmFsdWUocHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4pO1xuXG4gIC8vIENyZWF0ZSBjYWNoZSBrZXkgZnJvbSBpbnN0YWxsYXRpb24gSUQgYW5kIHNlY3JldHMgKGhhc2ggdG8gYXZvaWQgZXhwb3Npbmcgc2Vuc2l0aXZlIGRhdGEgYnkgYWNjaWRlbnQpXG4gIGNvbnN0IGNhY2hlS2V5ID0gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGAke2luc3RhbGxhdGlvbklkIHx8ICduby1pbnN0YWxsJ30tJHtnaXRodWJTZWNyZXRzLmRvbWFpbn0tJHtnaXRodWJTZWNyZXRzLmFwcElkfS0ke2dpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW59YCkuZGlnZXN0KCdoZXgnKTtcblxuICBjb25zdCBjYWNoZWQgPSBvY3Rva2l0Q2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgaWYgKGNhY2hlZCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBUZXN0IGlmIHRoZSBjYWNoZWQgb2N0b2tpdCBpcyBzdGlsbCB2YWxpZFxuICAgICAgYXdhaXQgY2FjaGVkLnJlc3QubWV0YS5nZXRPY3RvY2F0KCk7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ1VzaW5nIGNhY2hlZCBvY3Rva2l0JyxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb2N0b2tpdDogY2FjaGVkLFxuICAgICAgICBnaXRodWJTZWNyZXRzLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ09jdG9raXQgY2FjaGUgaXMgaW52YWxpZCcsXG4gICAgICAgIGVycm9yOiBlLFxuICAgICAgfSk7XG4gICAgICBvY3Rva2l0Q2FjaGUuZGVsZXRlKGNhY2hlS2V5KTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBiYXNlVXJsID0gYmFzZVVybEZyb21Eb21haW4oZ2l0aHViU2VjcmV0cy5kb21haW4pO1xuXG4gIGxldCB0b2tlbjtcbiAgaWYgKGdpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW4pIHtcbiAgICB0b2tlbiA9IGdpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW47XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgcHJpdmF0ZUtleSA9IGF3YWl0IGdldFNlY3JldFZhbHVlKHByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKTtcblxuICAgIGNvbnN0IGFwcE9jdG9raXQgPSBuZXcgT2N0b2tpdCh7XG4gICAgICBiYXNlVXJsLFxuICAgICAgYXV0aFN0cmF0ZWd5OiBjcmVhdGVBcHBBdXRoLFxuICAgICAgYXV0aDoge1xuICAgICAgICBhcHBJZDogZ2l0aHViU2VjcmV0cy5hcHBJZCxcbiAgICAgICAgcHJpdmF0ZUtleTogcHJpdmF0ZUtleSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0b2tlbiA9IChhd2FpdCBhcHBPY3Rva2l0LmF1dGgoe1xuICAgICAgdHlwZTogJ2luc3RhbGxhdGlvbicsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5zdGFsbGF0aW9uSWQsXG4gICAgfSkgYXMgYW55KS50b2tlbjtcbiAgfVxuXG4gIGNvbnN0IG9jdG9raXQgPSBuZXcgT2N0b2tpdCh7XG4gICAgYmFzZVVybCxcbiAgICBhdXRoOiB0b2tlbixcbiAgfSk7XG5cbiAgLy8gU3RvcmUgaW4gY2FjaGVcbiAgb2N0b2tpdENhY2hlLnNldChjYWNoZUtleSwgb2N0b2tpdCk7XG5cbiAgcmV0dXJuIHtcbiAgICBvY3Rva2l0LFxuICAgIGdpdGh1YlNlY3JldHMsXG4gIH07XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBnZXQgdGhlIE9jdG9raXQgaW5zdGFuY2UgZm9yIHRoZSBhcHAgaXRzZWxmLCBub3QgZm9yIGEgc3BlY2lmaWMgaW5zdGFsbGF0aW9uLlxuLy8gV2l0aCBQQVQgYXV0aGVudGljYXRpb24sIGl0IHJldHVybnMgdW5kZWZpbmVkLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFwcE9jdG9raXQoKSB7XG4gIGlmICghcHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4gfHwgIXByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGVudmlyb25tZW50IHZhcmlhYmxlcycpO1xuICB9XG5cbiAgY29uc3QgW3sgT2N0b2tpdCB9LCB7IGNyZWF0ZUFwcEF1dGggfV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgbG9hZE9jdG9raXRSZXN0KCksXG4gICAgbG9hZE9jdG9raXRBdXRoQXBwKCksXG4gIF0pO1xuXG4gIGNvbnN0IGdpdGh1YlNlY3JldHM6IEdpdEh1YlNlY3JldHMgPSBhd2FpdCBnZXRTZWNyZXRKc29uVmFsdWUocHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4pO1xuICBjb25zdCBiYXNlVXJsID0gYmFzZVVybEZyb21Eb21haW4oZ2l0aHViU2VjcmV0cy5kb21haW4pO1xuXG4gIGlmIChnaXRodWJTZWNyZXRzLnBlcnNvbmFsQXV0aFRva2VuIHx8ICFnaXRodWJTZWNyZXRzLmFwcElkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IHByaXZhdGVLZXkgPSBhd2FpdCBnZXRTZWNyZXRWYWx1ZShwcm9jZXNzLmVudi5HSVRIVUJfUFJJVkFURV9LRVlfU0VDUkVUX0FSTik7XG5cbiAgcmV0dXJuIG5ldyBPY3Rva2l0KHtcbiAgICBiYXNlVXJsLFxuICAgIGF1dGhTdHJhdGVneTogY3JlYXRlQXBwQXV0aCxcbiAgICBhdXRoOiB7XG4gICAgICBhcHBJZDogZ2l0aHViU2VjcmV0cy5hcHBJZCxcbiAgICAgIHByaXZhdGVLZXk6IHByaXZhdGVLZXksXG4gICAgfSxcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSdW5uZXIob2N0b2tpdDogUmVzdE9jdG9raXQsIHJ1bm5lckxldmVsOiBSdW5uZXJMZXZlbCwgb3duZXI6IHN0cmluZywgcmVwbzogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgbGV0IHBhZ2UgPSAxO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIGxldCBydW5uZXJzO1xuXG4gICAgaWYgKChydW5uZXJMZXZlbCA/PyAncmVwbycpID09PSAncmVwbycpIHtcbiAgICAgIHJ1bm5lcnMgPSBhd2FpdCBvY3Rva2l0LnJlc3QuYWN0aW9ucy5saXN0U2VsZkhvc3RlZFJ1bm5lcnNGb3JSZXBvKHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgcGFnZTogcGFnZSxcbiAgICAgICAgb3duZXI6IG93bmVyLFxuICAgICAgICByZXBvOiByZXBvLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJ1bm5lcnMgPSBhd2FpdCBvY3Rva2l0LnJlc3QuYWN0aW9ucy5saXN0U2VsZkhvc3RlZFJ1bm5lcnNGb3JPcmcoe1xuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBwYWdlOiBwYWdlLFxuICAgICAgICBvcmc6IG93bmVyLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHJ1bm5lcnMuZGF0YS5ydW5uZXJzLmxlbmd0aCA9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBydW5uZXIgb2YgcnVubmVycy5kYXRhLnJ1bm5lcnMpIHtcbiAgICAgIC8vIHdlIGZpbHRlciBieSBuYW1lIGluIHRoZSBBUEkgY2FsbCwgYnV0IHN0aWxsIGRvdWJsZS1jaGVjayBoZXJlXG4gICAgICAvLyB0aGlzIGlzIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdpdGggb2xkIEdIRVMgaW5zdGFuY2VzIHRoYXQgbWF5IG5vdCBzdXBwb3J0IHRoZSBuYW1lIGZpbHRlclxuICAgICAgaWYgKHJ1bm5lci5uYW1lID09IG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHJ1bm5lcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwYWdlKys7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZVJ1bm5lcihvY3Rva2l0OiBSZXN0T2N0b2tpdCwgcnVubmVyTGV2ZWw6IFJ1bm5lckxldmVsLCBvd25lcjogc3RyaW5nLCByZXBvOiBzdHJpbmcsIHJ1bm5lcklkOiBudW1iZXIpIHtcbiAgaWYgKChydW5uZXJMZXZlbCA/PyAncmVwbycpID09PSAncmVwbycpIHtcbiAgICBhd2FpdCBvY3Rva2l0LnJlc3QuYWN0aW9ucy5kZWxldGVTZWxmSG9zdGVkUnVubmVyRnJvbVJlcG8oe1xuICAgICAgb3duZXI6IG93bmVyLFxuICAgICAgcmVwbzogcmVwbyxcbiAgICAgIHJ1bm5lcl9pZDogcnVubmVySWQsXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMuZGVsZXRlU2VsZkhvc3RlZFJ1bm5lckZyb21Pcmcoe1xuICAgICAgb3JnOiBvd25lcixcbiAgICAgIHJ1bm5lcl9pZDogcnVubmVySWQsXG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlZGVsaXZlcihvY3Rva2l0OiBSZXN0T2N0b2tpdCwgZGVsaXZlcnlJZDogbnVtYmVyKSB7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFwcHMucmVkZWxpdmVyV2ViaG9va0RlbGl2ZXJ5KHtcbiAgICBkZWxpdmVyeV9pZDogZGVsaXZlcnlJZCxcbiAgfSk7XG5cbiAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVkZWxpdmVyIHdlYmhvb2sgZGVsaXZlcnkgd2l0aCBJRCAke2RlbGl2ZXJ5SWR9YCk7XG4gIH1cbiAgY29uc29sZS5sb2coe1xuICAgIG5vdGljZTogJ1N1Y2Nlc3NmdWxseSByZWRlbGl2ZXJlZCB3ZWJob29rIGRlbGl2ZXJ5JyxcbiAgICBkZWxpdmVyeUlkLFxuICB9KTtcbn1cbiJdfQ==