mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-23 02:35:21 +00:00
* ci(proof): trust maintainer label for private org members Private organization memberships report author_association=CONTRIBUTOR on PRs, so the real-behavior-proof gate currently demands proof from maintainers whose membership is private. The labeler workflow already applies the 'maintainer' label via the team-membership API (which sees private members), so treat that label as an equivalent privileged signal in evaluateRealBehaviorProof. * ci(proof): drop noisy comments * ci(proof): check maintainer team membership via GitHub App token Replace the label-based private-maintainer skip with a direct getMembershipForUserInOrg call using a minted GitHub App token, mirroring the pattern labeler.yml already uses for the same lookup. Removes the race against the labeler workflow and the implicit dependency on the 'maintainer' label having landed first. The App-token steps are continue-on-error so the gate still runs (using the existing author_association path) when the App key secrets are absent or both mints fail. * ci(proof): narrow App token to members:read ClawSweeper review #83418: actions/create-github-app-token defaults to the full installation permission set, but the proof gate only needs the org-members read scope used by teams.getMembershipForUserInOrg. Set permission-members: read on both the primary and fallback mint steps. * docs(changelog): private maintainers skip the real-behavior-proof gate
56 lines
1.9 KiB
JavaScript
56 lines
1.9 KiB
JavaScript
#!/usr/bin/env node
|
|
import { readFileSync } from "node:fs";
|
|
import {
|
|
evaluateRealBehaviorProof,
|
|
isMaintainerTeamMember,
|
|
} from "./real-behavior-proof-policy.mjs";
|
|
|
|
function escapeCommandValue(value) {
|
|
return String(value)
|
|
.replace(/%/g, "%25")
|
|
.replace(/\r/g, "%0D")
|
|
.replace(/\n/g, "%0A")
|
|
.replace(/:/g, "%3A");
|
|
}
|
|
|
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
if (!eventPath) {
|
|
console.error("::error title=Real behavior proof failed::GITHUB_EVENT_PATH is not set.");
|
|
process.exit(1);
|
|
}
|
|
|
|
const event = JSON.parse(readFileSync(eventPath, "utf8"));
|
|
const pullRequest = event.pull_request;
|
|
if (!pullRequest) {
|
|
console.log("No pull_request payload found; skipping real behavior proof gate.");
|
|
process.exit(0);
|
|
}
|
|
|
|
const token = process.env.GH_APP_TOKEN;
|
|
const org = event.repository?.owner?.login;
|
|
const authorLogin = pullRequest.user?.login;
|
|
if (token && org && authorLogin) {
|
|
try {
|
|
if (await isMaintainerTeamMember({ token, org, login: authorLogin })) {
|
|
console.log(
|
|
`PR author @${authorLogin} is an active member of the ${org}/maintainer team; skipping real behavior proof gate.`,
|
|
);
|
|
process.exit(0);
|
|
}
|
|
} catch (error) {
|
|
console.warn(
|
|
`::warning title=Maintainer membership check failed::${escapeCommandValue(error?.message ?? String(error))}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const evaluation = evaluateRealBehaviorProof({ pullRequest });
|
|
if (evaluation.passed) {
|
|
console.log(evaluation.reason);
|
|
process.exit(0);
|
|
}
|
|
|
|
const message = `${evaluation.reason} Add after-fix evidence from a real OpenClaw setup in the PR body. Screenshots, recordings, terminal screenshots, console output, redacted runtime logs, linked artifacts, or copied live output count. Unit tests, mocks, snapshots, lint, typechecks, and CI are supplemental only. A maintainer can apply proof: override when appropriate.`;
|
|
console.error(`::error title=Real behavior proof required::${escapeCommandValue(message)}`);
|
|
process.exit(1);
|