mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
CI: add Barnacle r: too-many-prs guard
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
8
.github/workflows/auto-response.yml
vendored
8
.github/workflows/auto-response.yml
vendored
@@ -35,6 +35,7 @@ jobs:
|
|||||||
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
|
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
|
||||||
script: |
|
script: |
|
||||||
// Labels prefixed with "r:" are auto-response triggers.
|
// Labels prefixed with "r:" are auto-response triggers.
|
||||||
|
const activePrLimit = 10;
|
||||||
const rules = [
|
const rules = [
|
||||||
{
|
{
|
||||||
label: "r: skill",
|
label: "r: skill",
|
||||||
@@ -48,6 +49,13 @@ jobs:
|
|||||||
message:
|
message:
|
||||||
"Please use [our support server](https://discord.gg/clawd) and ask in #help or #users-helping-users to resolve this, or follow the stuck FAQ at https://docs.openclaw.ai/help/faq#im-stuck-whats-the-fastest-way-to-get-unstuck.",
|
"Please use [our support server](https://discord.gg/clawd) and ask in #help or #users-helping-users to resolve this, or follow the stuck FAQ at https://docs.openclaw.ai/help/faq#im-stuck-whats-the-fastest-way-to-get-unstuck.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "r: too-many-prs",
|
||||||
|
close: true,
|
||||||
|
message:
|
||||||
|
`Closing this PR because the author has more than ${activePrLimit} active PRs in this repo. ` +
|
||||||
|
"Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "r: testflight",
|
label: "r: testflight",
|
||||||
close: true,
|
close: true,
|
||||||
|
|||||||
145
.github/workflows/labeler.yml
vendored
145
.github/workflows/labeler.yml
vendored
@@ -201,6 +201,151 @@ jobs:
|
|||||||
labels: [trustedLabel],
|
labels: [trustedLabel],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
- name: Apply too-many-prs label
|
||||||
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const pullRequest = context.payload.pull_request;
|
||||||
|
if (!pullRequest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const activePrLimitLabel = "r: too-many-prs";
|
||||||
|
const activePrLimit = 10;
|
||||||
|
const labelColor = "B60205";
|
||||||
|
const labelDescription = `Author has more than ${activePrLimit} active PRs in this repo`;
|
||||||
|
const authorLogin = pullRequest.user?.login;
|
||||||
|
if (!authorLogin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelNames = new Set(
|
||||||
|
(pullRequest.labels ?? [])
|
||||||
|
.map((label) => (typeof label === "string" ? label : label?.name))
|
||||||
|
.filter((name) => typeof name === "string"),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ensureLabelExists = async () => {
|
||||||
|
try {
|
||||||
|
await github.rest.issues.getLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
name: activePrLimitLabel,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 404) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
await github.rest.issues.createLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
name: activePrLimitLabel,
|
||||||
|
color: labelColor,
|
||||||
|
description: labelDescription,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPrivilegedAuthor = async () => {
|
||||||
|
if (pullRequest.author_association === "OWNER") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isMaintainer = false;
|
||||||
|
try {
|
||||||
|
const membership = await github.rest.teams.getMembershipForUserInOrg({
|
||||||
|
org: context.repo.owner,
|
||||||
|
team_slug: "maintainer",
|
||||||
|
username: authorLogin,
|
||||||
|
});
|
||||||
|
isMaintainer = membership?.data?.state === "active";
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 404) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMaintainer) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const permission = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
username: authorLogin,
|
||||||
|
});
|
||||||
|
const roleName = (permission?.data?.role_name ?? "").toLowerCase();
|
||||||
|
return roleName === "admin" || roleName === "maintain";
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 404) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (await isPrivilegedAuthor()) {
|
||||||
|
if (labelNames.has(activePrLimitLabel)) {
|
||||||
|
try {
|
||||||
|
await github.rest.issues.removeLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: pullRequest.number,
|
||||||
|
name: activePrLimitLabel,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 404) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let openPrCount = 0;
|
||||||
|
try {
|
||||||
|
const result = await github.rest.search.issuesAndPullRequests({
|
||||||
|
q: `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:${authorLogin}`,
|
||||||
|
per_page: 1,
|
||||||
|
});
|
||||||
|
openPrCount = result?.data?.total_count ?? 0;
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 422) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
core.warning(`Skipping open PR count for ${authorLogin}; treating as 0.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openPrCount > activePrLimit) {
|
||||||
|
await ensureLabelExists();
|
||||||
|
if (!labelNames.has(activePrLimitLabel)) {
|
||||||
|
await github.rest.issues.addLabels({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: pullRequest.number,
|
||||||
|
labels: [activePrLimitLabel],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelNames.has(activePrLimitLabel)) {
|
||||||
|
try {
|
||||||
|
await github.rest.issues.removeLabel({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: pullRequest.number,
|
||||||
|
name: activePrLimitLabel,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.status !== 404) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
backfill-pr-labels:
|
backfill-pr-labels:
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
|||||||
Reference in New Issue
Block a user