diff --git a/docs/forgejo.md b/docs/forgejo.md index d445d5a..58b99c5 100644 --- a/docs/forgejo.md +++ b/docs/forgejo.md @@ -7,19 +7,16 @@ This action supports [Forgejo](https://forgejo.org/) (and Forgejo Actions) as an - **Forgejo instance** with [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/) enabled - **Forgejo runner** registered and operational (e.g., a `grunt` or `ubuntu-latest` runner) - **Anthropic API key** or **Claude Code OAuth token** for Claude API access -- **Forgejo token** with repo access (automatically available as `github.token` in workflows, or use a dedicated token) +- **Forgejo token** with repo access (automatically available as `github.token` in workflows, or use a [dedicated bot user](#dedicated-bot-user-recommended)) ## Quick Start ### 1. Add Secrets -In your Forgejo repository, go to **Settings > Actions > Secrets** and add: +Add secrets at the **organization level** (Settings > Actions > Secrets) so all repos can share them: - `ANTHROPIC_API_KEY` — Your Anthropic API key (starting with `sk-ant-`) - -If you need a dedicated token for Claude's GitHub operations (recommended for tag mode): - -- `FORGEJO_CLAUDE_TOKEN` — A Forgejo personal access token with `repo` scope +- `CLAUDE_BOT_TOKEN` — API token for the dedicated bot user (see [Dedicated Bot User](#dedicated-bot-user-recommended) below) ### 2. Create Workflow @@ -45,7 +42,10 @@ jobs: with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} platform: "forgejo" - github_token: ${{ secrets.FORGEJO_CLAUDE_TOKEN }} + github_token: ${{ secrets.CLAUDE_BOT_TOKEN }} + bot_id: "YOUR_BOT_ID" # Replace with your bot's Forgejo user ID (see step 5 below) + bot_name: "claude-bot" + bot_email: "claude@yourdomain.com" # Must match the bot user's registered email ``` ### 3. Agent Mode (Automation) @@ -70,7 +70,10 @@ jobs: prompt: ${{ github.event.inputs.task }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} platform: "forgejo" - github_token: ${{ secrets.FORGEJO_CLAUDE_TOKEN }} + github_token: ${{ secrets.CLAUDE_BOT_TOKEN }} + bot_id: "YOUR_BOT_ID" # Replace with your bot's Forgejo user ID + bot_name: "claude-bot" + bot_email: "claude@yourdomain.com" ``` ## Platform Detection @@ -89,12 +92,12 @@ The action detects the platform using a three-tier strategy: ### Authentication -| Aspect | GitHub | Forgejo | -| ------------------------ | ------------------------------- | --------------------------------------- | -| **Default auth** | GitHub App OIDC token exchange | Direct `GITHUB_TOKEN` / `FORGEJO_TOKEN` | -| **Token setup** | Automatic via Claude GitHub App | Manual — provide `github_token` input | -| **App token revocation** | Automatic cleanup step | Skipped (no app token) | -| **Bot identity** | `claude[bot]` (ID: 41898282) | Token owner's identity | +| Aspect | GitHub | Forgejo | +| ------------------------ | ------------------------------- | ------------------------------------------------------------- | +| **Default auth** | GitHub App OIDC token exchange | Direct `GITHUB_TOKEN` / `FORGEJO_TOKEN` | +| **Token setup** | Automatic via Claude GitHub App | Manual — provide `github_token` input | +| **App token revocation** | Automatic cleanup step | Skipped (no app token) | +| **Bot identity** | `claude[bot]` (ID: 41898282) | Dedicated bot user via `bot_id`/`bot_name`/`bot_email` inputs | On Forgejo, there is no OIDC token exchange with Anthropic. The action uses the workflow token (`github.token`) or a user-provided `github_token` directly. @@ -131,6 +134,88 @@ platform: All other inputs work identically on both platforms. See the [Usage Guide](./usage.md) for the full list. +## Dedicated Bot User (Recommended) + +On GitHub, Claude gets its own identity via the GitHub App (`claude[bot]`). On Forgejo, there's no such mechanism — by default the action runs under whatever token you provide, meaning commits and comments appear as the human user. + +Creating a dedicated bot user solves this: + +- **Clear attribution**: Commits and comments show as `claude-bot`, not your personal account +- **Least privilege**: The bot token has only the permissions Claude needs +- **Audit trail**: Easy to distinguish human actions from bot actions in repo history +- **Security**: If the action is compromised, only the bot's scoped token is exposed + +### Setup Steps + +#### 1. Create the bot user + +Go to **Site Administration > User Accounts > Create User Account** or use the admin API: + +- **Username**: `claude-bot` +- **Email**: e.g., `claude@yourdomain.com` +- **Password**: any strong password (you'll use API tokens, not password login) +- **Uncheck** "Require user to change password" +- Leave "Admin" **unchecked** +- Optionally set a display name and avatar to distinguish from human users + +#### 2. Add to organizations via teams + +For each organization where Claude should operate: + +1. Go to **Org Settings > Teams > New Team** +2. Create a team named `Claude` with: + - **Permission**: `Write` + - **Access**: All Repositories (so new repos are automatically covered) +3. Add `claude-bot` to the team's **Members** + +#### 3. Generate a scoped API token + +Log in as `claude-bot`, go to **Settings > Applications**, and create a token: + +- **Token Name**: `claude-code-action` +- **Scopes**: + - `repo` — read/write (issues, PRs, comments, branches, commits) + - `user:read` — needed for API identity + - Leave `admin`, `organization`, `package` **unchecked** + +#### 4. Store the token as an org-level secret + +Add the token as `CLAUDE_BOT_TOKEN` at the **organization level** (Settings > Actions > Secrets) with visibility set to "All repositories". This way all repos in the org share the same secret. + +#### 5. Get the bot user's ID + +You'll need the Forgejo user ID for the `bot_id` input: + +```bash +curl -s "https://your-forgejo-instance/api/v1/users/claude-bot" | jq '.id' +``` + +#### 6. Configure the workflow + +```yaml +- uses: https://git.wxs.ro/actions/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + platform: "forgejo" + github_token: ${{ secrets.CLAUDE_BOT_TOKEN }} + bot_id: "YOUR_BOT_ID" # Replace with the ID from step 5 + bot_name: "claude-bot" + bot_email: "claude@yourdomain.com" # Must match the bot user's registered email +``` + +The `bot_email` input overrides the default noreply email format. When it matches the bot user's registered email in Forgejo, commits will be linked to the bot's profile in the UI. + +### Token Rotation + +Forgejo API tokens can expire. Plan for rotation: + +1. **Set a calendar reminder** for before the token expires +2. **Generate a new token** by logging in as `claude-bot` (same scopes as above) +3. **Update the org secret** `CLAUDE_BOT_TOKEN` with the new token value +4. **No code changes needed** — the workflow reads the secret at runtime + +Alternatively, generate a token without an expiration date (if your Forgejo instance allows it). + ## Included CI Workflows This fork includes four Forgejo-native workflows in `.forgejo/workflows/`: