mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(ci): evaluate duplicate proof sections
This commit is contained in:
@@ -143,22 +143,34 @@ export async function isMaintainerTeamMember({
|
||||
return body?.state === "active";
|
||||
}
|
||||
|
||||
function extractMarkdownSection(headingRegex, body = "") {
|
||||
function extractMarkdownSections(headingRegex, body = "") {
|
||||
// Normalize CRLF → LF so regexes and section slicing see GitHub web-editor PR
|
||||
// bodies the same way as locally-authored Markdown.
|
||||
const normalizedBody = normalizeLineEndings(body);
|
||||
const match = headingRegex.exec(normalizedBody);
|
||||
if (!match) {
|
||||
return "";
|
||||
const sections = [];
|
||||
const matcher = new RegExp(
|
||||
headingRegex.source,
|
||||
headingRegex.flags.includes("g") ? headingRegex.flags : `${headingRegex.flags}g`,
|
||||
);
|
||||
for (const match of normalizedBody.matchAll(matcher)) {
|
||||
const sectionStart = match.index + match[0].length;
|
||||
const rest = normalizedBody.slice(sectionStart);
|
||||
const nextHeading = rest.match(/\n#{1,6}\s+\S/);
|
||||
sections.push((nextHeading ? rest.slice(0, nextHeading.index) : rest).trim());
|
||||
}
|
||||
const sectionStart = match.index + match[0].length;
|
||||
const rest = normalizedBody.slice(sectionStart);
|
||||
const nextHeading = rest.match(/\n#{1,6}\s+\S/);
|
||||
return (nextHeading ? rest.slice(0, nextHeading.index) : rest).trim();
|
||||
return sections;
|
||||
}
|
||||
|
||||
function extractMarkdownSection(headingRegex, body = "") {
|
||||
return extractMarkdownSections(headingRegex, body)[0] ?? "";
|
||||
}
|
||||
|
||||
export function extractRealBehaviorProofSections(body = "") {
|
||||
return extractMarkdownSections(/^#{2,6}\s+real behavior proof\b[^\n]*$/im, body);
|
||||
}
|
||||
|
||||
export function extractRealBehaviorProofSection(body = "") {
|
||||
return extractMarkdownSection(/^#{2,6}\s+real behavior proof\b[^\n]*$/im, body);
|
||||
return extractRealBehaviorProofSections(body)[0] ?? "";
|
||||
}
|
||||
|
||||
function extractOutOfScopeFollowUpsSection(body = "") {
|
||||
@@ -298,24 +310,7 @@ export function evaluateClawSweeperExactHeadProof({ pullRequest, comments = [] }
|
||||
return result("insufficient", "No exact-head ClawSweeper proof verdict was found.");
|
||||
}
|
||||
|
||||
export function evaluateRealBehaviorProof({ pullRequest, labels } = {}) {
|
||||
const currentLabels = labels ?? pullRequest?.labels ?? [];
|
||||
if (hasProofOverride(currentLabels)) {
|
||||
return result("override", `Maintainer override label ${PROOF_OVERRIDE_LABEL} is present.`);
|
||||
}
|
||||
if (!isExternalPullRequest(pullRequest)) {
|
||||
return result("skipped", "Maintainer, collaborator, or bot PRs do not require this gate.");
|
||||
}
|
||||
|
||||
const body = pullRequest?.body ?? "";
|
||||
const section = extractRealBehaviorProofSection(body);
|
||||
if (!section) {
|
||||
return result(
|
||||
"missing",
|
||||
"External PRs must include a Real behavior proof section with after-fix evidence from a real setup.",
|
||||
);
|
||||
}
|
||||
|
||||
function evaluateRealBehaviorProofSection(section, body) {
|
||||
const fields = Object.fromEntries(
|
||||
requiredProofFields.map((field) => [field.key, extractFieldValue(section, field)]),
|
||||
);
|
||||
@@ -378,6 +373,28 @@ export function evaluateRealBehaviorProof({ pullRequest, labels } = {}) {
|
||||
return result("passed", "External PR includes after-fix real behavior proof.", { fields });
|
||||
}
|
||||
|
||||
export function evaluateRealBehaviorProof({ pullRequest, labels } = {}) {
|
||||
const currentLabels = labels ?? pullRequest?.labels ?? [];
|
||||
if (hasProofOverride(currentLabels)) {
|
||||
return result("override", `Maintainer override label ${PROOF_OVERRIDE_LABEL} is present.`);
|
||||
}
|
||||
if (!isExternalPullRequest(pullRequest)) {
|
||||
return result("skipped", "Maintainer, collaborator, or bot PRs do not require this gate.");
|
||||
}
|
||||
|
||||
const body = pullRequest?.body ?? "";
|
||||
const sections = extractRealBehaviorProofSections(body);
|
||||
if (sections.length === 0) {
|
||||
return result(
|
||||
"missing",
|
||||
"External PRs must include a Real behavior proof section with after-fix evidence from a real setup.",
|
||||
);
|
||||
}
|
||||
|
||||
const latestSection = sections.at(-1) ?? "";
|
||||
return evaluateRealBehaviorProofSection(latestSection, body);
|
||||
}
|
||||
|
||||
export function labelsForRealBehaviorProof(evaluation) {
|
||||
if (evaluation.status === "passed") {
|
||||
return [PROOF_SUPPLIED_LABEL];
|
||||
|
||||
Reference in New Issue
Block a user