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
36 changes: 36 additions & 0 deletions src/commands/openclawcode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,42 @@ describe("openclawCodeRunCommand", () => {
expect(payload.publishedPullRequestOpenedAt).toBe("2026-01-01T00:00:00.000Z");
});

it("reports publishedPullRequestHasOpenedAt as false when the published pr has no openedAt", async () => {
mocks.runIssueWorkflow.mockResolvedValue(
createRun({
draftPullRequest: {
...createRun().draftPullRequest!,
openedAt: undefined,
},
}),
);

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

const payload = JSON.parse(runtime.log.mock.calls[0]?.[0] ?? "null");
expect(payload.pullRequestPublished).toBe(true);
expect(payload.publishedPullRequestHasOpenedAt).toBe(false);
expect(payload.publishedPullRequestOpenedAt).toBeNull();
});

it("reports publishedPullRequestHasOpenedAt as true when the published pr has openedAt", async () => {
mocks.runIssueWorkflow.mockResolvedValue(
createRun({
draftPullRequest: {
...createRun().draftPullRequest!,
openedAt: "2026-01-02T00:00:00.000Z",
},
}),
);

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

const payload = JSON.parse(runtime.log.mock.calls[0]?.[0] ?? "null");
expect(payload.pullRequestPublished).toBe(true);
expect(payload.publishedPullRequestHasOpenedAt).toBe(true);
expect(payload.publishedPullRequestOpenedAt).toBe("2026-01-02T00:00:00.000Z");
});

it("treats blank published pull request bodies as absent in convenience signals", async () => {
mocks.runIssueWorkflow.mockResolvedValue(
createRun({
Expand Down
22 changes: 21 additions & 1 deletion src/commands/openclawcode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,25 @@ function resolveOperatorStateDir(stateDir?: string): string {
return path.resolve(stateDir ?? envStateDir ?? path.join(os.homedir(), ".openclaw"));
}

function hasPublishedPullRequestOpenedAt(
openedAt: WorkflowRun["draftPullRequest"] extends infer DraftPullRequest
? DraftPullRequest extends { openedAt?: infer OpenedAt }
? OpenedAt
: never
: never,
): boolean {
if (openedAt === true) {
return true;
}
if (typeof openedAt === "string") {
return openedAt.length > 0;
}
if (Array.isArray(openedAt)) {
return openedAt.length > 0;
}
return false;
}

function resolvePublishedPullRequest(run: WorkflowRun): {
pullRequestPublished: boolean;
publishedPullRequestNumber: number | null;
Expand All @@ -1502,7 +1521,8 @@ function resolvePublishedPullRequest(run: WorkflowRun): {
publishedPullRequestNumber: published ? (run.draftPullRequest?.number ?? null) : null,
publishedPullRequestHasNumber: published && run.draftPullRequest?.number != null,
publishedPullRequestHasUrl: published && run.draftPullRequest?.url != null,
publishedPullRequestHasOpenedAt: published && run.draftPullRequest?.openedAt != null,
publishedPullRequestHasOpenedAt:
published && hasPublishedPullRequestOpenedAt(run.draftPullRequest?.openedAt),
publishedPullRequestHasTitle:
published && (run.draftPullRequest?.title?.trim().length ?? 0) > 0,
publishedPullRequestHasBody: published && (run.draftPullRequest?.body?.trim().length ?? 0) > 0,
Expand Down
Loading