backport
Version:
A CLI tool that automates the process of backporting commits
137 lines • 6.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTargetBranchFromLabel = exports.getPullRequestStates = void 0;
const lodash_1 = require("lodash");
const filterEmpty_1 = require("../../utils/filterEmpty");
const commitFormatters_1 = require("../github/commitFormatters");
const getSourcePullRequest_1 = require("./getSourcePullRequest");
const isPullRequestCrossReferencedEvent_1 = require("./isPullRequestCrossReferencedEvent");
function mergeByKey(obj1, obj2, key) {
const merged = (0, lodash_1.merge)((0, lodash_1.keyBy)(obj1, key), (0, lodash_1.keyBy)(obj2, key));
const a = (0, lodash_1.values)(merged);
return a;
}
function getPullRequestStates({ sourceCommit, branchLabelMapping, }) {
const sourcePullRequest = (0, getSourcePullRequest_1.getSourcePullRequest)(sourceCommit);
// if there is no source pull request the commit was pushed directly to the source branch
// in that case there will be no labels, and thus not possible to deduce the expected target branches
if (!sourcePullRequest) {
return [];
}
const createdTargetPullRequests = getCreatedTargetPullRequests(sourceCommit);
// if there's no `branchLabelMapping`, it's not possible to determine the missing target branches
if (!branchLabelMapping) {
return createdTargetPullRequests;
}
const targetBranchesFromLabels = getTargetBranchesFromLabels(sourcePullRequest, branchLabelMapping);
const allTargetBranches = mergeByKey(targetBranchesFromLabels, createdTargetPullRequests, 'branch');
return allTargetBranches.map((res) => {
if (res.state) {
return { ...res, state: res.state };
}
// MERGED (source branch)
if (res.isSourceBranch) {
return {
...res,
state: 'MERGED',
url: sourcePullRequest.url,
number: sourcePullRequest.number,
mergeCommit: sourcePullRequest.mergeCommit
? {
message: sourcePullRequest.mergeCommit.message,
sha: sourcePullRequest.mergeCommit.sha,
}
: undefined,
};
}
// NOT_CREATED
return { ...res, state: 'NOT_CREATED' };
});
}
exports.getPullRequestStates = getPullRequestStates;
function getCreatedTargetPullRequests(sourceCommit) {
const sourcePullRequest = (0, getSourcePullRequest_1.getSourcePullRequest)(sourceCommit);
if (!sourcePullRequest) {
return [];
}
const sourceCommitMessage = (0, commitFormatters_1.getFirstLine)(sourceCommit.message);
return (sourcePullRequest.timelineItems.edges ?? [])
.filter(filterEmpty_1.filterNil)
.filter(isPullRequestCrossReferencedEvent_1.isPullRequestCrossReferencedEvent)
.filter((item) => {
const { targetPullRequest } = item.node;
// ignore closed PRs
if (targetPullRequest.state === 'CLOSED') {
return false;
}
// at least one of the commits in `targetPullRequest` should match the merge commit from the source pull request
const didCommitMatch = targetPullRequest.commits.edges?.some((commitEdge) => {
const targetCommit = commitEdge?.node?.targetCommit;
if (!targetCommit) {
return false;
}
const matchingRepoName = sourceCommit.repository.name === targetPullRequest.repository.name;
const matchingRepoOwner = sourceCommit.repository.owner.login ===
targetPullRequest.repository.owner.login;
const targetCommitMessage = (0, commitFormatters_1.getFirstLine)(targetCommit.message);
const matchingMessage = targetCommitMessage === sourceCommitMessage;
return matchingRepoName && matchingRepoOwner && matchingMessage;
});
const titleIncludesMessage = targetPullRequest.title.includes(sourceCommitMessage);
const titleIncludesNumber = targetPullRequest.title.includes(sourcePullRequest.number.toString());
return didCommitMatch || (titleIncludesMessage && titleIncludesNumber);
})
.map((item) => {
const { targetPullRequest } = item.node;
return {
url: targetPullRequest.url,
number: targetPullRequest.number,
branch: targetPullRequest.baseRefName,
state: targetPullRequest.state,
mergeCommit: targetPullRequest.targetMergeCommit
? {
sha: targetPullRequest.targetMergeCommit.sha,
message: targetPullRequest.targetMergeCommit.message,
}
: undefined,
};
});
}
function getTargetBranchesFromLabels(sourcePullRequest, branchLabelMapping) {
const targetBranchesFromLabels = sourcePullRequest.labels?.nodes
?.map((label) => label?.name)
.filter(filterEmpty_1.filterNil)
.map((label) => {
const res = getTargetBranchFromLabel({ branchLabelMapping, label });
if (res) {
const { branchLabelMappingKey, targetBranch } = res;
const isSourceBranch = targetBranch === sourcePullRequest.baseRefName;
return {
branch: targetBranch,
label,
branchLabelMappingKey,
isSourceBranch,
};
}
})
.filter(filterEmpty_1.filterNil);
return (0, lodash_1.uniqBy)(targetBranchesFromLabels, ({ branch }) => branch);
}
function getTargetBranchFromLabel({ branchLabelMapping, label, }) {
// only get first match
const result = Object.entries(branchLabelMapping).find(([key]) => {
const regex = new RegExp(key);
const isMatch = label.match(regex) !== null;
return isMatch;
});
if (result) {
const [branchLabelMappingKey, branchLabelMappingValue] = result;
const regex = new RegExp(branchLabelMappingKey);
const targetBranch = label.replace(regex, branchLabelMappingValue);
if (targetBranch) {
return { targetBranch, branchLabelMappingKey };
}
}
}
exports.getTargetBranchFromLabel = getTargetBranchFromLabel;
//# sourceMappingURL=getPullRequestStates.js.map