feat(prd-5): add dedicated claude-bot user for Forgejo

- Add bot_email action input for custom git commit email on Forgejo
- Update claude.yml to use CLAUDE_BOT_TOKEN with bot_id/bot_name/bot_email
- Update git-config.ts to use provided email over noreply format
- Add "Dedicated Bot User" setup guide to docs/forgejo.md
- Update CLAUDE.md with bot identity documentation

Infrastructure (done outside code):
- claude-bot user created (ID 48, non-admin, with avatar)
- Claude team with write access in all 12 orgs
- CLAUDE_BOT_TOKEN org-level secret in all 12 orgs

Progress: ~85% complete - pending E2E validation after merge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad MocanuandClaude Opus 4.6 committed 2026-02-25 20:56:55 +02:00
1 parent 07e0384538
commit b03ccb518c
13 files changed
+57 -16

No files matched your search

+2
View File
@@ -94,6 +94,7 @@ type BaseContext = {
sshSigningKey: string;
botId: string;
botName: string;
botEmail: string;
allowedBots: string;
allowedNonWriteUsers: string;
trackProgress: boolean;
@@ -154,6 +155,7 @@ export function parseGitHubContext(): GitHubContext {
sshSigningKey: process.env.SSH_SIGNING_KEY || "",
botId: process.env.BOT_ID ?? String(CLAUDE_APP_BOT_ID),
botName: process.env.BOT_NAME ?? CLAUDE_BOT_LOGIN,
botEmail: process.env.BOT_EMAIL ?? "",
allowedBots: process.env.ALLOWED_BOTS ?? "",
allowedNonWriteUsers: process.env.ALLOWED_NON_WRITE_USERS ?? "",
trackProgress: process.env.TRACK_PROGRESS === "true",
+4 -2
View File
@@ -17,6 +17,7 @@ const SSH_SIGNING_KEY_PATH = join(homedir(), ".ssh", "claude_signing_key");
type GitUser = {
login: string;
id: number;
email?: string;
};
export async function configureGitAuth(
@@ -37,10 +38,11 @@ export async function configureGitAuth(
console.log("Configuring git user...");
const botName = user.login;
const botId = user.id;
const botEmail = user.email || `${botId}+${botName}@${noreplyDomain}`;
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}`);
await $`git config user.email "${botEmail}"`;
console.log(`✓ Set git user as ${botName} <${botEmail}>`);
// Remove the authorization header that actions/checkout sets
console.log("Removing existing git authentication headers...");
+2
View File
@@ -41,6 +41,7 @@ export async function prepareAgentMode({
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
email: context.inputs.botEmail || undefined,
};
try {
await configureGitAuth(githubToken, context, user);
@@ -53,6 +54,7 @@ export async function prepareAgentMode({
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
email: context.inputs.botEmail || undefined,
};
try {
+2
View File
@@ -86,6 +86,7 @@ export async function prepareTagMode({
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
email: context.inputs.botEmail || undefined,
};
try {
await configureGitAuth(githubToken, context, user);
@@ -98,6 +99,7 @@ export async function prepareTagMode({
const user = {
login: context.inputs.botName,
id: parseInt(context.inputs.botId),
email: context.inputs.botEmail || undefined,
};
try {