danger
Version:
Unit tests for Team Culture
297 lines • 15.2 kB
JavaScript
"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.createOrAddLabel = exports.createOrUpdatePR = exports.createUpdatedIssueWithIDGenerator = exports.fileContentsGenerator = exports.isFileContents = void 0;
var path_1 = require("path");
var memfs_or_file_map_to_github_branch_1 = require("memfs-or-file-map-to-github-branch");
var DangerUtils_1 = require("../../runner/DangerUtils");
var debug_1 = require("../../debug");
function isFileContents(response) {
return response.type === "file";
}
exports.isFileContents = isFileContents;
var d = (0, debug_1.debug)("GitHub::Utils");
// We need to curry in access to the GitHub PR metadata
var utils = function (pr, api) {
/**
* Converts a set of filepaths into a sentence'd set of hrefs for the
* current PR. Can be configured to just show the name (instead of full filepath), to
* change the github repo or branch.
*
*/
var fileLinks = function (paths, useBasename, repoSlug, branch) {
// To support enterprise github, we need to handle custom github domains
// this can be pulled out of the repo url metadata
if (useBasename === void 0) { useBasename = true; }
var githubRoot = pr && pr.head.repo.html_url.split(pr.head.repo.owner.login)[0];
var slug = repoSlug || (pr && pr.head.repo.full_name);
var ref = branch || (pr && pr.head.ref);
var toHref = function (path) { return "".concat(githubRoot).concat(slug, "/blob/").concat(ref, "/").concat(path); };
// As we should only be getting paths we can ignore the nullability
var hrefs = paths.map(function (p) { return (0, DangerUtils_1.href)(toHref(p), useBasename ? (0, path_1.basename)(p) : p); });
return (0, DangerUtils_1.sentence)(hrefs);
};
return {
fileLinks: fileLinks,
fileContents: (0, exports.fileContentsGenerator)(api, pr && pr.head.repo.full_name, pr && pr.head.ref),
createUpdatedIssueWithID: (0, exports.createUpdatedIssueWithIDGenerator)(api),
createOrAddLabel: (0, exports.createOrAddLabel)(pr, api),
createOrUpdatePR: (0, exports.createOrUpdatePR)(pr, api),
};
};
/** Generates the fileContents function, needed so that Peril can re-create this func for an event */
var fileContentsGenerator = function (api, defaultRepoSlug, defaultRef) {
return function (path, repoSlug, ref) { return __awaiter(void 0, void 0, void 0, function () {
var opts, response, buffer, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Use the current state of PR if no repo/ref is passed
if (!repoSlug) {
repoSlug = defaultRepoSlug;
}
if (!ref) {
ref = defaultRef;
}
if (!repoSlug) {
throw new Error("You used fileContentsGenerator in a non-PR without specifying the repoSlug");
}
opts = {
ref: ref,
path: path,
repo: repoSlug.split("/")[1],
owner: repoSlug.split("/")[0],
};
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, api.repos.getContent(opts)];
case 2:
response = _b.sent();
if (!response || !response.data) {
return [2 /*return*/, ""];
}
if (Array.isArray(response.data)) {
// If we get an array, we have a directory
return [2 /*return*/, ""];
}
if (isFileContents(response.data) && response.data.content) {
buffer = Buffer.from(response.data.content, response.data.encoding);
return [2 /*return*/, buffer.toString()];
}
else {
return [2 /*return*/, ""];
}
return [3 /*break*/, 4];
case 3:
_a = _b.sent();
return [2 /*return*/, ""];
case 4: return [2 /*return*/];
}
});
}); };
};
exports.fileContentsGenerator = fileContentsGenerator;
/** Generates the createUpdatedIssueWithID function, needed so that Peril can re-create this func for an event */
var createUpdatedIssueWithIDGenerator = function (api) {
return function (id, content, settings) { return __awaiter(void 0, void 0, void 0, function () {
var uniqueHeader, q, searchResults, body, repo, owner, title, state, issueToUpdate, issue, issue;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
uniqueHeader = "Danger-Issue-ID-".concat(id.replace(/ /g, "_"));
q = "user:".concat(settings.owner, " repo:").concat(settings.repo, " ").concat(uniqueHeader);
return [4 /*yield*/, api.search.issuesAndPullRequests({ q: q })];
case 1:
searchResults = (_a.sent()).data;
d("Got ".concat(searchResults.total_count, " for ").concat(uniqueHeader));
body = "".concat(content, "\n\n").concat(uniqueHeader);
repo = settings.repo, owner = settings.owner, title = settings.title;
state = settings.open ? "open" : "closed";
if (!(searchResults.total_count > 0 && searchResults.items[0])) return [3 /*break*/, 3];
issueToUpdate = searchResults.items[0];
d("Found: ".concat(issueToUpdate));
return [4 /*yield*/, api.issues.update({
body: body,
owner: owner,
repo: repo,
title: title,
issue_number: issueToUpdate.number,
state: state,
})];
case 2:
issue = (_a.sent()).data;
return [2 /*return*/, issue.html_url];
case 3: return [4 /*yield*/, api.issues.create({ body: body, owner: owner, repo: repo, title: title })];
case 4:
issue = (_a.sent()).data;
return [2 /*return*/, issue.html_url];
}
});
}); };
};
exports.createUpdatedIssueWithIDGenerator = createUpdatedIssueWithIDGenerator;
var createOrUpdatePR = function (pr, api) { return function (config, fileMap) { return __awaiter(void 0, void 0, void 0, function () {
var repo, owner, branchSettings, prs, existingPR;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
repo = config.repo || (pr && pr.base.repo.name);
if (!repo) {
throw new Error("You need to set a `repo` in the config for `createOrUpdatePR`");
}
owner = config.owner || (pr && pr.base.user.login);
if (!owner) {
throw new Error("You need to set a `owner` in the config for `createOrUpdatePR`");
}
branchSettings = {
fullBaseBranch: "heads/".concat(config.baseBranch),
fullBranchReference: "heads/".concat(config.newBranchName),
message: config.commitMessage,
owner: owner,
repo: repo,
};
d("Creating a branch");
return [4 /*yield*/, (0, memfs_or_file_map_to_github_branch_1.filepathContentsMapToUpdateGitHubBranch)(api, fileMap, branchSettings)];
case 1:
_a.sent();
d("Getting open PRs");
return [4 /*yield*/, api.pulls.list({ repo: repo, owner: owner, state: "open" })];
case 2:
prs = _a.sent();
existingPR = prs.data.find(function (pr) { return pr.base.ref === config.newBranchName; });
if (!existingPR) return [3 /*break*/, 4];
d("Updating existing PR");
return [4 /*yield*/, api.pulls.update({
pull_number: existingPR.number,
base: config.baseBranch,
owner: owner,
repo: repo,
title: config.title,
body: config.body,
})];
case 3: return [2 /*return*/, _a.sent()];
case 4:
d("Creating a new PR");
return [4 /*yield*/, api.pulls.create({
base: config.baseBranch,
head: config.newBranchName,
owner: owner,
repo: repo,
title: config.title,
body: config.body,
})];
case 5: return [2 /*return*/, _a.sent()];
}
});
}); }; };
exports.createOrUpdatePR = createOrUpdatePR;
var createOrAddLabel = function (pr, api) {
return function (labelConfig, repoConfig) { return __awaiter(void 0, void 0, void 0, function () {
var config, label, existingLabels, e_1, e_2, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// Create or re-use an existing label
if (!repoConfig && !pr) {
throw new Error("To use createOrAddLabel without a PR you need to add a repoConfig arg");
}
config = repoConfig || (pr && { owner: pr.base.repo.owner.login, repo: pr.base.repo.name, id: pr.number });
d("Checking for existing labels");
label = null;
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, api.paginate("GET /repos/:owner/:repo/labels", {
owner: config.owner,
repo: config.repo,
})];
case 2:
existingLabels = _a.sent();
label = existingLabels.find(function (l) { return l.name == labelConfig.name; });
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
d("api.issues.getLabels gave an error", e_1);
return [3 /*break*/, 4];
case 4:
if (!!label) return [3 /*break*/, 8];
d("no label found, creating a new one for this repo");
_a.label = 5;
case 5:
_a.trys.push([5, 7, , 8]);
return [4 /*yield*/, api.issues.createLabel({
owner: config.owner,
repo: config.repo,
name: labelConfig.name,
color: labelConfig.color,
description: labelConfig.description,
})];
case 6:
_a.sent();
return [3 /*break*/, 8];
case 7:
e_2 = _a.sent();
d("api.issues.createLabel gave an error", e_2);
return [3 /*break*/, 8];
case 8:
d("adding a label to this pr");
_a.label = 9;
case 9:
_a.trys.push([9, 11, , 12]);
return [4 /*yield*/, api.issues.addLabels({
owner: config.owner,
repo: config.repo,
issue_number: config.id,
labels: [labelConfig.name],
})];
case 10:
_a.sent();
return [3 /*break*/, 12];
case 11:
e_3 = _a.sent();
d("api.issues.addLabels gave an error", e_3);
return [3 /*break*/, 12];
case 12: return [2 /*return*/];
}
});
}); };
};
exports.createOrAddLabel = createOrAddLabel;
exports.default = utils;
//# sourceMappingURL=GitHubUtils.js.map