UNPKG

@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
"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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QUMsRUFBRTt3QkFDdEIsSUFBSSxFQUFFLElBQUk7d0JBQ1YsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLGdCQUFnQjtxQkFDbkQsQ0FBQyxDQUFDO29CQUNILE1BQU0sSUFBQSx5QkFBUyxFQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3ZDLENBQUM7cUJBQU0sQ0FBQztvQkFDTixRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsd0NBQXdDO29CQUMvRCxPQUFPLENBQUMsR0FBRyxDQUFDO3dCQUNWLE1BQU0sRUFBRSw0Q0FBNEM7d0JBQ3BELFVBQVUsRUFBRSxPQUFPLENBQUMsRUFBRTt3QkFDdEIsSUFBSSxFQUFFLElBQUk7d0JBQ1YsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLGdCQUFnQjtxQkFDcEQsQ0FBQyxDQUFDO2dCQUNMLENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQztvQkFDVixNQUFNLEVBQUUsNENBQTRDO29CQUNwRCxVQUFVLEVBQUUsT0FBTyxDQUFDLEVBQUU7b0JBQ3RCLElBQUksRUFBRSxJQUFJO2lCQUNYLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE9jdG9raXQgfSBmcm9tICdAb2N0b2tpdC9yZXN0JztcbmltcG9ydCB7IGdldEFwcE9jdG9raXQsIHJlZGVsaXZlciB9IGZyb20gJy4vbGFtYmRhLWdpdGh1Yic7XG5cbi8qKlxuICogR2V0IHdlYmhvb2sgZGVsaXZlcnkgZmFpbHVyZXMgc2luY2UgdGhlIGxhc3QgcHJvY2Vzc2VkIGRlbGl2ZXJ5IElELlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5hc3luYyBmdW5jdGlvbiBuZXdEZWxpdmVyeUZhaWx1cmVzKG9jdG9raXQ6IE9jdG9raXQsIHNpbmNlSWQ6IG51bWJlcikge1xuICBjb25zdCBkZWxpdmVyaWVzOiBNYXA8c3RyaW5nLCB7IGlkOiBudW1iZXI7IGRlbGl2ZXJlZEF0OiBEYXRlOyByZWRlbGl2ZXJ5OiBib29sZWFuIH0+ID0gbmV3IE1hcCgpO1xuICBjb25zdCBzdWNjZXNzZnVsRGVsaXZlcmllczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gIGNvbnN0IHRpbWVMaW1pdE1zID0gMTAwMCAqIDYwICogMzA7IC8vIGRvbid0IGxvb2sgYXQgZGVsaXZlcmllcyBvdmVyIDMwIG1pbnV0ZXMgb2xkXG4gIGxldCBsYXN0SWQgPSAwO1xuICBsZXQgcHJvY2Vzc2VkQ291bnQgPSAwO1xuXG4gIGZvciBhd2FpdCAoY29uc3QgcmVzcG9uc2Ugb2Ygb2N0b2tpdC5wYWdpbmF0ZS5pdGVyYXRvcignR0VUIC9hcHAvaG9vay9kZWxpdmVyaWVzJykpIHtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGZldGNoIHdlYmhvb2sgZGVsaXZlcmllcycpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZGVsaXZlcnkgb2YgcmVzcG9uc2UuZGF0YSkge1xuICAgICAgY29uc3QgZGVsaXZlcmVkQXQgPSBuZXcgRGF0ZShkZWxpdmVyeS5kZWxpdmVyZWRfYXQpO1xuICAgICAgY29uc3Qgc3VjY2VzcyA9IGRlbGl2ZXJ5LnN0YXR1cyA9PT0gJ09LJztcblxuICAgICAgaWYgKGRlbGl2ZXJ5LmlkIDw9IHNpbmNlSWQpIHtcbiAgICAgICAgLy8gc3RvcCBwcm9jZXNzaW5nIGlmIHdlIHJlYWNoIHRoZSBsYXN0IHByb2Nlc3NlZCBkZWxpdmVyeSBJRFxuICAgICAgICBjb25zb2xlLmluZm8oe1xuICAgICAgICAgIG5vdGljZTogJ1JlYWNoZWQgbGFzdCBwcm9jZXNzZWQgZGVsaXZlcnkgSUQnLFxuICAgICAgICAgIHNpbmNlSWQ6IHNpbmNlSWQsXG4gICAgICAgICAgZGVsaXZlcnlJZDogZGVsaXZlcnkuaWQsXG4gICAgICAgICAgZ3VpZDogZGVsaXZlcnkuZ3VpZCxcbiAgICAgICAgICBwcm9jZXNzZWRDb3VudCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IGRlbGl2ZXJpZXMsIGxhc3RJZCB9O1xuICAgICAgfVxuXG4gICAgICBsYXN0SWQgPSBNYXRoLm1heChsYXN0SWQsIGRlbGl2ZXJ5LmlkKTtcblxuICAgICAgaWYgKGRlbGl2ZXJlZEF0LmdldFRpbWUoKSA8IERhdGUubm93KCkgLSB0aW1lTGltaXRNcykge1xuICAgICAgICAvLyBzdG9wIHByb2Nlc3NpbmcgaWYgdGhlIGRlbGl2ZXJ5IGlzIHRvbyBvbGQgKGZvciBmaXJzdCBpdGVyYXRpb24gYW5kIHBlcmZvcm1hbmNlIG9mIGZ1cnRoZXIgaXRlcmF0aW9ucylcbiAgICAgICAgY29uc29sZS5pbmZvKHtcbiAgICAgICAgICBub3RpY2U6ICdTdG9wcGluZyBhdCBvbGQgZGVsaXZlcnknLFxuICAgICAgICAgIGRlbGl2ZXJ5SWQ6IGRlbGl2ZXJ5LmlkLFxuICAgICAgICAgIGd1aWQ6IGRlbGl2ZXJ5Lmd1aWQsXG4gICAgICAgICAgZGVsaXZlcmVkQXQ6IGRlbGl2ZXJlZEF0LFxuICAgICAgICAgIHByb2Nlc3NlZENvdW50LFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgZGVsaXZlcmllcywgbGFzdElkIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUuZGVidWcoe1xuICAgICAgICBub3RpY2U6ICdQcm9jZXNzaW5nIHdlYmhvb2sgZGVsaXZlcnknLFxuICAgICAgICBkZWxpdmVyeUlkOiBkZWxpdmVyeS5pZCxcbiAgICAgICAgZ3VpZDogZGVsaXZlcnkuZ3VpZCxcbiAgICAgICAgc3RhdHVzOiBkZWxpdmVyeS5zdGF0dXMsXG4gICAgICAgIGRlbGl2ZXJlZEF0OiBkZWxpdmVyeS5kZWxpdmVyZWRfYXQsXG4gICAgICAgIHJlZGVsaXZlcnk6IGRlbGl2ZXJ5LnJlZGVsaXZlcnksXG4gICAgICB9KTtcbiAgICAgIHByb2Nlc3NlZENvdW50Kys7XG5cbiAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIHN1Y2Nlc3NmdWxEZWxpdmVyaWVzLmFkZChkZWxpdmVyeS5ndWlkKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdWNjZXNzZnVsRGVsaXZlcmllcy5oYXMoZGVsaXZlcnkuZ3VpZCkpIHtcbiAgICAgICAgLy8gZG8gbm90IHJlZGVsaXZlciBkZWxpdmVyaWVzIHRoYXQgd2VyZSBhbHJlYWR5IHN1Y2Nlc3NmdWxcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGRlbGl2ZXJpZXMuc2V0KGRlbGl2ZXJ5Lmd1aWQsIHsgaWQ6IGRlbGl2ZXJ5LmlkLCBkZWxpdmVyZWRBdCwgcmVkZWxpdmVyeTogZGVsaXZlcnkucmVkZWxpdmVyeSB9KTtcbiAgICB9XG4gIH1cblxuICBjb25zb2xlLmluZm8oe1xuICAgIG5vdGljZTogJ05vIG1vcmUgd2ViaG9vayBkZWxpdmVyaWVzIHRvIHByb2Nlc3MnLFxuICAgIGRlbGl2ZXJ5SWQ6ICdET05FJyxcbiAgICBndWlkOiAnRE9ORScsXG4gICAgZGVsaXZlcmVkQXQ6ICdET05FJyxcbiAgICBwcm9jZXNzZWRDb3VudCxcbiAgfSk7XG5cbiAgcmV0dXJuIHsgZGVsaXZlcmllcywgbGFzdElkIH07XG59XG5cbmxldCBsYXN0RGVsaXZlcnlJZFByb2Nlc3NlZCA9IDA7XG5jb25zdCBmYWlsdXJlczogTWFwPHN0cmluZywgeyBpZDogbnVtYmVyOyBmaXJzdERlbGl2ZXJlZEF0OiBEYXRlIH0+ID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIENsZWFyIHRoZSBjYWNoZSBvZiB3ZWJob29rIGRlbGl2ZXJ5IGZhaWx1cmVzLlxuICpcbiAqIEZvciB1bml0IHRlc3RpbmcgcHVycG9zZXMgb25seS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyRmFpbHVyZXNDYWNoZSgpIHtcbiAgbGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQgPSAwO1xuICBmYWlsdXJlcy5jbGVhcigpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcigpIHtcbiAgY29uc3Qgb2N0b2tpdCA9IGF3YWl0IGdldEFwcE9jdG9raXQoKTtcbiAgaWYgKCFvY3Rva2l0KSB7XG4gICAgY29uc29sZS5pbmZvKHtcbiAgICAgIG5vdGljZTogJ1NraXBwaW5nIHdlYmhvb2sgcmVkZWxpdmVyeScsXG4gICAgICByZWFzb246ICdBcHAgaW5zdGFsbGF0aW9uIG1pZ2h0IG5vdCBiZSBjb25maWd1cmVkIG9yIHRoZSBhcHAgaXMgbm90IGluc3RhbGxlZC4nLFxuICAgIH0pO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIGZldGNoIGRlbGl2ZXJpZXMgc2luY2UgdGhlIGxhc3QgcHJvY2Vzc2VkIGRlbGl2ZXJ5IElEXG4gIC8vIGZvciBhbnkgZmFpbHVyZXM6XG4gIC8vICAxLiBpZiB0aGlzIGlzIG5vdCBhIHJlZGVsaXZlcnksIHNhdmUgdGhlIGRlbGl2ZXJ5IElEIGFuZCB0aW1lLCBhbmQgZmluYWxseSByZXRyeVxuICAvLyAgMi4gaWYgdGhpcyBpcyBhIHJlZGVsaXZlcnksIGNoZWNrIGlmIHRoZSBvcmlnaW5hbCBkZWxpdmVyeSBpcyBzdGlsbCB3aXRoaW4gdGhlIHRpbWUgbGltaXQgYW5kIHJldHJ5IGlmIGl0IGlzXG4gIGNvbnN0IHsgZGVsaXZlcmllcywgbGFzdElkIH0gPSBhd2FpdCBuZXdEZWxpdmVyeUZhaWx1cmVzKG9jdG9raXQsIGxhc3REZWxpdmVyeUlkUHJvY2Vzc2VkKTtcbiAgbGFzdERlbGl2ZXJ5SWRQcm9jZXNzZWQgPSBNYXRoLm1heChsYXN0RGVsaXZlcnlJZFByb2Nlc3NlZCwgbGFzdElkKTtcbiAgY29uc3QgdGltZUxpbWl0TXMgPSAxMDAwICogNjAgKiA2MCAqIDM7IC8vIHJldHJ5IGZvciB1cCB0byAzIGhvdXJzXG4gIGZvciAoY29uc3QgW2d1aWQsIGRldGFpbHNdIG9mIGRlbGl2ZXJpZXMpIHtcbiAgICBpZiAoIWRldGFpbHMucmVkZWxpdmVyeSkge1xuICAgICAgZmFpbHVyZXMuc2V0KGd1aWQsIHsgaWQ6IGRldGFpbHMuaWQsIGZpcnN0RGVsaXZlcmVkQXQ6IGRldGFpbHMuZGVsaXZlcmVkQXQgfSk7XG4gICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgIG5vdGljZTogJ1JlZGVsaXZlcmluZyBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICBkZWxpdmVyeUlkOiBkZXRhaWxzLmlkLFxuICAgICAgICBndWlkOiBndWlkLFxuICAgICAgICBmaXJzdERlbGl2ZXJlZEF0OiBkZXRhaWxzLmRlbGl2ZXJlZEF0LFxuICAgICAgfSk7XG4gICAgICBhd2FpdCByZWRlbGl2ZXIob2N0b2tpdCwgZGV0YWlscy5pZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHRoaXMgaXMgYSByZWRlbGl2ZXJ5LCBjaGVjayBpZiB0aGUgb3JpZ2luYWwgZGVsaXZlcnkgaXMgc3RpbGwgd2l0aGluIHRoZSB0aW1lIGxpbWl0XG4gICAgICBjb25zdCBvcmlnaW5hbEZhaWx1cmUgPSBmYWlsdXJlcy5nZXQoZ3VpZCk7XG4gICAgICBpZiAob3JpZ2luYWxGYWlsdXJlKSB7XG4gICAgICAgIGlmIChuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIG9yaWdpbmFsRmFpbHVyZS5maXJzdERlbGl2ZXJlZEF0LmdldFRpbWUoKSA8IHRpbWVMaW1pdE1zKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coe1xuICAgICAgICAgICAgbm90aWNlOiAnUmVkZWxpdmVyaW5nIGZhaWxlZCBkZWxpdmVyeScsXG4gICAgICAgICAgICBkZWxpdmVyeUlkOiBkZXRhaWxzLmlkLFxuICAgICAgICAgICAgZ3VpZDogZ3VpZCxcbiAgICAgICAgICAgIGZpcnN0RGVsaXZlcmVkQXQ6IG9yaWdpbmFsRmFpbHVyZS5maXJzdERlbGl2ZXJlZEF0LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGF3YWl0IHJlZGVsaXZlcihvY3Rva2l0LCBkZXRhaWxzLmlkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmYWlsdXJlcy5kZWxldGUoZ3VpZCk7IC8vIG5vIG5lZWQgdG8ga2VlcCB0cmFjayBvZiB0aGlzIGFueW1vcmVcbiAgICAgICAgICBjb25zb2xlLmxvZyh7XG4gICAgICAgICAgICBub3RpY2U6ICdTa2lwcGluZyByZWRlbGl2ZXJ5IG9mIG9sZCBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICAgICAgZGVsaXZlcnlJZDogZGV0YWlscy5pZCxcbiAgICAgICAgICAgIGd1aWQ6IGd1aWQsXG4gICAgICAgICAgICBmaXJzdERlbGl2ZXJlZEF0OiBvcmlnaW5hbEZhaWx1cmU/LmZpcnN0RGVsaXZlcmVkQXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKHtcbiAgICAgICAgICBub3RpY2U6ICdTa2lwcGluZyByZWRlbGl2ZXJ5IG9mIG9sZCBmYWlsZWQgZGVsaXZlcnknLFxuICAgICAgICAgIGRlbGl2ZXJ5SWQ6IGRldGFpbHMuaWQsXG4gICAgICAgICAgZ3VpZDogZ3VpZCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=