Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04c695038f | |||
| e9a585ce47 | |||
| 7407b6cbc5 | |||
| 507efb0c25 |
+14
-5
@@ -275,11 +275,20 @@ export async function deleteProgressComment(ctx: ToolContext): Promise<boolean>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.octokit.rest.issues.deleteComment({
|
try {
|
||||||
owner: ctx.owner,
|
await ctx.octokit.rest.issues.deleteComment({
|
||||||
repo: ctx.name,
|
owner: ctx.owner,
|
||||||
comment_id: existingCommentId,
|
repo: ctx.name,
|
||||||
});
|
comment_id: existingCommentId,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// ignore 404 - comment already deleted
|
||||||
|
if (error instanceof Error && error.message.includes("Not Found")) {
|
||||||
|
// comment already deleted, continue
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reset state but mark as "updated" so ensureProgressCommentUpdated doesn't try to handle it
|
// reset state but mark as "updated" so ensureProgressCommentUpdated doesn't try to handle it
|
||||||
progressCommentId = null;
|
progressCommentId = null;
|
||||||
|
|||||||
+18
-12
@@ -123,19 +123,13 @@ export function StartReviewTool(ctx: ToolContext) {
|
|||||||
id: reviewId,
|
id: reviewId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log.debug(`review session started: id=${reviewId}, nodeId=${reviewNodeId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: `Review session started for PR #${pull_number}.`,
|
message: `Review session started for PR #${pull_number}.`,
|
||||||
guidance: {
|
instructions:
|
||||||
analyze: [
|
"Analyze: What does this PR change? Is the approach sound? What bugs, edge cases, or security issues exist? " +
|
||||||
"What does this PR change? Summarize in 1-2 sentences.",
|
"Before commenting: Skip nitpicks unless requested. Only comment if the codebase maintainer would care.",
|
||||||
"Is the approach sound? If not, stop and comment on approach first.",
|
|
||||||
"What bugs, edge cases, or security issues exist?",
|
|
||||||
],
|
|
||||||
beforeCommenting: [
|
|
||||||
"Skip nitpicks unless explicitly requested.",
|
|
||||||
"Would the codebase maintainer care about this feedback, based on what you can infer about the code quality standards in this repo?",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -166,8 +160,12 @@ export function AddReviewCommentTool(ctx: ToolContext) {
|
|||||||
throw new Error("No review session started. Call start_review first.");
|
throw new Error("No review session started. Call start_review first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
`adding review comment: reviewNodeId=${ctx.toolState.review.nodeId}, path=${path}, line=${line}, side=${side || "RIGHT"}`
|
||||||
|
);
|
||||||
|
|
||||||
// add comment thread via GraphQL (REST doesn't support adding to existing pending review)
|
// add comment thread via GraphQL (REST doesn't support adding to existing pending review)
|
||||||
await ctx.octokit.graphql<AddPullRequestReviewThreadResponse>(
|
const result = await ctx.octokit.graphql<AddPullRequestReviewThreadResponse>(
|
||||||
ADD_PULL_REQUEST_REVIEW_THREAD,
|
ADD_PULL_REQUEST_REVIEW_THREAD,
|
||||||
{
|
{
|
||||||
pullRequestReviewId: ctx.toolState.review.nodeId,
|
pullRequestReviewId: ctx.toolState.review.nodeId,
|
||||||
@@ -178,9 +176,12 @@ export function AddReviewCommentTool(ctx: ToolContext) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
log.debug(`review comment added: threadId=${result.addPullRequestReviewThread.thread.id}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: `Comment added to ${path}:${line}`,
|
message: `Comment added to ${path}:${line}`,
|
||||||
|
threadId: result.addPullRequestReviewThread.thread.id,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -211,6 +212,9 @@ export function SubmitReviewTool(ctx: ToolContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reviewId = ctx.toolState.review.id;
|
const reviewId = ctx.toolState.review.id;
|
||||||
|
log.debug(
|
||||||
|
`submitting review: id=${reviewId}, nodeId=${ctx.toolState.review.nodeId}, prNumber=${ctx.toolState.prNumber}`
|
||||||
|
);
|
||||||
|
|
||||||
// build quick links footer
|
// build quick links footer
|
||||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||||
@@ -234,6 +238,8 @@ export function SubmitReviewTool(ctx: ToolContext) {
|
|||||||
body: bodyWithFooter,
|
body: bodyWithFooter,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
log.debug(`review submitted: reviewId=${result.data.id}, state=${result.data.state}`);
|
||||||
|
|
||||||
// clear review state
|
// clear review state
|
||||||
delete ctx.toolState.review;
|
delete ctx.toolState.review;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pullfrog/action",
|
"name": "@pullfrog/action",
|
||||||
"version": "0.0.149",
|
"version": "0.0.151",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"index.js",
|
"index.js",
|
||||||
|
|||||||
+4
-4
@@ -36,8 +36,8 @@ export interface WorkflowRunInfo {
|
|||||||
export async function fetchWorkflowRunInfo(runId: string): Promise<WorkflowRunInfo> {
|
export async function fetchWorkflowRunInfo(runId: string): Promise<WorkflowRunInfo> {
|
||||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
|
||||||
// add timeout to prevent hanging (5 seconds)
|
// add timeout to prevent hanging (30 seconds)
|
||||||
const timeoutMs = 5000;
|
const timeoutMs = 30000;
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
||||||
|
|
||||||
@@ -90,8 +90,8 @@ export async function getRepoSettings(
|
|||||||
): Promise<RepoSettings> {
|
): Promise<RepoSettings> {
|
||||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
|
||||||
// Add timeout to prevent hanging (5 seconds)
|
// Add timeout to prevent hanging (30 seconds)
|
||||||
const timeoutMs = 5000;
|
const timeoutMs = 30000;
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -342,12 +342,11 @@ export const log = {
|
|||||||
*/
|
*/
|
||||||
toolCall: ({ toolName, input }: { toolName: string; input: unknown }): void => {
|
toolCall: ({ toolName, input }: { toolName: string; input: unknown }): void => {
|
||||||
const inputFormatted = formatJsonValue(input);
|
const inputFormatted = formatJsonValue(input);
|
||||||
// if (inputFormatted !== "{}")
|
const timestamp = isDebugEnabled() ? ` [${new Date().toISOString()}]` : "";
|
||||||
const output = inputFormatted !== "{}" ? `${toolName}(${inputFormatted})` : `${toolName}()`;
|
const output =
|
||||||
|
inputFormatted !== "{}"
|
||||||
// if (inputFormatted !== "{}") {
|
? `→ ${toolName}(${inputFormatted})${timestamp}`
|
||||||
// output += formatIndentedField("input", inputFormatted);
|
: `→ ${toolName}()${timestamp}`;
|
||||||
// }
|
|
||||||
|
|
||||||
log.info(output.trimEnd());
|
log.info(output.trimEnd());
|
||||||
},
|
},
|
||||||
|
|||||||
+5
-6
@@ -48,17 +48,16 @@ function isGitHubActionsEnvironment(): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function acquireTokenViaOIDC(): Promise<string> {
|
async function acquireTokenViaOIDC(): Promise<string> {
|
||||||
log.debug("» generating OIDC token...");
|
log.info("» generating OIDC token...");
|
||||||
|
|
||||||
const oidcToken = await core.getIDToken("pullfrog-api");
|
const oidcToken = await core.getIDToken("pullfrog-api");
|
||||||
log.debug("» OIDC token generated successfully");
|
|
||||||
|
|
||||||
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
const apiUrl = process.env.API_URL || "https://pullfrog.com";
|
||||||
|
|
||||||
log.debug("» exchanging OIDC token for installation token...");
|
log.info("» exchanging OIDC token for installation token...");
|
||||||
|
|
||||||
// Add timeout to prevent long waits (5 seconds)
|
// Add timeout to prevent long waits (30 seconds)
|
||||||
const timeoutMs = 5000;
|
const timeoutMs = 30000;
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ async function acquireTokenViaOIDC(): Promise<string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tokenData = (await tokenResponse.json()) as InstallationToken;
|
const tokenData = (await tokenResponse.json()) as InstallationToken;
|
||||||
log.debug(`» installation token obtained for ${tokenData.repository || "all repositories"}`);
|
log.info(`» installation token obtained for ${tokenData.repository || "all repositories"}`);
|
||||||
|
|
||||||
return tokenData.token;
|
return tokenData.token;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user