feat: add bot_id input to handle GitHub App authentication errors (#534)

Adds a new optional bot_id input parameter that defaults to the github-actions[bot] ID (41898282). This resolves the "403 Resource not accessible by integration" error that occurs when using GitHub App installation tokens, which cannot access the /user endpoint.

Changes:
- Add bot_id input to action.yml with default value
- Update context parsing to include bot_id from environment
- Modify agent mode to use bot_id when available, avoiding API calls that fail with GitHub App tokens
- Add clear error handling for GitHub App token limitations
- Update documentation in usage.md and faq.md
- Fix test mocks to include bot_id field

This allows users to specify a custom bot user ID or use the default github-actions[bot] ID automatically, preventing 403 errors in automation workflows.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Ashwin Bhat
2025-09-04 14:55:25 -07:00
committed by GitHub
parent fb823f6dd6
commit 63f1c772bd
12 changed files with 162 additions and 53 deletions

13
src/github/constants.ts Normal file
View File

@@ -0,0 +1,13 @@
/**
* GitHub-related constants used throughout the application
*/
/**
* Claude App bot user ID
*/
export const CLAUDE_APP_BOT_ID = 41898282;
/**
* Claude bot username
*/
export const CLAUDE_BOT_LOGIN = "claude[bot]";

View File

@@ -8,6 +8,7 @@ import type {
PullRequestReviewCommentEvent,
WorkflowRunEvent,
} from "@octokit/webhooks-types";
import { CLAUDE_APP_BOT_ID, CLAUDE_BOT_LOGIN } from "./constants";
// Custom types for GitHub Actions events that aren't webhooks
export type WorkflowDispatchEvent = {
action?: never;
@@ -74,6 +75,8 @@ type BaseContext = {
branchPrefix: string;
useStickyComment: boolean;
useCommitSigning: boolean;
botId: string;
botName: string;
allowedBots: string;
trackProgress: boolean;
};
@@ -122,6 +125,8 @@ export function parseGitHubContext(): GitHubContext {
branchPrefix: process.env.BRANCH_PREFIX ?? "claude/",
useStickyComment: process.env.USE_STICKY_COMMENT === "true",
useCommitSigning: process.env.USE_COMMIT_SIGNING === "true",
botId: process.env.BOT_ID ?? String(CLAUDE_APP_BOT_ID),
botName: process.env.BOT_NAME ?? CLAUDE_BOT_LOGIN,
allowedBots: process.env.ALLOWED_BOTS ?? "",
trackProgress: process.env.TRACK_PROGRESS === "true",
},

View File

@@ -17,7 +17,7 @@ type GitUser = {
export async function configureGitAuth(
githubToken: string,
context: GitHubContext,
user: GitUser | null,
user: GitUser,
) {
console.log("Configuring git authentication for non-signing mode");
@@ -28,20 +28,14 @@ export async function configureGitAuth(
? "users.noreply.github.com"
: `users.noreply.${serverUrl.hostname}`;
// Configure git user based on the comment creator
// Configure git user
console.log("Configuring git user...");
if (user) {
const botName = user.login;
const botId = user.id;
console.log(`Setting git user as ${botName}...`);
await $`git config user.name "${botName}"`;
await $`git config user.email "${botId}+${botName}@${noreplyDomain}"`;
console.log(`✓ Set git user as ${botName}`);
} else {
console.log("No user data in comment, using default bot user");
await $`git config user.name "github-actions[bot]"`;
await $`git config user.email "41898282+github-actions[bot]@${noreplyDomain}"`;
}
const botName = user.login;
const botId = user.id;
console.log(`Setting git user as ${botName}...`);
await $`git config user.name "${botName}"`;
await $`git config user.email "${botId}+${botName}@${noreplyDomain}"`;
console.log(`✓ Set git user as ${botName}`);
// Remove the authorization header that actions/checkout sets
console.log("Removing existing git authentication headers...");

View File

@@ -77,22 +77,16 @@ export const agentMode: Mode = {
return false;
},
async prepare({
context,
githubToken,
octokit,
}: ModeOptions): Promise<ModeResult> {
async prepare({ context, githubToken }: ModeOptions): Promise<ModeResult> {
// Configure git authentication for agent mode (same as tag mode)
if (!context.inputs.useCommitSigning) {
try {
// Get the authenticated user (will be claude[bot] when using Claude App token)
const { data: authenticatedUser } =
await octokit.rest.users.getAuthenticated();
const user = {
login: authenticatedUser.login,
id: authenticatedUser.id,
};
// Use bot_id and bot_name from inputs directly
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
};
try {
// Use the shared git configuration function
await configureGitAuth(githubToken, context, user);
} catch (error) {

View File

@@ -89,8 +89,14 @@ export const tagMode: Mode = {
// Configure git authentication if not using commit signing
if (!context.inputs.useCommitSigning) {
// Use bot_id and bot_name from inputs directly
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
};
try {
await configureGitAuth(githubToken, context, commentData.user);
await configureGitAuth(githubToken, context, user);
} catch (error) {
console.error("Failed to configure git authentication:", error);
throw error;