Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.
4 changes: 2 additions & 2 deletions dist/check-group/core/config_getter.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchConfig = void 0;
var utils_1 = require("../utils");
var user_config_parser_1 = require("./user_config_parser");
var core = __importStar(require("@actions/core"));
/**
* Fetches the app configuration from the user's repository.
Expand Down Expand Up @@ -106,7 +106,7 @@ var fetchConfig = function (context) { return __awaiter(void 0, void 0, void 0,
_a.label = 4;
case 4:
core.debug("configData: ".concat(JSON.stringify(configData)));
return [2 /*return*/, (0, utils_1.parseUserConfig)(configData)];
return [2 /*return*/, (0, user_config_parser_1.parseUserConfig)(configData)];
}
});
}); };
Expand Down
204 changes: 204 additions & 0 deletions dist/check-group/core/generate_progress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.commentOnPr = exports.generateProgressDetailsMarkdown = exports.generateProgressDetailsCLI = void 0;
var statusToMark = function (check, postedChecks) {
if (check in postedChecks) {
if (postedChecks[check].conclusion === "success") {
return "✅";
}
if (postedChecks[check].conclusion === "failure") {
return "❌";
}
if (postedChecks[check].conclusion === "cancelled") {
return "🚫";
}
if (postedChecks[check].conclusion === null) {
return "⌛"; // pending
}
}
return "❓";
};
var statusToLink = function (check, postedChecks) {
if (check in postedChecks) {
var checkData = postedChecks[check];
// assert(checkData.name === check)
return "[".concat(check, "](").concat(checkData.details_url, ")");
}
return check;
};
var parseStatus = function (check, postedChecks) {
if (check in postedChecks) {
var checkData = postedChecks[check];
if (checkData.conclusion === null) {
return checkData.status;
}
else {
return checkData.conclusion;
}
}
return "no_status";
};
var generateProgressDetailsCLI = function (subprojects, postedChecks) {
var progress = "";
// these are the required subprojects
subprojects.forEach(function (subproject) {
progress += "Summary for sub-project ".concat(subproject.id, "\n");
// for padding
var longestLength = Math.max.apply(Math, (subproject.checks.map(function (check) { return check.length; })));
subproject.checks.forEach(function (check) {
var mark = statusToMark(check, postedChecks);
var status = parseStatus(check, postedChecks);
progress += "".concat(check.padEnd(longestLength, ' '), " | ").concat(mark, " | ").concat(status.padEnd(12, ' '), "\n");
});
progress += "\n\n";
});
progress += "\n";
progress += "## Currently received checks\n";
var longestLength = 1;
for (var availableCheck in postedChecks) {
longestLength = Math.max(longestLength, availableCheck.length);
}
for (var availableCheck in postedChecks) {
var mark = statusToMark(availableCheck, postedChecks);
var status_1 = parseStatus(availableCheck, postedChecks);
progress += "".concat(availableCheck.padEnd(longestLength, ' '), " | ").concat(mark, " | ").concat(status_1.padEnd(12, ' '), "\n");
}
progress += "\n";
return progress;
};
exports.generateProgressDetailsCLI = generateProgressDetailsCLI;
var generateProgressDetailsMarkdown = function (subprojects, postedChecks) {
var progress = "## Groups summary\n";
subprojects.forEach(function (subproject) {
// create a map of the relevant checks with their status
var subprojectCheckStatus = {};
subproject.checks.forEach(function (check) {
var status = (check in postedChecks) ? postedChecks[check].conclusion : 'no_status';
subprojectCheckStatus[check] = status;
});
// get the aggregated status of all statuses in the subproject
var subprojectEmoji = Object.values(subprojectCheckStatus).every(function (v) { return v === "success"; }) ? "🟢" : "🔴";
// generate the markdown table
progress += "<details>\n\n";
progress += "<summary><b>".concat(subprojectEmoji, " ").concat(subproject.id, "</b></summary>\n\n");
progress += "| Check ID | Status | |\n";
progress += "| -------- | ------ | --- |\n";
for (var _i = 0, _a = Object.entries(subprojectCheckStatus); _i < _a.length; _i++) {
var _b = _a[_i], check = _b[0], status_2 = _b[1];
var link = statusToLink(check, postedChecks);
var status_3 = parseStatus(check, postedChecks);
var mark = statusToMark(check, postedChecks);
progress += "| ".concat(link, " | ").concat(status_3, " | ").concat(mark, " |\n");
}
progress += "\n</details>\n\n";
});
return progress;
};
exports.generateProgressDetailsMarkdown = generateProgressDetailsMarkdown;
var PR_COMMENT_START = "<!-- checkgroup-comment-start -->";
function formPrComment(result, inputs, subprojects, postedChecks) {
var parsedConclusion = result.replace("_", " ");
// capitalize
parsedConclusion = parsedConclusion.charAt(0).toUpperCase() + parsedConclusion.slice(1);
var hasFailed = result === "has_failure";
var conclusionEmoji = (result === "all_passing") ? "🟢" : (hasFailed) ? "🔴" : "🟡";
var lightning = (result === "all_passing") ? "⚡" : (hasFailed) ? "⛈️" : "🌩️";
var failedMesage = ("\n**\u26A0\uFE0F This job will need to be re-run to merge your PR."
+ " If you do not have write access to the repository you can ask `".concat(inputs.maintainers, "` to re-run it for you.")
+ " If you push a new commit, all of CI will re-trigger ⚠️**"
+ " If you have any other questions, you can reach out to `".concat(inputs.owner, "` for help."));
var progressDetails = (0, exports.generateProgressDetailsMarkdown)(subprojects, postedChecks);
return (PR_COMMENT_START
+ "\n# ".concat(lightning, " Required checks status: ").concat(parsedConclusion, " ").concat(conclusionEmoji)
+ ((hasFailed) ? failedMesage : "")
+ ((subprojects.length) ? "\n".concat(progressDetails) : "\nNo groups match the files changed in this PR.")
+ "\n\n---"
+ "\nThis comment was automatically generated and updates for ".concat(inputs.timeout, " minutes ")
+ "every ".concat(inputs.interval, " seconds.")
+ "\n\nThank you for your contribution! 💜");
}
function getPrComment(context) {
return __awaiter(this, void 0, void 0, function () {
var params, commentsRes, _i, _a, comment;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
params = context.issue();
return [4 /*yield*/, context.octokit.rest.issues.listComments(params)];
case 1:
commentsRes = _b.sent();
for (_i = 0, _a = commentsRes.data; _i < _a.length; _i++) {
comment = _a[_i];
if (comment.body.includes(PR_COMMENT_START)) {
return [2 /*return*/, { id: comment.id, body: comment.body }];
}
}
return [2 /*return*/, { id: 0, body: "" }];
}
});
});
}
function commentOnPr(context, result, inputs, subprojects, postedChecks) {
return __awaiter(this, void 0, void 0, function () {
var existingData, newComment;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getPrComment(context)];
case 1:
existingData = _a.sent();
context.log.debug("existingData: ".concat(JSON.stringify(existingData)));
newComment = formPrComment(result, inputs, subprojects, postedChecks);
if (existingData.body === newComment) {
return [2 /*return*/];
}
if (!(existingData.id === 0)) return [3 /*break*/, 3];
return [4 /*yield*/, context.octokit.issues.createComment(context.issue({ body: newComment }))];
case 2:
_a.sent();
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, context.octokit.issues.updateComment(context.repo({ body: newComment, comment_id: existingData.id }))];
case 4:
_a.sent();
_a.label = 5;
case 5: return [2 /*return*/];
}
});
});
}
exports.commentOnPr = commentOnPr;
63 changes: 42 additions & 21 deletions dist/check-group/core/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
"use strict";
/**
* @module Core
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
Expand Down Expand Up @@ -63,52 +60,62 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchConfig = exports.CheckGroup = void 0;
var utils_1 = require("../utils");
/**
* @module Core
*/
var core = __importStar(require("@actions/core"));
var generate_progress_1 = require("./generate_progress");
var subproj_matching_1 = require("./subproj_matching");
var satisfy_expected_checks_1 = require("./satisfy_expected_checks");
var config_getter_1 = require("./config_getter");
Object.defineProperty(exports, "fetchConfig", { enumerable: true, get: function () { return config_getter_1.fetchConfig; } });
var utils_2 = require("../utils");
var utils_3 = require("../utils");
/**
* The orchestration class.
*/
var CheckGroup = /** @class */ (function () {
function CheckGroup(pullRequestNumber, config, context, sha) {
this.intervalTimer = setTimeout(function () { return ''; }, 0);
this.timeoutTimer = setTimeout(function () { return ''; }, 0);
this.inputs = {};
this.pullRequestNumber = pullRequestNumber;
this.config = config;
this.context = context;
this.sha = sha;
}
CheckGroup.prototype.run = function () {
return __awaiter(this, void 0, void 0, function () {
var filenames, subprojs, expectedChecks, interval, timeout;
var filenames, subprojs, expectedChecks, maintainers, owner, interval, timeout;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.files()];
case 1:
filenames = _a.sent();
core.info("Files are: ".concat(JSON.stringify(filenames)));
subprojs = (0, utils_2.matchFilenamesToSubprojects)(filenames, this.config.subProjects);
subprojs = (0, subproj_matching_1.matchFilenamesToSubprojects)(filenames, this.config.subProjects);
core.debug("Matching subprojects are: ".concat(JSON.stringify(subprojs)));
if (core.isDebug()) {
expectedChecks = collectExpectedChecks(subprojs);
core.debug("Expected checks are: ".concat(JSON.stringify(expectedChecks)));
}
maintainers = core.getInput('maintainers');
this.inputs.maintainers = maintainers;
owner = core.getInput('owner');
this.inputs.owner = owner;
interval = parseInt(core.getInput('interval'));
this.inputs.interval = interval;
core.info("Check interval: ".concat(interval));
this.runCheck(subprojs, 1, interval * 1000);
timeout = parseInt(core.getInput('timeout'));
this.inputs.timeout = timeout;
core.info("Timeout: ".concat(timeout));
// set a timeout that will stop the job to avoid polling the GitHub API infinitely
this.timeoutTimer = setTimeout(function () {
clearTimeout(_this.intervalTimer);
core.setFailed("The timeout of ".concat(timeout, " minutes has triggered but not all required jobs were passing.")
+ " This job will need to be re-run to merge your PR."
+ " If you do not have write access to the repository you can ask ".concat(core.getInput('maintainers'), " to re-run it for you.")
+ " If you have any other questions, you can reach out to ".concat(core.getInput('owner'), " for help."));
+ " If you do not have write access to the repository you can ask ".concat(maintainers, " to re-run it for you.")
+ " If you have any other questions, you can reach out to ".concat(owner, " for help."));
}, timeout * 60 * 1000);
return [2 /*return*/];
}
Expand All @@ -117,7 +124,7 @@ var CheckGroup = /** @class */ (function () {
};
CheckGroup.prototype.runCheck = function (subprojs, tries, interval) {
return __awaiter(this, void 0, void 0, function () {
var postedChecks, conclusion, summary, details, error_1;
var postedChecks, result, error_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
Expand All @@ -129,12 +136,10 @@ var CheckGroup = /** @class */ (function () {
case 1:
postedChecks = _a.sent();
core.debug("postedChecks: ".concat(JSON.stringify(postedChecks)));
conclusion = (0, utils_3.satisfyExpectedChecks)(subprojs, postedChecks);
summary = (0, utils_1.generateProgressSummary)(subprojs, postedChecks);
details = (0, utils_1.generateProgressDetails)(subprojs, postedChecks);
core.info("".concat(this.config.customServiceName, " conclusion: '").concat(conclusion, "':\n").concat(summary, "\n").concat(details));
result = (0, satisfy_expected_checks_1.satisfyExpectedChecks)(subprojs, postedChecks);
this.notifyProgress(subprojs, postedChecks, result);
core.endGroup();
if (conclusion === "all_passing") {
if (result === "all_passing") {
core.info("All required checks were successful!");
clearTimeout(this.intervalTimer);
clearTimeout(this.timeoutTimer);
Expand All @@ -155,6 +160,17 @@ var CheckGroup = /** @class */ (function () {
});
});
};
CheckGroup.prototype.notifyProgress = function (subprojs, postedChecks, result) {
return __awaiter(this, void 0, void 0, function () {
var details;
return __generator(this, function (_a) {
details = (0, generate_progress_1.generateProgressDetailsCLI)(subprojs, postedChecks);
core.info("".concat(this.config.customServiceName, " result: '").concat(result, "':\n").concat(details));
(0, generate_progress_1.commentOnPr)(this.context, result, this.inputs, subprojs, postedChecks);
return [2 /*return*/];
});
});
};
/**
* Gets a list of files that are modified in
* a pull request.
Expand Down Expand Up @@ -193,8 +209,13 @@ var getPostedChecks = function (context, sha) { return __awaiter(void 0, void 0,
core.debug("checkRuns: ".concat(JSON.stringify(checkRuns)));
checkNames = {};
checkRuns.forEach(function (checkRun) {
var conclusion = checkRun.conclusion ? checkRun.conclusion : "pending";
checkNames[checkRun.name] = conclusion;
var checkRunData = {
name: checkRun.name,
status: checkRun.status,
conclusion: checkRun.conclusion,
details_url: checkRun.details_url
};
checkNames[checkRun.name] = checkRunData;
});
return [2 /*return*/, checkNames];
}
Expand All @@ -205,11 +226,11 @@ var collectExpectedChecks = function (configs) {
var requiredChecks = {};
configs.forEach(function (config) {
config.checks.forEach(function (check) {
if (check.id in requiredChecks) {
requiredChecks[check.id].push(config.id);
if (check in requiredChecks) {
requiredChecks[check].push(config.id);
}
else {
requiredChecks[check.id] = [config.id];
requiredChecks[check] = [config.id];
}
});
});
Expand Down
Loading