mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 06:54:13 +08:00
tmp
This commit is contained in:
@@ -74,9 +74,13 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: "false"
|
default: "false"
|
||||||
bot_id:
|
bot_id:
|
||||||
description: "GitHub user ID to use for git operations when authenticated user cannot be fetched (defaults to github-actions[bot] ID)"
|
description: "GitHub user ID to use for git operations (defaults to github-actions[bot] ID)"
|
||||||
required: false
|
required: false
|
||||||
default: "41898282" # github-actions[bot] ID - see src/github/constants.ts
|
default: "41898282" # github-actions[bot] ID - see src/github/constants.ts
|
||||||
|
bot_name:
|
||||||
|
description: "GitHub username to use for git operations (defaults to github-actions[bot])"
|
||||||
|
required: false
|
||||||
|
default: "github-actions[bot]"
|
||||||
track_progress:
|
track_progress:
|
||||||
description: "Force tag mode with tracking comments for pull_request and issue events. Only applicable to pull_request (opened, synchronize, ready_for_review, reopened) and issue (opened, edited, labeled, assigned) events."
|
description: "Force tag mode with tracking comments for pull_request and issue events. Only applicable to pull_request (opened, synchronize, ready_for_review, reopened) and issue (opened, edited, labeled, assigned) events."
|
||||||
required: false
|
required: false
|
||||||
@@ -149,6 +153,7 @@ runs:
|
|||||||
DEFAULT_WORKFLOW_TOKEN: ${{ github.token }}
|
DEFAULT_WORKFLOW_TOKEN: ${{ github.token }}
|
||||||
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
||||||
BOT_ID: ${{ inputs.bot_id }}
|
BOT_ID: ${{ inputs.bot_id }}
|
||||||
|
BOT_NAME: ${{ inputs.bot_name }}
|
||||||
TRACK_PROGRESS: ${{ inputs.track_progress }}
|
TRACK_PROGRESS: ${{ inputs.track_progress }}
|
||||||
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
||||||
CLAUDE_ARGS: ${{ inputs.claude_args }}
|
CLAUDE_ARGS: ${{ inputs.claude_args }}
|
||||||
|
|||||||
16
docs/faq.md
16
docs/faq.md
@@ -32,13 +32,25 @@ The OIDC token is required in order for the Claude GitHub app to function. If yo
|
|||||||
|
|
||||||
This error occurs when the action tries to fetch the authenticated user information using a GitHub App installation token. GitHub App tokens have limited access and cannot access the `/user` endpoint, which causes this 403 error.
|
This error occurs when the action tries to fetch the authenticated user information using a GitHub App installation token. GitHub App tokens have limited access and cannot access the `/user` endpoint, which causes this 403 error.
|
||||||
|
|
||||||
**Solution**: The action now includes a `bot_id` input that defaults to the github-actions[bot] ID (41898282). This avoids the need to fetch user information. If you need to use a different bot user, you can specify a custom bot_id:
|
**Solution**: The action now includes `bot_id` and `bot_name` inputs that default to github-actions[bot]. This avoids the need to fetch user information from the API.
|
||||||
|
|
||||||
|
For the default github-actions[bot]:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: anthropics/claude-code-action@v1
|
- uses: anthropics/claude-code-action@v1
|
||||||
with:
|
with:
|
||||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
bot_id: "12345678" # Custom bot user ID
|
# bot_id and bot_name have sensible defaults, no need to specify
|
||||||
|
```
|
||||||
|
|
||||||
|
For custom bots, specify both:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: anthropics/claude-code-action@v1
|
||||||
|
with:
|
||||||
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
|
bot_id: "12345678" # Your bot's GitHub user ID
|
||||||
|
bot_name: "my-bot" # Your bot's username
|
||||||
```
|
```
|
||||||
|
|
||||||
This issue typically only affects agent/automation mode workflows. Interactive workflows (with @claude mentions) don't encounter this issue as they use the comment author's information.
|
This issue typically only affects agent/automation mode workflows. Interactive workflows (with @claude mentions) don't encounter this issue as they use the comment author's information.
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
| Input | Description | Required | Default |
|
| Input | Description | Required | Default |
|
||||||
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -------- | ---------- |
|
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------- | -------- | --------------------- |
|
||||||
| `anthropic_api_key` | Anthropic API key (required for direct API, not needed for Bedrock/Vertex) | No\* | - |
|
| `anthropic_api_key` | Anthropic API key (required for direct API, not needed for Bedrock/Vertex) | No\* | - |
|
||||||
| `claude_code_oauth_token` | Claude Code OAuth token (alternative to anthropic_api_key) | No\* | - |
|
| `claude_code_oauth_token` | Claude Code OAuth token (alternative to anthropic_api_key) | No\* | - |
|
||||||
| `prompt` | Instructions for Claude. Can be a direct prompt or custom template for automation workflows | No | - |
|
| `prompt` | Instructions for Claude. Can be a direct prompt or custom template for automation workflows | No | - |
|
||||||
@@ -68,7 +68,8 @@ jobs:
|
|||||||
| `additional_permissions` | Additional permissions to enable. Currently supports 'actions: read' for viewing workflow results | No | "" |
|
| `additional_permissions` | Additional permissions to enable. Currently supports 'actions: read' for viewing workflow results | No | "" |
|
||||||
| `experimental_allowed_domains` | Restrict network access to these domains only (newline-separated). | No | "" |
|
| `experimental_allowed_domains` | Restrict network access to these domains only (newline-separated). | No | "" |
|
||||||
| `use_commit_signing` | Enable commit signing using GitHub's commit signature verification. When false, Claude uses standard git commands | No | `false` |
|
| `use_commit_signing` | Enable commit signing using GitHub's commit signature verification. When false, Claude uses standard git commands | No | `false` |
|
||||||
| `bot_id` | GitHub user ID to use for git operations when authenticated user cannot be fetched (defaults to github-actions[bot] ID) | No | `41898282` |
|
| `bot_id` | GitHub user ID to use for git operations (defaults to github-actions[bot] ID) | No | `41898282` |
|
||||||
|
| `bot_name` | GitHub username to use for git operations (defaults to github-actions[bot]) | No | `github-actions[bot]` |
|
||||||
| `allowed_bots` | Comma-separated list of allowed bot usernames, or '\*' to allow all bots. Empty string (default) allows no bots | No | "" |
|
| `allowed_bots` | Comma-separated list of allowed bot usernames, or '\*' to allow all bots. Empty string (default) allows no bots | No | "" |
|
||||||
|
|
||||||
### Deprecated Inputs
|
### Deprecated Inputs
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub Actions bot user ID
|
* Claude App bot user ID
|
||||||
* This is the official ID for github-actions[bot] used in GitHub repositories
|
|
||||||
*/
|
*/
|
||||||
export const GITHUB_ACTIONS_BOT_ID = 41898282;
|
export const CLAUDE_APP_BOT_ID = 41898282;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub Actions bot username
|
* GitHub Actions bot username
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type {
|
|||||||
PullRequestReviewCommentEvent,
|
PullRequestReviewCommentEvent,
|
||||||
WorkflowRunEvent,
|
WorkflowRunEvent,
|
||||||
} from "@octokit/webhooks-types";
|
} from "@octokit/webhooks-types";
|
||||||
import { GITHUB_ACTIONS_BOT_ID } from "./constants";
|
import { CLAUDE_APP_BOT_ID, GITHUB_ACTIONS_BOT_LOGIN } from "./constants";
|
||||||
// Custom types for GitHub Actions events that aren't webhooks
|
// Custom types for GitHub Actions events that aren't webhooks
|
||||||
export type WorkflowDispatchEvent = {
|
export type WorkflowDispatchEvent = {
|
||||||
action?: never;
|
action?: never;
|
||||||
@@ -76,6 +76,7 @@ type BaseContext = {
|
|||||||
useStickyComment: boolean;
|
useStickyComment: boolean;
|
||||||
useCommitSigning: boolean;
|
useCommitSigning: boolean;
|
||||||
botId: string;
|
botId: string;
|
||||||
|
botName: string;
|
||||||
allowedBots: string;
|
allowedBots: string;
|
||||||
trackProgress: boolean;
|
trackProgress: boolean;
|
||||||
};
|
};
|
||||||
@@ -124,7 +125,8 @@ export function parseGitHubContext(): GitHubContext {
|
|||||||
branchPrefix: process.env.BRANCH_PREFIX ?? "claude/",
|
branchPrefix: process.env.BRANCH_PREFIX ?? "claude/",
|
||||||
useStickyComment: process.env.USE_STICKY_COMMENT === "true",
|
useStickyComment: process.env.USE_STICKY_COMMENT === "true",
|
||||||
useCommitSigning: process.env.USE_COMMIT_SIGNING === "true",
|
useCommitSigning: process.env.USE_COMMIT_SIGNING === "true",
|
||||||
botId: process.env.BOT_ID ?? String(GITHUB_ACTIONS_BOT_ID),
|
botId: process.env.BOT_ID ?? String(CLAUDE_APP_BOT_ID),
|
||||||
|
botName: process.env.BOT_NAME ?? GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
allowedBots: process.env.ALLOWED_BOTS ?? "",
|
allowedBots: process.env.ALLOWED_BOTS ?? "",
|
||||||
trackProgress: process.env.TRACK_PROGRESS === "true",
|
trackProgress: process.env.TRACK_PROGRESS === "true",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
import { $ } from "bun";
|
import { $ } from "bun";
|
||||||
import type { GitHubContext } from "../context";
|
import type { GitHubContext } from "../context";
|
||||||
import { GITHUB_SERVER_URL } from "../api/config";
|
import { GITHUB_SERVER_URL } from "../api/config";
|
||||||
import { GITHUB_ACTIONS_BOT_ID, GITHUB_ACTIONS_BOT_LOGIN } from "../constants";
|
|
||||||
|
|
||||||
type GitUser = {
|
type GitUser = {
|
||||||
login: string;
|
login: string;
|
||||||
@@ -18,7 +17,7 @@ type GitUser = {
|
|||||||
export async function configureGitAuth(
|
export async function configureGitAuth(
|
||||||
githubToken: string,
|
githubToken: string,
|
||||||
context: GitHubContext,
|
context: GitHubContext,
|
||||||
user: GitUser | null,
|
user: GitUser,
|
||||||
) {
|
) {
|
||||||
console.log("Configuring git authentication for non-signing mode");
|
console.log("Configuring git authentication for non-signing mode");
|
||||||
|
|
||||||
@@ -29,20 +28,14 @@ export async function configureGitAuth(
|
|||||||
? "users.noreply.github.com"
|
? "users.noreply.github.com"
|
||||||
: `users.noreply.${serverUrl.hostname}`;
|
: `users.noreply.${serverUrl.hostname}`;
|
||||||
|
|
||||||
// Configure git user based on the comment creator
|
// Configure git user
|
||||||
console.log("Configuring git user...");
|
console.log("Configuring git user...");
|
||||||
if (user) {
|
|
||||||
const botName = user.login;
|
const botName = user.login;
|
||||||
const botId = user.id;
|
const botId = user.id;
|
||||||
console.log(`Setting git user as ${botName}...`);
|
console.log(`Setting git user as ${botName}...`);
|
||||||
await $`git config user.name "${botName}"`;
|
await $`git config user.name "${botName}"`;
|
||||||
await $`git config user.email "${botId}+${botName}@${noreplyDomain}"`;
|
await $`git config user.email "${botId}+${botName}@${noreplyDomain}"`;
|
||||||
console.log(`✓ Set git user as ${botName}`);
|
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_LOGIN}"`;
|
|
||||||
await $`git config user.email "${GITHUB_ACTIONS_BOT_ID}+${GITHUB_ACTIONS_BOT_LOGIN}@${noreplyDomain}"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the authorization header that actions/checkout sets
|
// Remove the authorization header that actions/checkout sets
|
||||||
console.log("Removing existing git authentication headers...");
|
console.log("Removing existing git authentication headers...");
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { parseAllowedTools } from "./parse-tools";
|
|||||||
import { configureGitAuth } from "../../github/operations/git-config";
|
import { configureGitAuth } from "../../github/operations/git-config";
|
||||||
import type { GitHubContext } from "../../github/context";
|
import type { GitHubContext } from "../../github/context";
|
||||||
import { isEntityContext } from "../../github/context";
|
import { isEntityContext } from "../../github/context";
|
||||||
import { GITHUB_ACTIONS_BOT_ID } from "../../github/constants";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract GitHub context as environment variables for agent mode
|
* Extract GitHub context as environment variables for agent mode
|
||||||
@@ -78,66 +77,14 @@ export const agentMode: Mode = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
async prepare({
|
async prepare({ context, githubToken }: ModeOptions): Promise<ModeResult> {
|
||||||
context,
|
|
||||||
githubToken,
|
|
||||||
octokit,
|
|
||||||
}: ModeOptions): Promise<ModeResult> {
|
|
||||||
// Configure git authentication for agent mode (same as tag mode)
|
// Configure git authentication for agent mode (same as tag mode)
|
||||||
if (!context.inputs.useCommitSigning) {
|
if (!context.inputs.useCommitSigning) {
|
||||||
let user = null;
|
// Use bot_id and bot_name from inputs directly
|
||||||
|
const user = {
|
||||||
// Check if bot_id is provided
|
login: context.inputs.botName,
|
||||||
console.log("yolobot", context.inputs.botId);
|
id: parseInt(context.inputs.botId),
|
||||||
const botId = context.inputs.botId;
|
|
||||||
if (botId && botId !== String(GITHUB_ACTIONS_BOT_ID)) {
|
|
||||||
// Use custom bot_id - try to fetch user info
|
|
||||||
try {
|
|
||||||
const { data: userData } = await octokit.rest.users.getByUsername({
|
|
||||||
username: context.actor,
|
|
||||||
});
|
|
||||||
user = {
|
|
||||||
login: userData.login,
|
|
||||||
id: userData.id,
|
|
||||||
};
|
};
|
||||||
console.log("yolo user", user);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(
|
|
||||||
`Could not fetch user info for ${context.actor}, using bot_id ${botId}`,
|
|
||||||
);
|
|
||||||
user = {
|
|
||||||
login: context.actor,
|
|
||||||
id: parseInt(botId),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Try to get authenticated user, but don't fail if using GitHub App token
|
|
||||||
try {
|
|
||||||
const { data: authenticatedUser } =
|
|
||||||
await octokit.rest.users.getAuthenticated();
|
|
||||||
user = {
|
|
||||||
login: authenticatedUser.login,
|
|
||||||
id: authenticatedUser.id,
|
|
||||||
};
|
|
||||||
console.log("yolo user auth", user);
|
|
||||||
} catch (error: any) {
|
|
||||||
// Check if this is a GitHub App token limitation
|
|
||||||
if (
|
|
||||||
error?.status === 403 &&
|
|
||||||
error?.message?.includes("Resource not accessible by integration")
|
|
||||||
) {
|
|
||||||
console.log(
|
|
||||||
"Using GitHub App token - defaulting to github-actions[bot] for git operations",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
"Failed to get authenticated user:",
|
|
||||||
error?.message || error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// User will remain null, which will trigger default behavior in configureGitAuth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use the shared git configuration function
|
// Use the shared git configuration function
|
||||||
|
|||||||
@@ -89,8 +89,14 @@ export const tagMode: Mode = {
|
|||||||
|
|
||||||
// Configure git authentication if not using commit signing
|
// Configure git authentication if not using commit signing
|
||||||
if (!context.inputs.useCommitSigning) {
|
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 {
|
try {
|
||||||
await configureGitAuth(githubToken, context, commentData.user);
|
await configureGitAuth(githubToken, context, user);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to configure git authentication:", error);
|
console.error("Failed to configure git authentication:", error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import { describe, test, expect, beforeEach, afterEach, spyOn } from "bun:test";
|
|||||||
import { prepareMcpConfig } from "../src/mcp/install-mcp-server";
|
import { prepareMcpConfig } from "../src/mcp/install-mcp-server";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import type { ParsedGitHubContext } from "../src/github/context";
|
import type { ParsedGitHubContext } from "../src/github/context";
|
||||||
import { GITHUB_ACTIONS_BOT_ID } from "../src/github/constants";
|
import {
|
||||||
|
CLAUDE_APP_BOT_ID,
|
||||||
|
GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
|
} from "../src/github/constants";
|
||||||
|
|
||||||
describe("prepareMcpConfig", () => {
|
describe("prepareMcpConfig", () => {
|
||||||
let consoleInfoSpy: any;
|
let consoleInfoSpy: any;
|
||||||
@@ -32,7 +35,8 @@ describe("prepareMcpConfig", () => {
|
|||||||
branchPrefix: "",
|
branchPrefix: "",
|
||||||
useStickyComment: false,
|
useStickyComment: false,
|
||||||
useCommitSigning: false,
|
useCommitSigning: false,
|
||||||
botId: String(GITHUB_ACTIONS_BOT_ID),
|
botId: String(CLAUDE_APP_BOT_ID),
|
||||||
|
botName: GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import type {
|
|||||||
PullRequestReviewEvent,
|
PullRequestReviewEvent,
|
||||||
PullRequestReviewCommentEvent,
|
PullRequestReviewCommentEvent,
|
||||||
} from "@octokit/webhooks-types";
|
} from "@octokit/webhooks-types";
|
||||||
import { GITHUB_ACTIONS_BOT_ID } from "../src/github/constants";
|
import {
|
||||||
|
CLAUDE_APP_BOT_ID,
|
||||||
|
GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
|
} from "../src/github/constants";
|
||||||
|
|
||||||
const defaultInputs = {
|
const defaultInputs = {
|
||||||
prompt: "",
|
prompt: "",
|
||||||
@@ -19,7 +22,8 @@ const defaultInputs = {
|
|||||||
branchPrefix: "claude/",
|
branchPrefix: "claude/",
|
||||||
useStickyComment: false,
|
useStickyComment: false,
|
||||||
useCommitSigning: false,
|
useCommitSigning: false,
|
||||||
botId: String(GITHUB_ACTIONS_BOT_ID),
|
botId: String(CLAUDE_APP_BOT_ID),
|
||||||
|
botName: GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test";
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { checkWritePermissions } from "../src/github/validation/permissions";
|
import { checkWritePermissions } from "../src/github/validation/permissions";
|
||||||
import type { ParsedGitHubContext } from "../src/github/context";
|
import type { ParsedGitHubContext } from "../src/github/context";
|
||||||
import { GITHUB_ACTIONS_BOT_ID } from "../src/github/constants";
|
import {
|
||||||
|
CLAUDE_APP_BOT_ID,
|
||||||
|
GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
|
} from "../src/github/constants";
|
||||||
|
|
||||||
describe("checkWritePermissions", () => {
|
describe("checkWritePermissions", () => {
|
||||||
let coreInfoSpy: any;
|
let coreInfoSpy: any;
|
||||||
@@ -68,7 +71,8 @@ describe("checkWritePermissions", () => {
|
|||||||
branchPrefix: "claude/",
|
branchPrefix: "claude/",
|
||||||
useStickyComment: false,
|
useStickyComment: false,
|
||||||
useCommitSigning: false,
|
useCommitSigning: false,
|
||||||
botId: String(GITHUB_ACTIONS_BOT_ID),
|
botId: String(CLAUDE_APP_BOT_ID),
|
||||||
|
botName: GITHUB_ACTIONS_BOT_LOGIN,
|
||||||
allowedBots: "",
|
allowedBots: "",
|
||||||
trackProgress: false,
|
trackProgress: false,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user