@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.
149 lines • 18.6 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 = 0;
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 deliveredAt = new Date(delivery.delivered_at);
const success = delivery.status === 'OK';
if (delivery.id <= sinceId) {
// stop processing if we reach the last processed delivery ID
console.info({
notice: 'Reached last processed delivery ID',
sinceId: sinceId,
deliveryId: delivery.id,
guid: delivery.guid,
processedCount,
});
return { deliveries, lastId };
}
lastId = Math.max(lastId, delivery.id);
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: delivery.id,
guid: delivery.guid,
deliveredAt: deliveredAt,
processedCount,
});
return { deliveries, lastId };
}
console.debug({
notice: 'Processing webhook delivery',
deliveryId: delivery.id,
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: delivery.id, 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 = 0;
const failures = new Map();
/**
* Clear the cache of webhook delivery failures.
*
* For unit testing purposes only.
*
* @internal
*/
function clearFailuresCache() {
lastDeliveryIdProcessed = 0;
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 = Math.max(lastDeliveryIdProcessed, lastId);
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: 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: 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: details.id,
guid: guid,
firstDeliveredAt: originalFailure?.firstDeliveredAt,
});
}
}
else {
console.log({
notice: 'Skipping redelivery of old failed delivery',
deliveryId: details.id,
guid: guid,
});
}
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViaG9vay1yZWRlbGl2ZXJ5LmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJob29rLXJlZGVsaXZlcnkubGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBK0ZBLGdEQUdDO0FBRUQsMEJBeURDO0FBNUpELG1EQUEyRDtBQUUzRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLE9BQWdCLEVBQUUsT0FBZTtJQUNsRSxNQUFNLFVBQVUsR0FBd0UsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNsRyxNQUFNLG9CQUFvQixHQUFnQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BELE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsK0NBQStDO0lBQ25GLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNmLElBQUksY0FBYyxHQUFHLENBQUMsQ0FBQztJQUV2QixJQUFJLEtBQUssRUFBRSxNQUFNLFFBQVEsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLENBQUM7UUFDbkYsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsS0FBSyxNQUFNLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckMsTUFBTSxXQUFXLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDO1lBRXpDLElBQUksUUFBUSxDQUFDLEVBQUUsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDM0IsNkRBQTZEO2dCQUM3RCxPQUFPLENBQUMsSUFBSSxDQUFDO29CQUNYLE1BQU0sRUFBRSxv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QUMsRUFBRTt3QkFDdEIsSUFBSSxFQUFFLElBQUk7d0JBQ1YsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLGdCQUFnQjtxQkFDbkQsQ0FBQyxDQUFDO29CQUNILE1BQU0sSUFBQSx5QkFBUyxFQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3ZDLENBQUM7cUJBQU0sQ0FBQztvQkFDTixRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsd0NBQXdDO29CQUMvRCxPQUFPLENBQUMsR0FBRyxDQUFDO3dCQUNWLE1BQU0sRUFBRSw0Q0FBNEM7d0JBQ3BELFVBQVUsRUFBRSxPQUFPLENBQUMsRUFBRTt3QkFDdEIsSUFBSSxFQUFFLElBQUk7d0JBQ1YsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLGdCQUFnQjtxQkFDcEQsQ0FBQyxDQUFDO2dCQUNMLENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQztvQkFDVixNQUFNLEVBQUUsNENBQTRDO29CQUNwRCxVQUFVLEVBQUUsT0FBTyxDQUFDLEVBQUU7b0JBQ3RCLElBQUksRUFBRSxJQUFJO2lCQUNYLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPY3Rva2l0IH0gZnJvbSAnQG9jdG9raXQvcmVzdCc7XG5pbXBvcnQgeyBnZXRBcHBPY3Rva2l0LCByZWRlbGl2ZXIgfSBmcm9tICcuL2xhbWJkYS1naXRodWInO1xuXG4vKipcbiAqIEdldCB3ZWJob29rIGRlbGl2ZXJ5IGZhaWx1cmVzIHNpbmNlIHRoZSBsYXN0IHByb2Nlc3NlZCBkZWxpdmVyeSBJRC5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuYXN5bmMgZnVuY3Rpb24gbmV3RGVsaXZlcnlGYWlsdXJlcyhvY3Rva2l0OiBPY3Rva2l0LCBzaW5jZUlkOiBudW1iZXIpIHtcbiAgY29uc3QgZGVsaXZlcmllczogTWFwPHN0cmluZywgeyBpZDogbnVtYmVyOyBkZWxpdmVyZWRBdDogRGF0ZTsgcmVkZWxpdmVyeTogYm9vbGVhbiB9PiA9IG5ldyBNYXAoKTtcbiAgY29uc3Qgc3VjY2Vzc2Z1bERlbGl2ZXJpZXM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICBjb25zdCB0aW1lTGltaXRNcyA9IDEwMDAgKiA2MCAqIDMwOyAvLyBkb24ndCBsb29rIGF0IGRlbGl2ZXJpZXMgb3ZlciAzMCBtaW51dGVzIG9sZFxuICBsZXQgbGFzdElkID0gMDtcbiAgbGV0IHByb2Nlc3NlZENvdW50ID0gMDtcblxuICBmb3IgYXdhaXQgKGNvbnN0IHJlc3BvbnNlIG9mIG9jdG9raXQucGFnaW5hdGUuaXRlcmF0b3IoJ0dFVCAvYXBwL2hvb2svZGVsaXZlcmllcycpKSB7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBmZXRjaCB3ZWJob29rIGRlbGl2ZXJpZXMnKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRlbGl2ZXJ5IG9mIHJlc3BvbnNlLmRhdGEpIHtcbiAgICAgIGNvbnN0IGRlbGl2ZXJlZEF0ID0gbmV3IERhdGUoZGVsaXZlcnkuZGVsaXZlcmVkX2F0KTtcbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBkZWxpdmVyeS5zdGF0dXMgPT09ICdPSyc7XG5cbiAgICAgIGlmIChkZWxpdmVyeS5pZCA8PSBzaW5jZUlkKSB7XG4gICAgICAgIC8vIHN0b3AgcHJvY2Vzc2luZyBpZiB3ZSByZWFjaCB0aGUgbGFzdCBwcm9jZXNzZWQgZGVsaXZlcnkgSURcbiAgICAgICAgY29uc29sZS5pbmZvKHtcbiAgICAgICAgICBub3RpY2U6ICdSZWFjaGVkIGxhc3QgcHJvY2Vzc2VkIGRlbGl2ZXJ5IElEJyxcbiAgICAgICAgICBzaW5jZUlkOiBzaW5jZUlkLFxuICAgICAgICAgIGRlbGl2ZXJ5SWQ6IGRlbGl2ZXJ5LmlkLFxuICAgICAgICAgIGd1aWQ6IGRlbGl2ZXJ5Lmd1aWQsXG4gICAgICAgICAgcHJvY2Vzc2VkQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyBkZWxpdmVyaWVzLCBsYXN0SWQgfTtcbiAgICAgIH1cblxuICAgICAgbGFzdElkID0gTWF0aC5tYXgobGFzdElkLCBkZWxpdmVyeS5pZCk7XG5cbiAgICAgIGlmIChkZWxpdmVyZWRBdC5nZXRUaW1lKCkgPCBEYXRlLm5vdygpIC0gdGltZUxpbWl0TXMpIHtcbiAgICAgICAgLy8gc3RvcCBwcm9jZXNzaW5nIGlmIHRoZSBkZWxpdmVyeSBpcyB0b28gb2xkIChmb3IgZmlyc3QgaXRlcmF0aW9uIGFuZCBwZXJmb3JtYW5jZSBvZiBmdXJ0aGVyIGl0ZXJhdGlvbnMpXG4gICAgICAgIGNvbnNvbGUuaW5mbyh7XG4gICAgICAgICAgbm90aWNlOiAnU3RvcHBpbmcgYXQgb2xkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICBkZWxpdmVyeUlkOiBkZWxpdmVyeS5pZCxcbiAgICAgICAgICBndWlkOiBkZWxpdmVyeS5ndWlkLFxuICAgICAgICAgIGRlbGl2ZXJlZEF0OiBkZWxpdmVyZWRBdCxcbiAgICAgICAgICBwcm9jZXNzZWRDb3VudCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IGRlbGl2ZXJpZXMsIGxhc3RJZCB9O1xuICAgICAgfVxuXG4gICAgICBjb25zb2xlLmRlYnVnKHtcbiAgICAgICAgbm90aWNlOiAnUHJvY2Vzc2luZyB3ZWJob29rIGRlbGl2ZXJ5JyxcbiAgICAgICAgZGVsaXZlcnlJZDogZGVsaXZlcnkuaWQsXG4gICAgICAgIGd1aWQ6IGRlbGl2ZXJ5Lmd1aWQsXG4gICAgICAgIHN0YXR1czogZGVsaXZlcnkuc3RhdHVzLFxuICAgICAgICBkZWxpdmVyZWRBdDogZGVsaXZlcnkuZGVsaXZlcmVkX2F0LFxuICAgICAgICByZWRlbGl2ZXJ5OiBkZWxpdmVyeS5yZWRlbGl2ZXJ5LFxuICAgICAgfSk7XG4gICAgICBwcm9jZXNzZWRDb3VudCsrO1xuXG4gICAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgICBzdWNjZXNzZnVsRGVsaXZlcmllcy5hZGQoZGVsaXZlcnkuZ3VpZCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3VjY2Vzc2Z1bERlbGl2ZXJpZXMuaGFzKGRlbGl2ZXJ5Lmd1aWQpKSB7XG4gICAgICAgIC8vIGRvIG5vdCByZWRlbGl2ZXIgZGVsaXZlcmllcyB0aGF0IHdlcmUgYWxyZWFkeSBzdWNjZXNzZnVsXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBkZWxpdmVyaWVzLnNldChkZWxpdmVyeS5ndWlkLCB7IGlkOiBkZWxpdmVyeS5pZCwgZGVsaXZlcmVkQXQsIHJlZGVsaXZlcnk6IGRlbGl2ZXJ5LnJlZGVsaXZlcnkgfSk7XG4gICAgfVxuICB9XG5cbiAgY29uc29sZS5pbmZvKHtcbiAgICBub3RpY2U6ICdObyBtb3JlIHdlYmhvb2sgZGVsaXZlcmllcyB0byBwcm9jZXNzJyxcbiAgICBkZWxpdmVyeUlkOiAnRE9ORScsXG4gICAgZ3VpZDogJ0RPTkUnLFxuICAgIGRlbGl2ZXJlZEF0OiAnRE9ORScsXG4gICAgcHJvY2Vzc2VkQ291bnQsXG4gIH0pO1xuXG4gIHJldHVybiB7IGRlbGl2ZXJpZXMsIGxhc3RJZCB9O1xufVxuXG5sZXQgbGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQgPSAwO1xuY29uc3QgZmFpbHVyZXM6IE1hcDxzdHJpbmcsIHsgaWQ6IG51bWJlcjsgZmlyc3REZWxpdmVyZWRBdDogRGF0ZSB9PiA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBDbGVhciB0aGUgY2FjaGUgb2Ygd2ViaG9vayBkZWxpdmVyeSBmYWlsdXJlcy5cbiAqXG4gKiBGb3IgdW5pdCB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhckZhaWx1cmVzQ2FjaGUoKSB7XG4gIGxhc3REZWxpdmVyeUlkUHJvY2Vzc2VkID0gMDtcbiAgZmFpbHVyZXMuY2xlYXIoKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoKSB7XG4gIGNvbnN0IG9jdG9raXQgPSBhd2FpdCBnZXRBcHBPY3Rva2l0KCk7XG4gIGlmICghb2N0b2tpdCkge1xuICAgIGNvbnNvbGUuaW5mbyh7XG4gICAgICBub3RpY2U6ICdTa2lwcGluZyB3ZWJob29rIHJlZGVsaXZlcnknLFxuICAgICAgcmVhc29uOiAnQXBwIGluc3RhbGxhdGlvbiBtaWdodCBub3QgYmUgY29uZmlndXJlZCBvciB0aGUgYXBwIGlzIG5vdCBpbnN0YWxsZWQuJyxcbiAgICB9KTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBmZXRjaCBkZWxpdmVyaWVzIHNpbmNlIHRoZSBsYXN0IHByb2Nlc3NlZCBkZWxpdmVyeSBJRFxuICAvLyBmb3IgYW55IGZhaWx1cmVzOlxuICAvLyAgMS4gaWYgdGhpcyBpcyBub3QgYSByZWRlbGl2ZXJ5LCBzYXZlIHRoZSBkZWxpdmVyeSBJRCBhbmQgdGltZSwgYW5kIGZpbmFsbHkgcmV0cnlcbiAgLy8gIDIuIGlmIHRoaXMgaXMgYSByZWRlbGl2ZXJ5LCBjaGVjayBpZiB0aGUgb3JpZ2luYWwgZGVsaXZlcnkgaXMgc3RpbGwgd2l0aGluIHRoZSB0aW1lIGxpbWl0IGFuZCByZXRyeSBpZiBpdCBpc1xuICBjb25zdCB7IGRlbGl2ZXJpZXMsIGxhc3RJZCB9ID0gYXdhaXQgbmV3RGVsaXZlcnlGYWlsdXJlcyhvY3Rva2l0LCBsYXN0RGVsaXZlcnlJZFByb2Nlc3NlZCk7XG4gIGxhc3REZWxpdmVyeUlkUHJvY2Vzc2VkID0gTWF0aC5tYXgobGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQsIGxhc3RJZCk7XG4gIGNvbnN0IHRpbWVMaW1pdE1zID0gMTAwMCAqIDYwICogNjAgKiAzOyAvLyByZXRyeSBmb3IgdXAgdG8gMyBob3Vyc1xuICBmb3IgKGNvbnN0IFtndWlkLCBkZXRhaWxzXSBvZiBkZWxpdmVyaWVzKSB7XG4gICAgaWYgKCFkZXRhaWxzLnJlZGVsaXZlcnkpIHtcbiAgICAgIGZhaWx1cmVzLnNldChndWlkLCB7IGlkOiBkZXRhaWxzLmlkLCBmaXJzdERlbGl2ZXJlZEF0OiBkZXRhaWxzLmRlbGl2ZXJlZEF0IH0pO1xuICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICBub3RpY2U6ICdSZWRlbGl2ZXJpbmcgZmFpbGVkIGRlbGl2ZXJ5JyxcbiAgICAgICAgZGVsaXZlcnlJZDogZGV0YWlscy5pZCxcbiAgICAgICAgZ3VpZDogZ3VpZCxcbiAgICAgICAgZmlyc3REZWxpdmVyZWRBdDogZGV0YWlscy5kZWxpdmVyZWRBdCxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgcmVkZWxpdmVyKG9jdG9raXQsIGRldGFpbHMuaWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpZiB0aGlzIGlzIGEgcmVkZWxpdmVyeSwgY2hlY2sgaWYgdGhlIG9yaWdpbmFsIGRlbGl2ZXJ5IGlzIHN0aWxsIHdpdGhpbiB0aGUgdGltZSBsaW1pdFxuICAgICAgY29uc3Qgb3JpZ2luYWxGYWlsdXJlID0gZmFpbHVyZXMuZ2V0KGd1aWQpO1xuICAgICAgaWYgKG9yaWdpbmFsRmFpbHVyZSkge1xuICAgICAgICBpZiAobmV3IERhdGUoKS5nZXRUaW1lKCkgLSBvcmlnaW5hbEZhaWx1cmUuZmlyc3REZWxpdmVyZWRBdC5nZXRUaW1lKCkgPCB0aW1lTGltaXRNcykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKHtcbiAgICAgICAgICAgIG5vdGljZTogJ1JlZGVsaXZlcmluZyBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICAgICAgZGVsaXZlcnlJZDogZGV0YWlscy5pZCxcbiAgICAgICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgICAgICBmaXJzdERlbGl2ZXJlZEF0OiBvcmlnaW5hbEZhaWx1cmUuZmlyc3REZWxpdmVyZWRBdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBhd2FpdCByZWRlbGl2ZXIob2N0b2tpdCwgZGV0YWlscy5pZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmFpbHVyZXMuZGVsZXRlKGd1aWQpOyAvLyBubyBuZWVkIHRvIGtlZXAgdHJhY2sgb2YgdGhpcyBhbnltb3JlXG4gICAgICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICAgICAgbm90aWNlOiAnU2tpcHBpbmcgcmVkZWxpdmVyeSBvZiBvbGQgZmFpbGVkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICAgIGRlbGl2ZXJ5SWQ6IGRldGFpbHMuaWQsXG4gICAgICAgICAgICBndWlkOiBndWlkLFxuICAgICAgICAgICAgZmlyc3REZWxpdmVyZWRBdDogb3JpZ2luYWxGYWlsdXJlPy5maXJzdERlbGl2ZXJlZEF0LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgICAgbm90aWNlOiAnU2tpcHBpbmcgcmVkZWxpdmVyeSBvZiBvbGQgZmFpbGVkIGRlbGl2ZXJ5JyxcbiAgICAgICAgICBkZWxpdmVyeUlkOiBkZXRhaWxzLmlkLFxuICAgICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19