@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
JavaScript
;
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==