mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
feat: add sticky_comment input to reduce GitHub comment spam (#211)
* feat: no claude spam * feat: add silent property * feat: add silent property * feat: add silent property * chore: call me a sticky comment * chore: applying review comments * chore: apply review comments * format * reword --------- Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
bcb072b63f
commit
79f2086fce
@@ -85,6 +85,7 @@ jobs:
|
||||
| `base_branch` | The base branch to use for creating new branches (e.g., 'main', 'develop') | No | - |
|
||||
| `max_turns` | Maximum number of conversation turns Claude can take (limits back-and-forth exchanges) | No | - |
|
||||
| `timeout_minutes` | Timeout in minutes for execution | No | `30` |
|
||||
| `use_sticky_comment` | Use just one comment to deliver PR comments (only applies for pull_request event workflows) | No | `false` |
|
||||
| `github_token` | GitHub token for Claude to operate with. **Only include this if you're connecting a custom GitHub app of your own!** | No | - |
|
||||
| `model` | Model to use (provider-specific format required for Bedrock/Vertex) | No | - |
|
||||
| `anthropic_model` | **DEPRECATED**: Use `model` instead. Kept for backward compatibility. | No | - |
|
||||
|
||||
@@ -78,6 +78,10 @@ inputs:
|
||||
description: "Timeout in minutes for execution"
|
||||
required: false
|
||||
default: "30"
|
||||
use_sticky_comment:
|
||||
description: "Use just one comment to deliver issue/PR comments"
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
execution_file:
|
||||
@@ -116,6 +120,7 @@ runs:
|
||||
MCP_CONFIG: ${{ inputs.mcp_config }}
|
||||
OVERRIDE_GITHUB_TOKEN: ${{ inputs.github_token }}
|
||||
GITHUB_RUN_ID: ${{ github.run_id }}
|
||||
USE_STICKY_COMMENT: ${{ inputs.use_sticky_comment }}
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude-code
|
||||
@@ -180,6 +185,7 @@ runs:
|
||||
TRIGGER_USERNAME: ${{ github.event.comment.user.login || github.event.issue.user.login || github.event.pull_request.user.login || github.event.sender.login || github.triggering_actor || github.actor || '' }}
|
||||
PREPARE_SUCCESS: ${{ steps.prepare.outcome == 'success' }}
|
||||
PREPARE_ERROR: ${{ steps.prepare.outputs.prepare_error || '' }}
|
||||
USE_STICKY_COMMENT: ${{ inputs.use_sticky_comment }}
|
||||
|
||||
- name: Display Claude Code Report
|
||||
if: steps.prepare.outputs.contains_trigger == 'true' && steps.claude-code.outputs.execution_file != ''
|
||||
|
||||
@@ -36,6 +36,7 @@ export type ParsedGitHubContext = {
|
||||
directPrompt: string;
|
||||
baseBranch?: string;
|
||||
branchPrefix: string;
|
||||
useStickyComment: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -62,6 +63,7 @@ export function parseGitHubContext(): ParsedGitHubContext {
|
||||
directPrompt: process.env.DIRECT_PROMPT ?? "",
|
||||
baseBranch: process.env.BASE_BRANCH,
|
||||
branchPrefix: process.env.BRANCH_PREFIX ?? "claude/",
|
||||
useStickyComment: process.env.STICKY_COMMENT === "true",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { appendFileSync } from "fs";
|
||||
import { createJobRunLink, createCommentBody } from "./common";
|
||||
import {
|
||||
isPullRequestReviewCommentEvent,
|
||||
isPullRequestEvent,
|
||||
type ParsedGitHubContext,
|
||||
} from "../../context";
|
||||
import type { Octokit } from "@octokit/rest";
|
||||
@@ -25,8 +26,39 @@ export async function createInitialComment(
|
||||
try {
|
||||
let response;
|
||||
|
||||
// Only use createReplyForReviewComment if it's a PR review comment AND we have a comment_id
|
||||
if (isPullRequestReviewCommentEvent(context)) {
|
||||
if (
|
||||
context.inputs.useStickyComment &&
|
||||
context.isPR &&
|
||||
!isPullRequestEvent(context)
|
||||
) {
|
||||
const comments = await octokit.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.entityNumber,
|
||||
});
|
||||
const existingComment = comments.data.find(
|
||||
(comment) =>
|
||||
comment.user?.login.indexOf("claude[bot]") !== -1 ||
|
||||
comment.body === initialBody,
|
||||
);
|
||||
if (existingComment) {
|
||||
response = await octokit.rest.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: existingComment.id,
|
||||
body: initialBody,
|
||||
});
|
||||
} else {
|
||||
// Create new comment if no existing one found
|
||||
response = await octokit.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.entityNumber,
|
||||
body: initialBody,
|
||||
});
|
||||
}
|
||||
} else if (isPullRequestReviewCommentEvent(context)) {
|
||||
// Only use createReplyForReviewComment if it's a PR review comment AND we have a comment_id
|
||||
response = await octokit.rest.pulls.createReplyForReviewComment({
|
||||
owner,
|
||||
repo,
|
||||
|
||||
@@ -20,6 +20,7 @@ const defaultInputs = {
|
||||
useVertex: false,
|
||||
timeoutMinutes: 30,
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
};
|
||||
|
||||
const defaultRepository = {
|
||||
|
||||
@@ -68,6 +68,7 @@ describe("checkWritePermissions", () => {
|
||||
customInstructions: "",
|
||||
directPrompt: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ describe("checkContainsTrigger", () => {
|
||||
disallowedTools: [],
|
||||
customInstructions: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
expect(checkContainsTrigger(context)).toBe(true);
|
||||
@@ -64,6 +65,7 @@ describe("checkContainsTrigger", () => {
|
||||
disallowedTools: [],
|
||||
customInstructions: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
expect(checkContainsTrigger(context)).toBe(false);
|
||||
@@ -276,6 +278,7 @@ describe("checkContainsTrigger", () => {
|
||||
disallowedTools: [],
|
||||
customInstructions: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
expect(checkContainsTrigger(context)).toBe(true);
|
||||
@@ -305,6 +308,7 @@ describe("checkContainsTrigger", () => {
|
||||
disallowedTools: [],
|
||||
customInstructions: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
expect(checkContainsTrigger(context)).toBe(true);
|
||||
@@ -334,6 +338,7 @@ describe("checkContainsTrigger", () => {
|
||||
disallowedTools: [],
|
||||
customInstructions: "",
|
||||
branchPrefix: "claude/",
|
||||
useStickyComment: false,
|
||||
},
|
||||
});
|
||||
expect(checkContainsTrigger(context)).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user