chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
// Helper function to parse semantic version for comparison
|
||||
function parseSemanticVersion(version) {
|
||||
const versionStr = version.replace(/^v/, "");
|
||||
const cleanVersion = versionStr.replace(/rc\d+$/, "");
|
||||
const parts = cleanVersion.split(".").map(Number);
|
||||
|
||||
return {
|
||||
major: parts[0] || 0,
|
||||
minor: parts[1] || 0,
|
||||
micro: parts[2] || 0,
|
||||
isRc: versionStr.includes("rc"),
|
||||
original: version,
|
||||
};
|
||||
}
|
||||
|
||||
// Helper function to compare versions for sorting
|
||||
function compareVersions(a, b) {
|
||||
const versionA = parseSemanticVersion(a.tag_name);
|
||||
const versionB = parseSemanticVersion(b.tag_name);
|
||||
|
||||
// Compare major.minor.micro in descending order
|
||||
if (versionA.major !== versionB.major) {
|
||||
return versionB.major - versionA.major;
|
||||
}
|
||||
if (versionA.minor !== versionB.minor) {
|
||||
return versionB.minor - versionA.minor;
|
||||
}
|
||||
if (versionA.micro !== versionB.micro) {
|
||||
return versionB.micro - versionA.micro;
|
||||
}
|
||||
|
||||
// If versions are equal, prefer non-rc over rc
|
||||
if (versionA.isRc !== versionB.isRc) {
|
||||
return versionA.isRc ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module.exports = async ({ context, github, core }) => {
|
||||
const { owner, repo } = context.repo;
|
||||
const { base, number: pull_number } = context.payload.pull_request;
|
||||
if (base.ref.match(/^branch-\d+\.\d+$/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pr = await github.rest.pulls.get({
|
||||
owner,
|
||||
repo,
|
||||
pull_number,
|
||||
});
|
||||
const { body } = pr.data;
|
||||
|
||||
// Skip running this check if PR is filed by a bot (except GitHub Copilot)
|
||||
if (pr.data.user?.type?.toLowerCase() === "bot" && pr.data.user?.login !== "Copilot") {
|
||||
core.info(
|
||||
`Skipping processing because the PR is filed by a bot: ${pr.data.user?.login || "unknown"}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip running this check on CD automation PRs
|
||||
if (!body || body.trim() === "") {
|
||||
core.info("Skipping processing because the PR has no body.");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: remove the "yes/no" alternatives once all open PRs have switched to the new template
|
||||
const yesRegex = /- \[( |x)\] (yes \()?this PR (will be|is critical)/gi;
|
||||
const yesMatches = [...body.matchAll(yesRegex)];
|
||||
const yesMatch = yesMatches.length > 0 ? yesMatches[yesMatches.length - 1] : null;
|
||||
const yes = yesMatch ? yesMatch[1].toLowerCase() === "x" : false;
|
||||
// TODO: remove the "yes/no" alternatives once all open PRs have switched to the new template
|
||||
const noRegex = /- \[( |x)\] (no \()?this PR (will be|can wait)/gi;
|
||||
const noMatches = [...body.matchAll(noRegex)];
|
||||
const noMatch = noMatches.length > 0 ? noMatches[noMatches.length - 1] : null;
|
||||
const no = noMatch ? noMatch[1].toLowerCase() === "x" : false;
|
||||
|
||||
if (yes && no) {
|
||||
core.setFailed(
|
||||
"Both yes and no are selected. Please select only one in the patch release section."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!yes && !no) {
|
||||
core.setFailed("Please fill in the patch release section.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (no) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if a version label already exists
|
||||
const existingLabels = await github.rest.issues.listLabelsOnIssue({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
});
|
||||
|
||||
const versionLabelPattern = /^v\d+\.\d+\.\d+$/;
|
||||
const existingVersionLabel = existingLabels.data.find((label) =>
|
||||
versionLabelPattern.test(label.name)
|
||||
);
|
||||
|
||||
if (existingVersionLabel) {
|
||||
core.info(
|
||||
`Version label ${existingVersionLabel.name} already exists on this PR. Skipping label addition.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
|
||||
// Filter version tags that start with 'v', sort by semantic version, and select the latest
|
||||
const versionReleases = releases.data.filter(({ tag_name }) => tag_name.startsWith("v"));
|
||||
const sortedReleases = versionReleases.sort(compareVersions);
|
||||
const latest = sortedReleases[0];
|
||||
const version = latest.tag_name.replace("v", "");
|
||||
const [major, minor, micro] = version.replace(/rc\d+$/, "").split(".");
|
||||
const nextMicro = version.includes("rc") ? micro : (parseInt(micro) + 1).toString();
|
||||
const label = `v${major}.${minor}.${nextMicro}`;
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
labels: [label],
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user