

























@@ -3,6 +3,7 @@ import {
33candidateLabels,
44classifyPullRequestCandidateLabels,
55managedLabelSpecs,
6+runBarnacleAutoResponse,
67} from "../../scripts/github/barnacle-auto-response.mjs";
7889const blankTemplateBody = [
@@ -43,6 +44,80 @@ function file(filename: string, status = "modified") {
4344};
4445}
454647+function barnacleContext(pullRequest: Record<string, unknown>, labels: string[] = []) {
48+return {
49+repo: {
50+owner: "openclaw",
51+repo: "openclaw",
52+},
53+payload: {
54+action: "opened",
55+pull_request: {
56+number: 123,
57+title: "Cleanup plugin docs",
58+body: blankTemplateBody,
59+author_association: "CONTRIBUTOR",
60+user: {
61+login: "contributor",
62+},
63+labels: labels.map((name) => ({ name })),
64+ ...pullRequest,
65+},
66+},
67+};
68+}
69+70+function barnacleGithub(files: ReturnType<typeof file>[]) {
71+const calls = {
72+addLabels: [] as Array<{ issue_number: number; labels: string[] }>,
73+removeLabel: [] as Array<{ issue_number: number; name: string }>,
74+};
75+const github = {
76+paginate: async () => files,
77+rest: {
78+issues: {
79+addLabels: async (params: { issue_number: number; labels: string[] }) => {
80+calls.addLabels.push(params);
81+},
82+createComment: async () => undefined,
83+createLabel: async () => undefined,
84+getLabel: async (params: { name: string }) => ({
85+data: {
86+color:
87+managedLabelSpecs[params.name as keyof typeof managedLabelSpecs]?.color ?? "C5DEF5",
88+description:
89+managedLabelSpecs[params.name as keyof typeof managedLabelSpecs]?.description ?? "",
90+},
91+}),
92+lock: async () => undefined,
93+removeLabel: async (params: { issue_number: number; name: string }) => {
94+calls.removeLabel.push(params);
95+},
96+update: async () => undefined,
97+updateLabel: async () => undefined,
98+},
99+pulls: {
100+listFiles: async () => files,
101+},
102+repos: {
103+getCollaboratorPermissionLevel: async () => ({
104+data: {
105+role_name: "read",
106+},
107+}),
108+},
109+teams: {
110+getMembershipForUserInOrg: async () => {
111+const error = new Error("not found") as Error & { status: number };
112+error.status = 404;
113+throw error;
114+},
115+},
116+},
117+};
118+return { calls, github };
119+}
120+46121describe("barnacle-auto-response", () => {
47122it("keeps Barnacle-owned labels documented and ClawHub spelled correctly", () => {
48123expect(managedLabelSpecs["r: skill"].description).toContain("ClawHub");
@@ -119,4 +194,83 @@ describe("barnacle-auto-response", () => {
119194120195expect(labels).not.toContain(candidateLabels.dirtyCandidate);
121196});
197+198+it("does not add candidate labels to maintainer-authored PRs", async () => {
199+const { calls, github } = barnacleGithub([
200+file("ui/src/app.ts"),
201+file("src/gateway/server.ts"),
202+file("extensions/slack/src/index.ts"),
203+file("docs/plugins/community.md"),
204+]);
205+206+await runBarnacleAutoResponse({
207+ github,
208+context: barnacleContext({
209+author_association: "OWNER",
210+user: {
211+login: "maintainer",
212+},
213+}),
214+core: {
215+info: () => undefined,
216+},
217+});
218+219+expect(calls.addLabels).toEqual([]);
220+});
221+222+it("removes stale Barnacle candidate and PR-limit labels from maintainer-authored PRs", async () => {
223+const { calls, github } = barnacleGithub([
224+file("ui/src/app.ts"),
225+file("src/gateway/server.ts"),
226+file("extensions/slack/src/index.ts"),
227+file("docs/plugins/community.md"),
228+]);
229+230+await runBarnacleAutoResponse({
231+ github,
232+context: barnacleContext(
233+{
234+author_association: "OWNER",
235+user: {
236+login: "maintainer",
237+},
238+},
239+[candidateLabels.dirtyCandidate, "r: too-many-prs"],
240+),
241+core: {
242+info: () => undefined,
243+},
244+});
245+246+expect(calls.removeLabel).toEqual(
247+expect.arrayContaining([
248+expect.objectContaining({ name: candidateLabels.dirtyCandidate }),
249+expect.objectContaining({ name: "r: too-many-prs" }),
250+]),
251+);
252+});
253+254+it("still adds candidate labels to broad contributor PRs", async () => {
255+const { calls, github } = barnacleGithub([
256+file("ui/src/app.ts"),
257+file("src/gateway/server.ts"),
258+file("extensions/slack/src/index.ts"),
259+file("docs/plugins/community.md"),
260+]);
261+262+await runBarnacleAutoResponse({
263+ github,
264+context: barnacleContext({}),
265+core: {
266+info: () => undefined,
267+},
268+});
269+270+expect(calls.addLabels).toContainEqual(
271+expect.objectContaining({
272+labels: expect.arrayContaining([candidateLabels.dirtyCandidate]),
273+}),
274+);
275+});
122276});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。