@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.
155 lines • 17.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.baseUrlFromDomain = baseUrlFromDomain;
exports.getOctokit = getOctokit;
exports.getAppOctokit = getAppOctokit;
exports.getRunner = getRunner;
exports.deleteRunner = deleteRunner;
exports.redeliver = redeliver;
const crypto_1 = require("crypto");
const auth_app_1 = require("@octokit/auth-app");
const rest_1 = require("@octokit/rest");
const lambda_helpers_1 = require("./lambda-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 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 rest_1.Octokit({
baseUrl,
authStrategy: auth_app_1.createAppAuth,
auth: {
appId: githubSecrets.appId,
privateKey: privateKey,
},
});
token = (await appOctokit.auth({
type: 'installation',
installationId: installationId,
})).token;
}
const octokit = new rest_1.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 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 rest_1.Octokit({
baseUrl,
authStrategy: auth_app_1.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({
page: page,
owner: owner,
repo: repo,
});
}
else {
runners = await octokit.rest.actions.listSelfHostedRunnersForOrg({
page: page,
org: owner,
});
}
if (runners.data.runners.length == 0) {
return;
}
for (const runner of runners.data.runners) {
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWdpdGh1Yi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9sYW1iZGEtZ2l0aHViLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBS0EsOENBS0M7QUFhRCxnQ0FrRUM7QUFJRCxzQ0FzQkM7QUFFRCw4QkE4QkM7QUFFRCxvQ0FhQztBQUVELDhCQVlDO0FBaExELG1DQUFvQztBQUNwQyxnREFBa0Q7QUFDbEQsd0NBQXdDO0FBQ3hDLHFEQUFzRTtBQUV0RSxTQUFnQixpQkFBaUIsQ0FBQyxNQUFjO0lBQzlDLElBQUksTUFBTSxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzNCLE9BQU8sd0JBQXdCLENBQUM7SUFDbEMsQ0FBQztJQUNELE9BQU8sV0FBVyxNQUFNLFNBQVMsQ0FBQztBQUNwQyxDQUFDO0FBV0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUM7QUFFekMsS0FBSyxVQUFVLFVBQVUsQ0FBQyxjQUF1QjtJQUN0RCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsNkJBQTZCLEVBQUUsQ0FBQztRQUNqRixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELE1BQU0sYUFBYSxHQUFrQixNQUFNLElBQUEsbUNBQWtCLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRTdGLHdHQUF3RztJQUN4RyxNQUFNLFFBQVEsR0FBRyxJQUFBLG1CQUFVLEVBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsY0FBYyxJQUFJLFlBQVksSUFBSSxhQUFhLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQyxLQUFLLElBQUksYUFBYSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFbEwsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMxQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ1gsSUFBSSxDQUFDO1lBQ0gsNENBQTRDO1lBQzVDLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEMsT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDVixNQUFNLEVBQUUsc0JBQXNCO2FBQy9CLENBQUMsQ0FBQztZQUNILE9BQU87Z0JBQ0wsT0FBTyxFQUFFLE1BQU07Z0JBQ2YsYUFBYTthQUNkLENBQUM7UUFDSixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE9BQU8sQ0FBQyxHQUFHLENBQUM7Z0JBQ1YsTUFBTSxFQUFFLDBCQUEwQjtnQkFDbEMsS0FBSyxFQUFFLENBQUM7YUFDVCxDQUFDLENBQUM7WUFDSCxZQUFZLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXhELElBQUksS0FBSyxDQUFDO0lBQ1YsSUFBSSxhQUFhLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUNwQyxLQUFLLEdBQUcsYUFBYSxDQUFDLGlCQUFpQixDQUFDO0lBQzFDLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFBLCtCQUFjLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBRW5GLE1BQU0sVUFBVSxHQUFHLElBQUksY0FBTyxDQUFDO1lBQzdCLE9BQU87WUFDUCxZQUFZLEVBQUUsd0JBQWE7WUFDM0IsSUFBSSxFQUFFO2dCQUNKLEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSztnQkFDMUIsVUFBVSxFQUFFLFVBQVU7YUFDdkI7U0FDRixDQUFDLENBQUM7UUFFSCxLQUFLLEdBQUcsQ0FBQyxNQUFNLFVBQVUsQ0FBQyxJQUFJLENBQUM7WUFDN0IsSUFBSSxFQUFFLGNBQWM7WUFDcEIsY0FBYyxFQUFFLGNBQWM7U0FDL0IsQ0FBUyxDQUFBLENBQUMsS0FBSyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLGNBQU8sQ0FBQztRQUMxQixPQUFPO1FBQ1AsSUFBSSxFQUFFLEtBQUs7S0FDWixDQUFDLENBQUM7SUFFSCxpQkFBaUI7SUFDakIsWUFBWSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFcEMsT0FBTztRQUNMLE9BQU87UUFDUCxhQUFhO0tBQ2QsQ0FBQztBQUNKLENBQUM7QUFFRCx5R0FBeUc7QUFDekcsaURBQWlEO0FBQzFDLEtBQUssVUFBVSxhQUFhO0lBQ2pDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO1FBQ2pGLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBRUQsTUFBTSxhQUFhLEdBQWtCLE1BQU0sSUFBQSxtQ0FBa0IsRUFBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDN0YsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXhELElBQUksYUFBYSxDQUFDLGlCQUFpQixJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUEsK0JBQWMsRUFBQyxPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7SUFFbkYsT0FBTyxJQUFJLGNBQU8sQ0FBQztRQUNqQixPQUFPO1FBQ1AsWUFBWSxFQUFFLHdCQUFhO1FBQzNCLElBQUksRUFBRTtZQUNKLEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSztZQUMxQixVQUFVLEVBQUUsVUFBVTtTQUN2QjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFTSxLQUFLLFVBQVUsU0FBUyxDQUFDLE9BQWdCLEVBQUUsV0FBd0IsRUFBRSxLQUFhLEVBQUUsSUFBWSxFQUFFLElBQVk7SUFDbkgsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ2IsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNaLElBQUksT0FBTyxDQUFDO1FBRVosSUFBSSxDQUFDLFdBQVcsSUFBSSxNQUFNLENBQUMsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUN2QyxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQztnQkFDaEUsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osSUFBSSxFQUFFLElBQUk7YUFDWCxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLDJCQUEyQixDQUFDO2dCQUMvRCxJQUFJLEVBQUUsSUFBSTtnQkFDVixHQUFHLEVBQUUsS0FBSzthQUNYLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNyQyxPQUFPO1FBQ1QsQ0FBQztRQUVELEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMxQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQ3hCLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxFQUFFLENBQUM7SUFDVCxDQUFDO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxZQUFZLENBQUMsT0FBZ0IsRUFBRSxXQUF3QixFQUFFLEtBQWEsRUFBRSxJQUFZLEVBQUUsUUFBZ0I7SUFDMUgsSUFBSSxDQUFDLFdBQVcsSUFBSSxNQUFNLENBQUMsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUN2QyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLDhCQUE4QixDQUFDO1lBQ3hELEtBQUssRUFBRSxLQUFLO1lBQ1osSUFBSSxFQUFFLElBQUk7WUFDVixTQUFTLEVBQUUsUUFBUTtTQUNwQixDQUFDLENBQUM7SUFDTCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsNkJBQTZCLENBQUM7WUFDdkQsR0FBRyxFQUFFLEtBQUs7WUFDVixTQUFTLEVBQUUsUUFBUTtTQUNwQixDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxTQUFTLENBQUMsT0FBZ0IsRUFBRSxVQUFrQjtJQUNsRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDO1FBQ2hFLFdBQVcsRUFBRSxVQUFVO0tBQ3hCLENBQUMsQ0FBQztJQUVILElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ1YsTUFBTSxFQUFFLDJDQUEyQztRQUNuRCxVQUFVO0tBQ1gsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgY3JlYXRlQXBwQXV0aCB9IGZyb20gJ0BvY3Rva2l0L2F1dGgtYXBwJztcbmltcG9ydCB7IE9jdG9raXQgfSBmcm9tICdAb2N0b2tpdC9yZXN0JztcbmltcG9ydCB7IGdldFNlY3JldEpzb25WYWx1ZSwgZ2V0U2VjcmV0VmFsdWUgfSBmcm9tICcuL2xhbWJkYS1oZWxwZXJzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGJhc2VVcmxGcm9tRG9tYWluKGRvbWFpbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGRvbWFpbiA9PSAnZ2l0aHViLmNvbScpIHtcbiAgICByZXR1cm4gJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20nO1xuICB9XG4gIHJldHVybiBgaHR0cHM6Ly8ke2RvbWFpbn0vYXBpL3YzYDtcbn1cblxudHlwZSBSdW5uZXJMZXZlbCA9ICdyZXBvJyB8ICdvcmcnIHwgdW5kZWZpbmVkOyAvLyB1bmRlZmluZWQgaXMgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGFuZCBzaG91bGQgYmUgdHJlYXRlZCBhcyAncmVwbydcblxuZXhwb3J0IGludGVyZmFjZSBHaXRIdWJTZWNyZXRzIHtcbiAgZG9tYWluOiBzdHJpbmc7XG4gIGFwcElkOiBudW1iZXI7XG4gIHBlcnNvbmFsQXV0aFRva2VuOiBzdHJpbmc7XG4gIHJ1bm5lckxldmVsOiBSdW5uZXJMZXZlbDtcbn1cblxuY29uc3Qgb2N0b2tpdENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIE9jdG9raXQ+KCk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRPY3Rva2l0KGluc3RhbGxhdGlvbklkPzogbnVtYmVyKTogUHJvbWlzZTx7IG9jdG9raXQ6IE9jdG9raXQ7IGdpdGh1YlNlY3JldHM6IEdpdEh1YlNlY3JldHMgfT4ge1xuICBpZiAoIXByb2Nlc3MuZW52LkdJVEhVQl9TRUNSRVRfQVJOIHx8ICFwcm9jZXNzLmVudi5HSVRIVUJfUFJJVkFURV9LRVlfU0VDUkVUX0FSTikge1xuICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBlbnZpcm9ubWVudCB2YXJpYWJsZXMnKTtcbiAgfVxuXG4gIGNvbnN0IGdpdGh1YlNlY3JldHM6IEdpdEh1YlNlY3JldHMgPSBhd2FpdCBnZXRTZWNyZXRKc29uVmFsdWUocHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4pO1xuXG4gIC8vIENyZWF0ZSBjYWNoZSBrZXkgZnJvbSBpbnN0YWxsYXRpb24gSUQgYW5kIHNlY3JldHMgKGhhc2ggdG8gYXZvaWQgZXhwb3Npbmcgc2Vuc2l0aXZlIGRhdGEgYnkgYWNjaWRlbnQpXG4gIGNvbnN0IGNhY2hlS2V5ID0gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGAke2luc3RhbGxhdGlvbklkIHx8ICduby1pbnN0YWxsJ30tJHtnaXRodWJTZWNyZXRzLmRvbWFpbn0tJHtnaXRodWJTZWNyZXRzLmFwcElkfS0ke2dpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW59YCkuZGlnZXN0KCdoZXgnKTtcblxuICBjb25zdCBjYWNoZWQgPSBvY3Rva2l0Q2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgaWYgKGNhY2hlZCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBUZXN0IGlmIHRoZSBjYWNoZWQgb2N0b2tpdCBpcyBzdGlsbCB2YWxpZFxuICAgICAgYXdhaXQgY2FjaGVkLnJlc3QubWV0YS5nZXRPY3RvY2F0KCk7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ1VzaW5nIGNhY2hlZCBvY3Rva2l0JyxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb2N0b2tpdDogY2FjaGVkLFxuICAgICAgICBnaXRodWJTZWNyZXRzLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ09jdG9raXQgY2FjaGUgaXMgaW52YWxpZCcsXG4gICAgICAgIGVycm9yOiBlLFxuICAgICAgfSk7XG4gICAgICBvY3Rva2l0Q2FjaGUuZGVsZXRlKGNhY2hlS2V5KTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBiYXNlVXJsID0gYmFzZVVybEZyb21Eb21haW4oZ2l0aHViU2VjcmV0cy5kb21haW4pO1xuXG4gIGxldCB0b2tlbjtcbiAgaWYgKGdpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW4pIHtcbiAgICB0b2tlbiA9IGdpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW47XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgcHJpdmF0ZUtleSA9IGF3YWl0IGdldFNlY3JldFZhbHVlKHByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKTtcblxuICAgIGNvbnN0IGFwcE9jdG9raXQgPSBuZXcgT2N0b2tpdCh7XG4gICAgICBiYXNlVXJsLFxuICAgICAgYXV0aFN0cmF0ZWd5OiBjcmVhdGVBcHBBdXRoLFxuICAgICAgYXV0aDoge1xuICAgICAgICBhcHBJZDogZ2l0aHViU2VjcmV0cy5hcHBJZCxcbiAgICAgICAgcHJpdmF0ZUtleTogcHJpdmF0ZUtleSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0b2tlbiA9IChhd2FpdCBhcHBPY3Rva2l0LmF1dGgoe1xuICAgICAgdHlwZTogJ2luc3RhbGxhdGlvbicsXG4gICAgICBpbnN0YWxsYXRpb25JZDogaW5zdGFsbGF0aW9uSWQsXG4gICAgfSkgYXMgYW55KS50b2tlbjtcbiAgfVxuXG4gIGNvbnN0IG9jdG9raXQgPSBuZXcgT2N0b2tpdCh7XG4gICAgYmFzZVVybCxcbiAgICBhdXRoOiB0b2tlbixcbiAgfSk7XG5cbiAgLy8gU3RvcmUgaW4gY2FjaGVcbiAgb2N0b2tpdENhY2hlLnNldChjYWNoZUtleSwgb2N0b2tpdCk7XG5cbiAgcmV0dXJuIHtcbiAgICBvY3Rva2l0LFxuICAgIGdpdGh1YlNlY3JldHMsXG4gIH07XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBnZXQgdGhlIE9jdG9raXQgaW5zdGFuY2UgZm9yIHRoZSBhcHAgaXRzZWxmLCBub3QgZm9yIGEgc3BlY2lmaWMgaW5zdGFsbGF0aW9uLlxuLy8gV2l0aCBQQVQgYXV0aGVudGljYXRpb24sIGl0IHJldHVybnMgdW5kZWZpbmVkLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFwcE9jdG9raXQoKSB7XG4gIGlmICghcHJvY2Vzcy5lbnYuR0lUSFVCX1NFQ1JFVF9BUk4gfHwgIXByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGVudmlyb25tZW50IHZhcmlhYmxlcycpO1xuICB9XG5cbiAgY29uc3QgZ2l0aHViU2VjcmV0czogR2l0SHViU2VjcmV0cyA9IGF3YWl0IGdldFNlY3JldEpzb25WYWx1ZShwcm9jZXNzLmVudi5HSVRIVUJfU0VDUkVUX0FSTik7XG4gIGNvbnN0IGJhc2VVcmwgPSBiYXNlVXJsRnJvbURvbWFpbihnaXRodWJTZWNyZXRzLmRvbWFpbik7XG5cbiAgaWYgKGdpdGh1YlNlY3JldHMucGVyc29uYWxBdXRoVG9rZW4gfHwgIWdpdGh1YlNlY3JldHMuYXBwSWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcHJpdmF0ZUtleSA9IGF3YWl0IGdldFNlY3JldFZhbHVlKHByb2Nlc3MuZW52LkdJVEhVQl9QUklWQVRFX0tFWV9TRUNSRVRfQVJOKTtcblxuICByZXR1cm4gbmV3IE9jdG9raXQoe1xuICAgIGJhc2VVcmwsXG4gICAgYXV0aFN0cmF0ZWd5OiBjcmVhdGVBcHBBdXRoLFxuICAgIGF1dGg6IHtcbiAgICAgIGFwcElkOiBnaXRodWJTZWNyZXRzLmFwcElkLFxuICAgICAgcHJpdmF0ZUtleTogcHJpdmF0ZUtleSxcbiAgICB9LFxuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFJ1bm5lcihvY3Rva2l0OiBPY3Rva2l0LCBydW5uZXJMZXZlbDogUnVubmVyTGV2ZWwsIG93bmVyOiBzdHJpbmcsIHJlcG86IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gIGxldCBwYWdlID0gMTtcbiAgd2hpbGUgKHRydWUpIHtcbiAgICBsZXQgcnVubmVycztcblxuICAgIGlmICgocnVubmVyTGV2ZWwgPz8gJ3JlcG8nKSA9PT0gJ3JlcG8nKSB7XG4gICAgICBydW5uZXJzID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMubGlzdFNlbGZIb3N0ZWRSdW5uZXJzRm9yUmVwbyh7XG4gICAgICAgIHBhZ2U6IHBhZ2UsXG4gICAgICAgIG93bmVyOiBvd25lcixcbiAgICAgICAgcmVwbzogcmVwbyxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBydW5uZXJzID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMubGlzdFNlbGZIb3N0ZWRSdW5uZXJzRm9yT3JnKHtcbiAgICAgICAgcGFnZTogcGFnZSxcbiAgICAgICAgb3JnOiBvd25lcixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChydW5uZXJzLmRhdGEucnVubmVycy5sZW5ndGggPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcnVubmVyIG9mIHJ1bm5lcnMuZGF0YS5ydW5uZXJzKSB7XG4gICAgICBpZiAocnVubmVyLm5hbWUgPT0gbmFtZSkge1xuICAgICAgICByZXR1cm4gcnVubmVyO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhZ2UrKztcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlUnVubmVyKG9jdG9raXQ6IE9jdG9raXQsIHJ1bm5lckxldmVsOiBSdW5uZXJMZXZlbCwgb3duZXI6IHN0cmluZywgcmVwbzogc3RyaW5nLCBydW5uZXJJZDogbnVtYmVyKSB7XG4gIGlmICgocnVubmVyTGV2ZWwgPz8gJ3JlcG8nKSA9PT0gJ3JlcG8nKSB7XG4gICAgYXdhaXQgb2N0b2tpdC5yZXN0LmFjdGlvbnMuZGVsZXRlU2VsZkhvc3RlZFJ1bm5lckZyb21SZXBvKHtcbiAgICAgIG93bmVyOiBvd25lcixcbiAgICAgIHJlcG86IHJlcG8sXG4gICAgICBydW5uZXJfaWQ6IHJ1bm5lcklkLFxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IG9jdG9raXQucmVzdC5hY3Rpb25zLmRlbGV0ZVNlbGZIb3N0ZWRSdW5uZXJGcm9tT3JnKHtcbiAgICAgIG9yZzogb3duZXIsXG4gICAgICBydW5uZXJfaWQ6IHJ1bm5lcklkLFxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWRlbGl2ZXIob2N0b2tpdDogT2N0b2tpdCwgZGVsaXZlcnlJZDogbnVtYmVyKSB7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgb2N0b2tpdC5yZXN0LmFwcHMucmVkZWxpdmVyV2ViaG9va0RlbGl2ZXJ5KHtcbiAgICBkZWxpdmVyeV9pZDogZGVsaXZlcnlJZCxcbiAgfSk7XG5cbiAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVkZWxpdmVyIHdlYmhvb2sgZGVsaXZlcnkgd2l0aCBJRCAke2RlbGl2ZXJ5SWR9YCk7XG4gIH1cbiAgY29uc29sZS5sb2coe1xuICAgIG5vdGljZTogJ1N1Y2Nlc3NmdWxseSByZWRlbGl2ZXJlZCB3ZWJob29rIGRlbGl2ZXJ5JyxcbiAgICBkZWxpdmVyeUlkLFxuICB9KTtcbn1cbiJdfQ==