@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.
150 lines • 19.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearFailuresCache = clearFailuresCache;
exports.handler = handler;
const lambda_github_1 = require("./lambda-github");
/**
* Get webhook delivery failures since the last processed delivery ID.
*
* @internal
*/
async function newDeliveryFailures(octokit, sinceId) {
const deliveries = new Map();
const successfulDeliveries = new Set();
const timeLimitMs = 1000 * 60 * 30; // don't look at deliveries over 30 minutes old
let lastId = 0n;
let processedCount = 0;
for await (const response of octokit.paginate.iterator('GET /app/hook/deliveries')) {
if (response.status !== 200) {
throw new Error('Failed to fetch webhook deliveries');
}
for (const delivery of response.data) {
const deliveryId = BigInt(delivery.id);
const deliveredAt = new Date(delivery.delivered_at);
const success = delivery.status === 'OK';
if (deliveryId <= sinceId) {
// stop processing if we reach the last processed delivery ID
console.info({
notice: 'Reached last processed delivery ID',
sinceId: String(sinceId),
deliveryId: String(deliveryId),
guid: delivery.guid,
processedCount,
});
return { deliveries, lastId };
}
lastId = deliveryId > lastId ? deliveryId : lastId;
if (deliveredAt.getTime() < Date.now() - timeLimitMs) {
// stop processing if the delivery is too old (for first iteration and performance of further iterations)
console.info({
notice: 'Stopping at old delivery',
deliveryId: String(deliveryId),
guid: delivery.guid,
deliveredAt: deliveredAt,
processedCount,
});
return { deliveries, lastId };
}
console.debug({
notice: 'Processing webhook delivery',
deliveryId: String(deliveryId),
guid: delivery.guid,
status: delivery.status,
deliveredAt: delivery.delivered_at,
redelivery: delivery.redelivery,
});
processedCount++;
if (success) {
successfulDeliveries.add(delivery.guid);
continue;
}
if (successfulDeliveries.has(delivery.guid)) {
// do not redeliver deliveries that were already successful
continue;
}
deliveries.set(delivery.guid, { id: deliveryId, deliveredAt, redelivery: delivery.redelivery });
}
}
console.info({
notice: 'No more webhook deliveries to process',
deliveryId: 'DONE',
guid: 'DONE',
deliveredAt: 'DONE',
processedCount,
});
return { deliveries, lastId };
}
let lastDeliveryIdProcessed = 0n;
const failures = new Map();
/**
* Clear the cache of webhook delivery failures.
*
* For unit testing purposes only.
*
* @internal
*/
function clearFailuresCache() {
lastDeliveryIdProcessed = 0n;
failures.clear();
}
async function handler() {
const octokit = await (0, lambda_github_1.getAppOctokit)();
if (!octokit) {
console.info({
notice: 'Skipping webhook redelivery',
reason: 'App installation might not be configured or the app is not installed.',
});
return;
}
// fetch deliveries since the last processed delivery ID
// for any failures:
// 1. if this is not a redelivery, save the delivery ID and time, and finally retry
// 2. if this is a redelivery, check if the original delivery is still within the time limit and retry if it is
const { deliveries, lastId } = await newDeliveryFailures(octokit, lastDeliveryIdProcessed);
lastDeliveryIdProcessed = lastId > lastDeliveryIdProcessed ? lastId : lastDeliveryIdProcessed;
const timeLimitMs = 1000 * 60 * 60 * 3; // retry for up to 3 hours
for (const [guid, details] of deliveries) {
if (!details.redelivery) {
failures.set(guid, { id: details.id, firstDeliveredAt: details.deliveredAt });
console.log({
notice: 'Redelivering failed delivery',
deliveryId: String(details.id),
guid: guid,
firstDeliveredAt: details.deliveredAt,
});
await (0, lambda_github_1.redeliver)(octokit, details.id);
}
else {
// if this is a redelivery, check if the original delivery is still within the time limit
const originalFailure = failures.get(guid);
if (originalFailure) {
if (new Date().getTime() - originalFailure.firstDeliveredAt.getTime() < timeLimitMs) {
console.log({
notice: 'Redelivering failed delivery',
deliveryId: String(details.id),
guid: guid,
firstDeliveredAt: originalFailure.firstDeliveredAt,
});
await (0, lambda_github_1.redeliver)(octokit, details.id);
}
else {
failures.delete(guid); // no need to keep track of this anymore
console.log({
notice: 'Skipping redelivery of old failed delivery',
deliveryId: String(details.id),
guid: guid,
firstDeliveredAt: originalFailure?.firstDeliveredAt,
});
}
}
else {
console.log({
notice: 'Skipping redelivery of old failed delivery',
deliveryId: String(details.id),
guid: guid,
});
}
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViaG9vay1yZWRlbGl2ZXJ5LmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJob29rLXJlZGVsaXZlcnkubGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZ0dBLGdEQUdDO0FBRUQsMEJBeURDO0FBN0pELG1EQUEyRDtBQUUzRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLE9BQWdCLEVBQUUsT0FBZTtJQUNsRSxNQUFNLFVBQVUsR0FBd0UsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNsRyxNQUFNLG9CQUFvQixHQUFnQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BELE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsK0NBQStDO0lBQ25GLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNoQixJQUFJLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFFdkIsSUFBSSxLQUFLLEVBQUUsTUFBTSxRQUFRLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDO1FBQ25GLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUVELEtBQUssTUFBTSxRQUFRLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdkMsTUFBTSxXQUFXLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDO1lBRXpDLElBQUksVUFBVSxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUMxQiw2REFB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T0FBTyxFQUFFLEdBQUcsV0FBVyxFQUFFLENBQUM7b0JBQ3BGLE9BQU8sQ0FBQyxHQUFHLENBQUM7d0JBQ1YsTUFBTSxFQUFFLDhCQUE4Qjt3QkFDdEMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUM5QixJQUFJLEVBQUUsSUFBSTt3QkFDVixnQkFBZ0IsRUFBRSxlQUFlLENBQUMsZ0JBQWdCO3FCQUNuRCxDQUFDLENBQUM7b0JBQ0gsTUFBTSxJQUFBLHlCQUFTLEVBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDdkMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyx3Q0FBd0M7b0JBQy9ELE9BQU8sQ0FBQyxHQUFHLENBQUM7d0JBQ1YsTUFBTSxFQUFFLDRDQUE0Qzt3QkFDcEQsVUFBVSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUM5QixJQUFJLEVBQUUsSUFBSTt3QkFDVixnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsZ0JBQWdCO3FCQUNwRCxDQUFDLENBQUM7Z0JBQ0wsQ0FBQztZQUNILENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDO29CQUNWLE1BQU0sRUFBRSw0Q0FBNEM7b0JBQ3BELFVBQVUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDOUIsSUFBSSxFQUFFLElBQUk7aUJBQ1gsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgT2N0b2tpdCB9IGZyb20gJ0BvY3Rva2l0L3Jlc3QnO1xuaW1wb3J0IHsgZ2V0QXBwT2N0b2tpdCwgcmVkZWxpdmVyIH0gZnJvbSAnLi9sYW1iZGEtZ2l0aHViJztcblxuLyoqXG4gKiBHZXQgd2ViaG9vayBkZWxpdmVyeSBmYWlsdXJlcyBzaW5jZSB0aGUgbGFzdCBwcm9jZXNzZWQgZGVsaXZlcnkgSUQuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG5ld0RlbGl2ZXJ5RmFpbHVyZXMob2N0b2tpdDogT2N0b2tpdCwgc2luY2VJZDogYmlnaW50KSB7XG4gIGNvbnN0IGRlbGl2ZXJpZXM6IE1hcDxzdHJpbmcsIHsgaWQ6IGJpZ2ludDsgZGVsaXZlcmVkQXQ6IERhdGU7IHJlZGVsaXZlcnk6IGJvb2xlYW4gfT4gPSBuZXcgTWFwKCk7XG4gIGNvbnN0IHN1Y2Nlc3NmdWxEZWxpdmVyaWVzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgY29uc3QgdGltZUxpbWl0TXMgPSAxMDAwICogNjAgKiAzMDsgLy8gZG9uJ3QgbG9vayBhdCBkZWxpdmVyaWVzIG92ZXIgMzAgbWludXRlcyBvbGRcbiAgbGV0IGxhc3RJZCA9IDBuO1xuICBsZXQgcHJvY2Vzc2VkQ291bnQgPSAwO1xuXG4gIGZvciBhd2FpdCAoY29uc3QgcmVzcG9uc2Ugb2Ygb2N0b2tpdC5wYWdpbmF0ZS5pdGVyYXRvcignR0VUIC9hcHAvaG9vay9kZWxpdmVyaWVzJykpIHtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGZldGNoIHdlYmhvb2sgZGVsaXZlcmllcycpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZGVsaXZlcnkgb2YgcmVzcG9uc2UuZGF0YSkge1xuICAgICAgY29uc3QgZGVsaXZlcnlJZCA9IEJpZ0ludChkZWxpdmVyeS5pZCk7XG4gICAgICBjb25zdCBkZWxpdmVyZWRBdCA9IG5ldyBEYXRlKGRlbGl2ZXJ5LmRlbGl2ZXJlZF9hdCk7XG4gICAgICBjb25zdCBzdWNjZXNzID0gZGVsaXZlcnkuc3RhdHVzID09PSAnT0snO1xuXG4gICAgICBpZiAoZGVsaXZlcnlJZCA8PSBzaW5jZUlkKSB7XG4gICAgICAgIC8vIHN0b3AgcHJvY2Vzc2luZyBpZiB3ZSByZWFjaCB0aGUgbGFzdCBwcm9jZXNzZWQgZGVsaXZlcnkgSURcbiAgICAgICAgY29uc29sZS5pbmZvKHtcbiAgICAgICAgICBub3RpY2U6ICdSZWFjaGVkIGxhc3QgcHJvY2Vzc2VkIGRlbGl2ZXJ5IElEJyxcbiAgICAgICAgICBzaW5jZUlkOiBTdHJpbmcoc2luY2VJZCksXG4gICAgICAgICAgZGVsaXZlcnlJZDogU3RyaW5nKGRlbGl2ZXJ5SWQpLFxuICAgICAgICAgIGd1aWQ6IGRlbGl2ZXJ5Lmd1aWQsXG4gICAgICAgICAgcHJvY2Vzc2VkQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyBkZWxpdmVyaWVzLCBsYXN0SWQgfTtcbiAgICAgIH1cblxuICAgICAgbGFzdElkID0gZGVsaXZlcnlJZCA+IGxhc3RJZCA/IGRlbGl2ZXJ5SWQgOiBsYXN0SWQ7XG5cbiAgICAgIGlmIChkZWxpdmVyZWRBdC5nZXRUaW1lKCkgPCBEYXRlLm5vdygpIC0gdGltZUxpbWl0TXMpIHtcbiAgICAgICAgLy8gc3RvcCBwcm9jZXNzaW5nIGlmIHRoZSBkZWxpdmVyeSBpcyB0b28gb2xkIChmb3IgZmlyc3QgaXRlcmF0aW9uIGFuZCBwZXJmb3JtYW5jZSBvZiBmdXJ0aGVyIGl0ZXJhdGlvbnMpXG4gICAgICAgIGNvbnNvbGUuaW5mbyh7XG4gICAgICAgICAgbm90aWNlOiAnU3RvcHBpbmcgYXQgb2xkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICBkZWxpdmVyeUlkOiBTdHJpbmcoZGVsaXZlcnlJZCksXG4gICAgICAgICAgZ3VpZDogZGVsaXZlcnkuZ3VpZCxcbiAgICAgICAgICBkZWxpdmVyZWRBdDogZGVsaXZlcmVkQXQsXG4gICAgICAgICAgcHJvY2Vzc2VkQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyBkZWxpdmVyaWVzLCBsYXN0SWQgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5kZWJ1Zyh7XG4gICAgICAgIG5vdGljZTogJ1Byb2Nlc3Npbmcgd2ViaG9vayBkZWxpdmVyeScsXG4gICAgICAgIGRlbGl2ZXJ5SWQ6IFN0cmluZyhkZWxpdmVyeUlkKSxcbiAgICAgICAgZ3VpZDogZGVsaXZlcnkuZ3VpZCxcbiAgICAgICAgc3RhdHVzOiBkZWxpdmVyeS5zdGF0dXMsXG4gICAgICAgIGRlbGl2ZXJlZEF0OiBkZWxpdmVyeS5kZWxpdmVyZWRfYXQsXG4gICAgICAgIHJlZGVsaXZlcnk6IGRlbGl2ZXJ5LnJlZGVsaXZlcnksXG4gICAgICB9KTtcbiAgICAgIHByb2Nlc3NlZENvdW50Kys7XG5cbiAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIHN1Y2Nlc3NmdWxEZWxpdmVyaWVzLmFkZChkZWxpdmVyeS5ndWlkKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdWNjZXNzZnVsRGVsaXZlcmllcy5oYXMoZGVsaXZlcnkuZ3VpZCkpIHtcbiAgICAgICAgLy8gZG8gbm90IHJlZGVsaXZlciBkZWxpdmVyaWVzIHRoYXQgd2VyZSBhbHJlYWR5IHN1Y2Nlc3NmdWxcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGRlbGl2ZXJpZXMuc2V0KGRlbGl2ZXJ5Lmd1aWQsIHsgaWQ6IGRlbGl2ZXJ5SWQsIGRlbGl2ZXJlZEF0LCByZWRlbGl2ZXJ5OiBkZWxpdmVyeS5yZWRlbGl2ZXJ5IH0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnNvbGUuaW5mbyh7XG4gICAgbm90aWNlOiAnTm8gbW9yZSB3ZWJob29rIGRlbGl2ZXJpZXMgdG8gcHJvY2VzcycsXG4gICAgZGVsaXZlcnlJZDogJ0RPTkUnLFxuICAgIGd1aWQ6ICdET05FJyxcbiAgICBkZWxpdmVyZWRBdDogJ0RPTkUnLFxuICAgIHByb2Nlc3NlZENvdW50LFxuICB9KTtcblxuICByZXR1cm4geyBkZWxpdmVyaWVzLCBsYXN0SWQgfTtcbn1cblxubGV0IGxhc3REZWxpdmVyeUlkUHJvY2Vzc2VkID0gMG47XG5jb25zdCBmYWlsdXJlczogTWFwPHN0cmluZywgeyBpZDogYmlnaW50OyBmaXJzdERlbGl2ZXJlZEF0OiBEYXRlIH0+ID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIENsZWFyIHRoZSBjYWNoZSBvZiB3ZWJob29rIGRlbGl2ZXJ5IGZhaWx1cmVzLlxuICpcbiAqIEZvciB1bml0IHRlc3RpbmcgcHVycG9zZXMgb25seS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyRmFpbHVyZXNDYWNoZSgpIHtcbiAgbGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQgPSAwbjtcbiAgZmFpbHVyZXMuY2xlYXIoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoKSB7XG4gIGNvbnN0IG9jdG9raXQgPSBhd2FpdCBnZXRBcHBPY3Rva2l0KCk7XG4gIGlmICghb2N0b2tpdCkge1xuICAgIGNvbnNvbGUuaW5mbyh7XG4gICAgICBub3RpY2U6ICdTa2lwcGluZyB3ZWJob29rIHJlZGVsaXZlcnknLFxuICAgICAgcmVhc29uOiAnQXBwIGluc3RhbGxhdGlvbiBtaWdodCBub3QgYmUgY29uZmlndXJlZCBvciB0aGUgYXBwIGlzIG5vdCBpbnN0YWxsZWQuJyxcbiAgICB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBmZXRjaCBkZWxpdmVyaWVzIHNpbmNlIHRoZSBsYXN0IHByb2Nlc3NlZCBkZWxpdmVyeSBJRFxuICAvLyBmb3IgYW55IGZhaWx1cmVzOlxuICAvLyAgMS4gaWYgdGhpcyBpcyBub3QgYSByZWRlbGl2ZXJ5LCBzYXZlIHRoZSBkZWxpdmVyeSBJRCBhbmQgdGltZSwgYW5kIGZpbmFsbHkgcmV0cnlcbiAgLy8gIDIuIGlmIHRoaXMgaXMgYSByZWRlbGl2ZXJ5LCBjaGVjayBpZiB0aGUgb3JpZ2luYWwgZGVsaXZlcnkgaXMgc3RpbGwgd2l0aGluIHRoZSB0aW1lIGxpbWl0IGFuZCByZXRyeSBpZiBpdCBpc1xuICBjb25zdCB7IGRlbGl2ZXJpZXMsIGxhc3RJZCB9ID0gYXdhaXQgbmV3RGVsaXZlcnlGYWlsdXJlcyhvY3Rva2l0LCBsYXN0RGVsaXZlcnlJZFByb2Nlc3NlZCk7XG4gIGxhc3REZWxpdmVyeUlkUHJvY2Vzc2VkID0gbGFzdElkID4gbGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQgPyBsYXN0SWQgOiBsYXN0RGVsaXZlcnlJZFByb2Nlc3NlZDtcbiAgY29uc3QgdGltZUxpbWl0TXMgPSAxMDAwICogNjAgKiA2MCAqIDM7IC8vIHJldHJ5IGZvciB1cCB0byAzIGhvdXJzXG4gIGZvciAoY29uc3QgW2d1aWQsIGRldGFpbHNdIG9mIGRlbGl2ZXJpZXMpIHtcbiAgICBpZiAoIWRldGFpbHMucmVkZWxpdmVyeSkge1xuICAgICAgZmFpbHVyZXMuc2V0KGd1aWQsIHsgaWQ6IGRldGFpbHMuaWQsIGZpcnN0RGVsaXZlcmVkQXQ6IGRldGFpbHMuZGVsaXZlcmVkQXQgfSk7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ1JlZGVsaXZlcmluZyBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICBkZWxpdmVyeUlkOiBTdHJpbmcoZGV0YWlscy5pZCksXG4gICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgIGZpcnN0RGVsaXZlcmVkQXQ6IGRldGFpbHMuZGVsaXZlcmVkQXQsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHJlZGVsaXZlcihvY3Rva2l0LCBkZXRhaWxzLmlkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgdGhpcyBpcyBhIHJlZGVsaXZlcnksIGNoZWNrIGlmIHRoZSBvcmlnaW5hbCBkZWxpdmVyeSBpcyBzdGlsbCB3aXRoaW4gdGhlIHRpbWUgbGltaXRcbiAgICAgIGNvbnN0IG9yaWdpbmFsRmFpbHVyZSA9IGZhaWx1cmVzLmdldChndWlkKTtcbiAgICAgIGlmIChvcmlnaW5hbEZhaWx1cmUpIHtcbiAgICAgICAgaWYgKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gb3JpZ2luYWxGYWlsdXJlLmZpcnN0RGVsaXZlcmVkQXQuZ2V0VGltZSgpIDwgdGltZUxpbWl0TXMpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgICAgICBub3RpY2U6ICdSZWRlbGl2ZXJpbmcgZmFpbGVkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICAgIGRlbGl2ZXJ5SWQ6IFN0cmluZyhkZXRhaWxzLmlkKSxcbiAgICAgICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgICAgICBmaXJzdERlbGl2ZXJlZEF0OiBvcmlnaW5hbEZhaWx1cmUuZmlyc3REZWxpdmVyZWRBdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBhd2FpdCByZWRlbGl2ZXIob2N0b2tpdCwgZGV0YWlscy5pZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmFpbHVyZXMuZGVsZXRlKGd1aWQpOyAvLyBubyBuZWVkIHRvIGtlZXAgdHJhY2sgb2YgdGhpcyBhbnltb3JlXG4gICAgICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICAgICAgbm90aWNlOiAnU2tpcHBpbmcgcmVkZWxpdmVyeSBvZiBvbGQgZmFpbGVkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICAgIGRlbGl2ZXJ5SWQ6IFN0cmluZyhkZXRhaWxzLmlkKSxcbiAgICAgICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgICAgICBmaXJzdERlbGl2ZXJlZEF0OiBvcmlnaW5hbEZhaWx1cmU/LmZpcnN0RGVsaXZlcmVkQXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKHtcbiAgICAgICAgICBub3RpY2U6ICdTa2lwcGluZyByZWRlbGl2ZXJ5IG9mIG9sZCBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICAgIGRlbGl2ZXJ5SWQ6IFN0cmluZyhkZXRhaWxzLmlkKSxcbiAgICAgICAgICBndWlkOiBndWlkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==