Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/commands/openclawcode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,39 @@ describe("openclawCodeRunCommand", () => {
expect(payload.verificationFollowUpCount).toBe(2);
});

it("prints docs-only webhook smoke test signals derived from the issue run", async () => {
mocks.runIssueWorkflow.mockResolvedValue(
createRun({
issue: {
owner: "openclaw",
repo: "openclaw",
number: 40,
title: "[Feature]: Webhook auto-intake smoke test after public tunnel setup",
},
buildResult: {
branchName: "openclawcode/issue-40",
summary: "Create a tiny docs-only smoke test issue for webhook tunnel validation.",
changedFiles: ["docs/openclawcode/webhook-smoke-test.md"],
issueClassification: "command-layer",
scopeCheck: {
ok: true,
blockedFiles: [],
summary: "Scope check passed for command-layer issue.",
},
testCommands: [],
testResults: [],
notes: [],
},
}),
);

await openclawCodeRunCommand({ issue: "40", repoRoot: "/repo", json: true }, runtime);

const payload = JSON.parse(runtime.log.mock.calls[0]?.[0] ?? "null");
expect(payload.issueDocsOnly).toBe(true);
expect(payload.issueWebhookSmokeTest).toBe(true);
});

it("prints failed auto-merge disposition when merge execution fails", async () => {
mocks.runIssueWorkflow.mockResolvedValue(
createRun({
Expand Down
20 changes: 20 additions & 0 deletions src/commands/openclawcode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,24 @@ function resolveVerificationApprovedForHumanReview(run: WorkflowRun): boolean |
return decision === "approve-for-human-review";
}

function resolveIssueDocsOnly(run: WorkflowRun): boolean {
const changedFiles = run.buildResult?.changedFiles;
if (!changedFiles || changedFiles.length === 0) {
return false;
}

return changedFiles.every((file) => file.startsWith("docs/"));
}

function resolveIssueWebhookSmokeTest(run: WorkflowRun): boolean {
const content = [run.issue.title, run.buildResult?.summary]
.filter((value): value is string => Boolean(value))
.join(" ")
.toLowerCase();

return content.includes("webhook") && content.includes("smoke test");
}

function toWorkflowRunJson(run: WorkflowRun) {
const autoMergePolicy = resolveAutoMergePolicy(run);
const autoMergeDisposition = resolveAutoMergeDisposition(run);
Expand All @@ -251,6 +269,8 @@ function toWorkflowRunJson(run: WorkflowRun) {
changeDisposition: changeDisposition.changeDisposition,
changeDispositionReason: changeDisposition.changeDispositionReason,
issueClassification: run.buildResult?.issueClassification ?? null,
issueDocsOnly: resolveIssueDocsOnly(run),
issueWebhookSmokeTest: resolveIssueWebhookSmokeTest(run),
scopeCheck: run.buildResult?.scopeCheck ?? null,
scopeCheckSummary: run.buildResult?.scopeCheck?.summary ?? null,
scopeCheckPassed: run.buildResult?.scopeCheck?.ok ?? null,
Expand Down
Loading