@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.
182 lines • 22.4 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({
// waiting for new octokit -- https://github.com/octokit/request.js/issues/797#issuecomment-3953274583
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: String(deliveryId),
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWdpdGh1Yi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9sYW1iZGEtZ2l0aHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZUEsMENBRUM7QUFFRCwwQ0FFQztBQUVELGdEQUVDO0FBSUQsOENBS0M7QUFhRCxnQ0F1RUM7QUFJRCxzQ0EyQkM7QUFFRCw4QkFrQ0M7QUFFRCxvQ0FhQztBQUVELDhCQWFDO0FBdk5ELG1DQUFvQztBQUVwQyxxREFBc0U7QUFTdEUsSUFBSSxpQkFBeUQsQ0FBQztBQUM5RCxJQUFJLGlCQUF5RCxDQUFDO0FBQzlELElBQUksb0JBQStELENBQUM7QUFFcEUsU0FBZ0IsZUFBZTtJQUM3QixPQUFPLENBQUMsaUJBQWlCLEtBQWpCLGlCQUFpQixHQUFLLHFDQUFPLGVBQWUsRUFBK0IsRUFBQyxDQUFDO0FBQ3ZGLENBQUM7QUFFRCxTQUFnQixlQUFlO0lBQzdCLE9BQU8sQ0FBQyxpQkFBaUIsS0FBakIsaUJBQWlCLEdBQUsscUNBQU8sZUFBZSxFQUErQixFQUFDLENBQUM7QUFDdkYsQ0FBQztBQUVELFNBQWdCLGtCQUFrQjtJQUNoQyxPQUFPLENBQUMsb0JBQW9CLEtBQXBCLG9CQUFvQixHQUFLLHFDQUFPLG1CQUFtQixFQUFrQyxFQUFDLENBQUM7QUFDakcsQ0FBQztBQUVELDBCQUEwQjtBQUUxQixTQUFnQixpQkFBaUIsQ0FBQyxNQUFjO0lBQzlDLElBQUksTUFBTSxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzNCLE9BQU8sd0JBQXdCLENBQUM7SUFDbEMsQ0FBQztJQUNELE9BQU8sV0FBVyxNQUFNLFNBQVMsQ0FBQztBQUNwQyxDQUFDO0FBV0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7QUFFN0MsS0FBSyxVQUFVLFVBQVUsQ0FBQyxjQUF1QjtJQUN0RCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENB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T0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsNkJBQTZCLENBQUM7WUFDdkQsR0FBRyxFQUFFLEtBQUs7WUFDVixTQUFTLEVBQUUsUUFBUTtTQUNwQixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxTQUFTLENBQUMsT0FBb0IsRUFBRSxVQUFrQjtJQUN0RSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDO1FBQ2hFLHNHQUFzRztRQUN0RyxXQUFXLEVBQUUsVUFBK0I7S0FDN0MsQ0FBQyxDQUFDO0lBRUgsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDVixNQUFNLEVBQUUsMkNBQTJDO1FBQ25ELFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDO0tBQy9CLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB0eXBlIHsgT2N0b2tpdCBhcyBSZXN0T2N0b2tpdCB9IGZyb20gJ0BvY3Rva2l0L3Jlc3QnO1xuaW1wb3J0IHsgZ2V0U2VjcmV0SnNvblZhbHVlLCBnZXRTZWNyZXRWYWx1ZSB9IGZyb20gJy4vbGFtYmRhLWhlbHBlcnMnO1xuXG4vLyAtLS0tIE9jdG9raXQgRVNNIGxvYWRlciBoZWxwZXJzIChpbmxpbmVkKSAtLS0tXG4vLyBPY3Rva2l0IHBhY2thZ2VzIGFyZSBFU00sIGJ1dCBvdXIgTGFtYmRhIGFzc2V0cyBhcmUgYnVuZGxlZCBpbnRvIENKUy5cbi8vIFVzaW5nIGR5bmFtaWMgYGltcG9ydCgpYCBoZXJlIGxldHMgZXNidWlsZCBpbmNsdWRlIE9jdG9raXQgaW4gdGhlIGJ1bmRsZS5cbnR5cGUgT2N0b2tpdFJlc3RNb2R1bGUgPSB0eXBlb2YgaW1wb3J0KCdAb2N0b2tpdC9yZXN0Jyk7XG50eXBlIE9jdG9raXRDb3JlTW9kdWxlID0gdHlwZW9mIGltcG9ydCgnQG9jdG9raXQvY29yZScpO1xudHlwZSBPY3Rva2l0QXV0aEFwcE1vZHVsZSA9IHR5cGVvZiBpbXBvcnQoJ0BvY3Rva2l0L2F1dGgtYXBwJyk7XG5cbmxldCByZXN0TW9kdWxlUHJvbWlzZTogUHJvbWlzZTxPY3Rva2l0UmVzdE1vZHVsZT4gfCB1bmRlZmluZWQ7XG5sZXQgY29yZU1vZHVsZVByb21pc2U6IFByb21pc2U8T2N0b2tpdENvcmVNb2R1bGU+IHwgdW5kZWZpbmVkO1xubGV0IGF1dGhBcHBNb2R1bGVQcm9taXNlOiBQcm9taXNlPE9jdG9raXRBdXRoQXBwTW9kdWxlPiB8IHVuZGVmaW5lZDtcblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRPY3Rva2l0UmVzdCgpOiBQcm9taXNlPE9jdG9raXRSZXN0TW9kdWxlPiB7XG4gIHJldHVybiAocmVzdE1vZHVsZVByb21pc2UgPz89IGltcG9ydCgnQG9jdG9raXQvcmVzdCcpIGFzIFByb21pc2U8T2N0b2tpdFJlc3RNb2R1bGU+KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRPY3Rva2l0Q29yZSgpOiBQcm9taXNlPE9jdG9raXRDb3JlTW9kdWxlPiB7XG4gIHJldHVybiAoY29yZU1vZHVsZVByb21pc2UgPz89IGltcG9ydCgnQG9jdG9raXQvY29yZScpIGFzIFByb21pc2U8T2N0b2tpdENvcmVNb2R1bGU+KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRPY3Rva2l0QXV0aEFwcCgpOiBQcm9taXNlPE9jdG9raXRBdXRoQXBwTW9kdWxlPiB7XG4gIHJldHVybiAoYXV0aEFwcE1vZHVsZVByb21pc2UgPz89IGltcG9ydCgnQG9jdG9raXQvYXV0aC1hcHAnKSBhcyBQcm9taXNlPE9jdG9raXRBdXRoQXBwTW9kdWxlPik7XG59XG5cbi8vIC0tLS0gT3RoZXIgaGVscGVycyAtLS0tXG5cbmV4cG9ydCBmdW5jdGlvbiBiYXNlVXJsRnJvbURvbWFpbihkb21haW46IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChkb21haW4gPT0gJ2dpdGh1Yi5jb20nKSB7XG4gICAgcmV0dXJuICdodHRwczovL2FwaS5naXRodWIuY29tJztcbiAgfVxuICByZXR1cm4gYGh0dHBzOi8vJHtkb21haW59L2FwaS92M2A7XG59XG5cbnR5cGUgUnVubmVyTGV2ZWwgPSAncmVwbycgfCAnb3JnJyB8IHVuZGVmaW5lZDsgLy8gdW5kZWZpbmVkIGlzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBhbmQgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgJ3JlcG8nXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0SHViU2VjcmV0cyB7XG4gIGRvbWFpbjogc3RyaW5nO1xuICBhcHBJZDogbnVtYmVyO1xuICBwZXJzb25hbEF1dGhUb2tlbjogc3RyaW5nO1xuICBydW5uZXJMZXZlbDogUnVubmVyTGV2ZWw7XG59XG5cbmNvbnN0IG9jdG9raXRDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBSZXN0T2N0b2tpdD4oKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldE9jdG9raXQoaW5zdGFsbGF0aW9uSWQ/OiBudW1iZXIpOiBQcm9taXNlPHsgb2N0b2tpdDogUmVzdE9jdG9raXQ7IGdpdGh1YlNlY3JldHM6IEdpdEh1YlNlY3JldHMgfT4ge1xuICBpZiAoIXByb2Nlc3MuZW52LkdJVEhVQl9TRUNSRVRfQVJOIHx8ICFwcm9jZXNzLmVudi5HSVRIVUJfUFJJVkFURV9LRVlfU0VDUkVUX0FSTikge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBlbnZpcm9ubWVudCB2YXJpYWJsZXMnKTtcbiAgfVxuXG4gIGNvbnN0IFt7IE9jdG9raXQgfSwgeyBjcmVhdGVBcHBBdXRoIH1dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGxvYWRPY3Rva2l0UmVzdCgpLFxuICAgIGxvYWRPY3Rva2l0QXV0aEFwcCgpLFxuICBdKTtcblxuICBjb25zdCBnaXRodWJTZWNyZXRzOiBHaXRIdWJTZWNyZXRzID0gYXdhaXQgZ2V0U2VjcmV0SnNvblZhbHVlKHByb2Nlc3MuZW52LkdJVEhVQl9TRUNSRVRfQVJOKTtcblxuICAvLyBDcmVhdGUgY2FjaGUga2V5IGZyb20gaW5zdGFsbGF0aW9uIElEIGFuZCBzZWNyZXRzIChoYXNoIHRvIGF2b2lkIGV4cG9zaW5nIHNlbnNpdGl2ZSBkYXRhIGJ5IGFjY2lkZW50KVxuICBjb25zdCBjYWNoZUtleSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShgJHtpbnN0YWxsYXRpb25JZCB8fCAnbm8taW5zdGFsbCd9LSR7Z2l0aHViU2VjcmV0cy5kb21haW59LSR7Z2l0aHViU2VjcmV0cy5hcHBJZH0tJHtnaXRodWJTZWNyZXRzLnBlcnNvbmFsQXV0aFRva2VufWApLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgY29uc3QgY2FjaGVkID0gb2N0b2tpdENhY2hlLmdldChjYWNoZUtleSk7XG4gIGlmIChjYWNoZWQpIHtcbiAgICB0cnkge1xuICAgICAgLy8gVGVzdCBpZiB0aGUgY2FjaGVkIG9jdG9raXQgaXMgc3RpbGwgdmFsaWRcbiAgICAgIGF3YWl0IGNhY2hlZC5yZXN0Lm1ldGEuZ2V0T2N0b2NhdCgpO1xuICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICBub3RpY2U6ICdVc2luZyBjYWNoZWQgb2N0b2tpdCcsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9jdG9raXQ6IGNhY2hlZCxcbiAgICAgICAgZ2l0aHViU2VjcmV0cyxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICBub3RpY2U6ICdPY3Rva2l0IGNhY2hlIGlzIGludmFsaWQnLFxuICAgICAgICBlcnJvcjogZSxcbiAgICAgIH0pO1xuICAgICAgb2N0b2tpdENhY2hlLmRlbGV0ZShjYWNoZUtleSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYmFzZVVybCA9IGJhc2VVcmxGcm9tRG9tYWluKGdpdGh1YlNlY3JldHMuZG9tYWluKTtcblxuICBsZXQgdG9rZW47XG4gIGlmIChnaXRodWJTZWNyZXRzLnBlcnNvbmFsQXV0aFRva2VuKSB7XG4gICAgdG9rZW4gPSBnaXRodWJTZWNyZXRzLnBlcnNvbmFsQXV0aFRva2VuO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHByaXZhdGVLZXkgPSBhd2FpdCBnZXRTZWNyZXRWYWx1ZShwcm9jZXNzLmVudi5HSVRIVUJfUFJJVkFURV9LRVlfU0VDUkVUX0FSTik7XG5cbiAgICBjb25zdCBhcHBPY3Rva2l0ID0gbmV3IE9jdG9raXQoe1xuICAgICAgYmFzZVVybCxcbiAgICAgIGF1dGhTdHJhdGVneTogY3JlYXRlQXBwQXV0aCxcbiAgICAgIGF1dGg6IHtcbiAgICAgICAgYXBwSWQ6IGdpdGh1YlNlY3JldHMuYXBwSWQsXG4gICAgICAgIHByaXZhdGVLZXk6IHByaXZhdGVLZXksXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdG9rZW4gPSAoYXdhaXQgYXBwT2N0b2tpdC5hdXRoKHtcbiAgICAgIHR5cGU6ICdpbnN0YWxsYXRpb24nLFxuICAgICAgaW5zdGFsbGF0aW9uSWQ6IGluc3RhbGxhdGlvbklkLFxuICAgIH0pIGFzIGFueSkudG9rZW47XG4gIH1cblxuICBjb25zdCBvY3Rva2l0ID0gbmV3IE9jdG9raXQoe1xuICAgIGJhc2VVcmwsXG4gICAgYXV0aDogdG9rZW4sXG4gIH0pO1xuXG4gIC8vIFN0b3JlIGluIGNhY2hlXG4gIG9jdG9raXRDYWNoZS5zZXQoY2FjaGVLZXksIG9jdG9raXQpO1xuXG4gIHJldHVybiB7XG4gICAgb2N0b2tpdCxcbiAgICBnaXRodWJTZWNyZXRzLFxuICB9O1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgdG8gZ2V0IHRoZSBPY3Rva2l0IGluc3RhbmNlIGZvciB0aGUgYXBwIGl0c2VsZiwgbm90IGZvciBhIHNwZWNpZmljIGluc3RhbGxhdGlvbi5cbi8vIFdpdGggUEFUIGF1dGhlbnRpY2F0aW9uLCBpdCByZXR1cm5zIHVuZGVmaW5lZC5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRBcHBPY3Rva2l0KCkge1xuICBpZiAoIXByb2Nlc3MuZW52LkdJVEhVQl9TRUNSRVRfQVJOIHx8ICFwcm9jZXNzLmVudi5HSVRIVUJfUFJJVkFURV9LRVlfU0VDUkVUX0FSTikge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBlbnZpcm9ubWVudCB2YXJpYWJsZXMnKTtcbiAgfVxuXG4gIGNvbnN0IFt7IE9jdG9raXQgfSwgeyBjcmVhdGVBcHBBdXRoIH1dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGxvYWRPY3Rva2l0UmVzdCgpLFxuICAgIGxvYWRPY3Rva2l0QXV0aEFwcCgpLFxuICBdKTtcblxuICBjb25zdCBnaXRodWJTZWNyZXRzOiBHaXRIdWJTZWNyZXRzID0gYXdhaXQgZ2V0U2VjcmV0SnNvblZhbHVlKHByb2Nlc3MuZW52LkdJVEhVQl9TRUNSRVRfQVJOKTtcbiAgY29uc3QgYmFzZVVybCA9IGJhc2VVcmxGcm9tRG9tYWluKGdpdGh1YlNlY3JldHMuZG9tYWluKTtcblxuICBpZiAoZ2l0aHViU2VjcmV0cy5wZXJzb25hbEF1dGhUb2tlbiB8fCAhZ2l0aHViU2VjcmV0cy5hcHBJZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBwcml2YXRlS2V5ID0gYXdhaXQgZ2V0U2VjcmV0VmFsdWUocHJvY2Vzcy5lbnYuR0lUSFVCX1BSSVZBVEVfS0VZX1NFQ1JFVF9BUk4pO1xuXG4gIHJldHVybiBuZXcgT2N0b2tpdCh7XG4gICAgYmFzZVVybCxcbiAgICBhdXRoU3RyYXRlZ3k6IGNyZWF0ZUFwcEF1dGgsXG4gICAgYXV0aDoge1xuICAgICAgYXBwSWQ6IGdpdGh1YlNlY3JldHMuYXBwSWQsXG4gICAgICBwcml2YXRlS2V5OiBwcml2YXRlS2V5LFxuICAgIH0sXG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UnVubmVyKG9jdG9raXQ6IFJlc3RPY3Rva2l0LCBydW5uZXJMZXZlbDogUnVubmVyTGV2ZWwsIG93bmVyOiBzdHJpbmcsIHJlcG86IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gIGxldCBwYWdlID0gMTtcbiAgd2hpbGUgKHRydWUpIHtcbiAgICBsZXQgcnVubmVycztcblxuICAgIGlmICgocnVubmVyTGV2ZWwgPz8gJ3JlcG8nKSA9PT0gJ3JlcG8nKSB7XG4gICAgICBydW5uZXJzID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMubGlzdFNlbGZIb3N0ZWRSdW5uZXJzRm9yUmVwbyh7XG4gICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIHBhZ2U6IHBhZ2UsXG4gICAgICAgIG93bmVyOiBvd25lcixcbiAgICAgICAgcmVwbzogcmVwbyxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBydW5uZXJzID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMubGlzdFNlbGZIb3N0ZWRSdW5uZXJzRm9yT3JnKHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgcGFnZTogcGFnZSxcbiAgICAgICAgb3JnOiBvd25lcixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChydW5uZXJzLmRhdGEucnVubmVycy5sZW5ndGggPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcnVubmVyIG9mIHJ1bm5lcnMuZGF0YS5ydW5uZXJzKSB7XG4gICAgICAvLyB3ZSBmaWx0ZXIgYnkgbmFtZSBpbiB0aGUgQVBJIGNhbGwsIGJ1dCBzdGlsbCBkb3VibGUtY2hlY2sgaGVyZVxuICAgICAgLy8gdGhpcyBpcyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSB3aXRoIG9sZCBHSEVTIGluc3RhbmNlcyB0aGF0IG1heSBub3Qgc3VwcG9ydCB0aGUgbmFtZSBmaWx0ZXJcbiAgICAgIGlmIChydW5uZXIubmFtZSA9PSBuYW1lKSB7XG4gICAgICAgIHJldHVybiBydW5uZXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcGFnZSsrO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVSdW5uZXIob2N0b2tpdDogUmVzdE9jdG9raXQsIHJ1bm5lckxldmVsOiBSdW5uZXJMZXZlbCwgb3duZXI6IHN0cmluZywgcmVwbzogc3RyaW5nLCBydW5uZXJJZDogbnVtYmVyKSB7XG4gIGlmICgocnVubmVyTGV2ZWwgPz8gJ3JlcG8nKSA9PT0gJ3JlcG8nKSB7XG4gICAgYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMuZGVsZXRlU2VsZkhvc3RlZFJ1bm5lckZyb21SZXBvKHtcbiAgICAgIG93bmVyOiBvd25lcixcbiAgICAgIHJlcG86IHJlcG8sXG4gICAgICBydW5uZXJfaWQ6IHJ1bm5lcklkLFxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IG9jdG9raXQucmVzdC5hY3Rpb25zLmRlbGV0ZVNlbGZIb3N0ZWRSdW5uZXJGcm9tT3JnKHtcbiAgICAgIG9yZzogb3duZXIsXG4gICAgICBydW5uZXJfaWQ6IHJ1bm5lcklkLFxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWRlbGl2ZXIob2N0b2tpdDogUmVzdE9jdG9raXQsIGRlbGl2ZXJ5SWQ6IGJpZ2ludCkge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IG9jdG9raXQucmVzdC5hcHBzLnJlZGVsaXZlcldlYmhvb2tEZWxpdmVyeSh7XG4gICAgLy8gd2FpdGluZyBmb3IgbmV3IG9jdG9raXQgLS0gaHR0cHM6Ly9naXRodWIuY29tL29jdG9raXQvcmVxdWVzdC5qcy9pc3N1ZXMvNzk3I2lzc3VlY29tbWVudC0zOTUzMjc0NTgzXG4gICAgZGVsaXZlcnlfaWQ6IGRlbGl2ZXJ5SWQgYXMgdW5rbm93biBhcyBudW1iZXIsXG4gIH0pO1xuXG4gIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJlZGVsaXZlciB3ZWJob29rIGRlbGl2ZXJ5IHdpdGggSUQgJHtkZWxpdmVyeUlkfWApO1xuICB9XG4gIGNvbnNvbGUubG9nKHtcbiAgICBub3RpY2U6ICdTdWNjZXNzZnVsbHkgcmVkZWxpdmVyZWQgd2ViaG9vayBkZWxpdmVyeScsXG4gICAgZGVsaXZlcnlJZDogU3RyaW5nKGRlbGl2ZXJ5SWQpLFxuICB9KTtcbn1cbiJdfQ==