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
4 changes: 2 additions & 2 deletions src/bugbotMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ export class BugbotMonitor {
// ============================================================

private computeSinceForRepo(repo: string): string | undefined {
if (this.state.hasFailedBugsForRepo(repo)) {
logger.debug("Skipping since filter to retry failed bugs.", { repo });
if (this.state.hasRetryableBugsForRepo(repo)) {
logger.debug("Skipping since filter to retry failed/skipped bugs.", { repo });
return undefined;
}
const lookbackMs = DEFAULT_LOOKBACK_DAYS * 24 * 60 * 60 * 1000;
Expand Down
33 changes: 33 additions & 0 deletions src/githubClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,39 @@ export class GitHubClient {

return data.id;
}

async hasIssueCommentContaining(
owner: string,
repo: string,
prNumber: number,
marker: string
): Promise<boolean> {
logger.debug("Checking for existing issue comment with marker.", {
owner,
repo,
prNumber,
});

const octokit = await this.getOctokitForOwner(owner);

for await (const response of octokit.paginate.iterator(
octokit.rest.issues.listComments,
{
owner,
repo,
issue_number: prNumber,
per_page: 100,
}
)) {
for (const comment of response.data) {
if (comment.body?.includes(marker)) {
return true;
}
}
}

return false;
}
}

// ============================================================
Expand Down
60 changes: 58 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { StateStore } from "./state.js";
import type { Config, FixResult, PrBugReport } from "./types.js";

const AUTOFIX_COMMENT_MARKER = "<!-- BUGBOT_AUTOFIX_COMMENT -->";
const AUTOFIX_NO_CHANGES_MARKER = "<!-- BUGBOT_AUTOFIX_NO_CHANGES -->";

class FixoolyDaemon {
private config: Config;
Expand Down Expand Up @@ -211,17 +212,19 @@ class FixoolyDaemon {
}
);
} else {
await this.postNoChangesComment(pr, bugs);

this.state.recordProcessedBugs(
bugs.map((b) => ({
bugId: b.bugId,
repo: repoFullName,
prNumber: pr.number,
})),
null
"SKIPPED_NO_CHANGES"
);

logger.info(
`No changes made for PR #${pr.number}. Bugs recorded as processed.`,
`No changes made for PR #${pr.number}. Bugs recorded as skipped.`,
{ prNumber: pr.number, repo: repoFullName }
);
}
Expand Down Expand Up @@ -289,6 +292,59 @@ class FixoolyDaemon {
}
}

// ============================================================
// Post no-changes comment on the PR
// ============================================================

private async postNoChangesComment(
pr: { owner: string; repo: string; number: number },
bugs: import("./types.js").BugbotBug[]
): Promise<void> {
try {
const alreadyPosted = await this.github.hasIssueCommentContaining(
pr.owner,
pr.repo,
pr.number,
AUTOFIX_NO_CHANGES_MARKER
);
if (alreadyPosted) {
logger.debug("No-changes comment already exists on PR, skipping.", {
prNumber: pr.number,
repo: `${pr.owner}/${pr.repo}`,
});
return;
}

const bugList = bugs
.map((b) => `- ⏭️ Skipped: **${b.title}**`)
.join("\n");

const body =
`${AUTOFIX_COMMENT_MARKER}\n${AUTOFIX_NO_CHANGES_MARKER}\n` +
`[Fixooly](https://github.com/Senna46/fixooly) ` +
`analyzed ${bugs.length} bug(s) but determined no code changes were needed.\n\n` +
bugList;

await this.github.createIssueComment(
pr.owner,
pr.repo,
pr.number,
body
);
logger.debug("Posted no-changes comment on PR.", {
prNumber: pr.number,
repo: `${pr.owner}/${pr.repo}`,
});
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
logger.warn("Failed to post no-changes comment on PR.", {
error: message,
prNumber: pr.number,
repo: `${pr.owner}/${pr.repo}`,
});
}
}

// ============================================================
// Shutdown
// ============================================================
Expand Down
4 changes: 2 additions & 2 deletions src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export class StateStore {
const row = this.db
.prepare("SELECT fix_commit_sha FROM processed_bugs WHERE bug_id = ?")
.get(bugId) as { fix_commit_sha: string | null } | undefined;
// Bugs marked as FAILED should be retried
// Only FAILED bugs should be retried; SKIPPED_NO_CHANGES is terminal
return row !== undefined && row.fix_commit_sha !== "FAILED";
}

hasFailedBugsForRepo(repo: string): boolean {
hasRetryableBugsForRepo(repo: string): boolean {
const row = this.db
.prepare(
"SELECT 1 FROM processed_bugs WHERE fix_commit_sha = 'FAILED' AND repo = ? LIMIT 1"
Expand Down