- Created docs/forgejo.md: comprehensive setup guide (prerequisites, quick start, platform detection, GitHub differences, CI workflows, upstream merge process, known limitations, troubleshooting) - Updated README.md with Forgejo support mention and docs link - Updated CLAUDE.md with Forgejo architecture section - Added platform input to docs/usage.md inputs table - Added 5 Forgejo FAQ entries to docs/faq.md - Upstream merge validated: zero conflicts (based on latest upstream) - PRD #1 100% complete: all milestones M1-M9 done, 794 tests passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
354 lines
29 KiB
Markdown
354 lines
29 KiB
Markdown
# PRD #1: Forgejo Platform Support with Upstream-Compatible Architecture
|
|
|
|
**Issue**: [#1](https://git.wxs.ro/actions/claude-code-action/issues/1)
|
|
**Priority**: High
|
|
**Created**: 2026-02-25
|
|
**Revised**: 2026-02-25 (post senior engineer review)
|
|
|
|
---
|
|
|
|
## Problem
|
|
|
|
The `claude-code-action` is tightly coupled to GitHub APIs (Octokit REST, GraphQL, `@actions/github`, OIDC token exchange). This makes it unusable with Forgejo Actions, despite Forgejo being workflow-compatible with GitHub Actions. We need Forgejo support while keeping upstream merges as painless as possible.
|
|
|
|
## Solution
|
|
|
|
Adopt a **lean adapter approach**: only create new files for functionality that is genuinely different on Forgejo, and **re-use existing `src/github/` code wherever Octokit REST is already compatible** with Forgejo's API. Make minimal, surgical modifications to entry points and `action.yml`.
|
|
|
|
### Key Insight: Octokit REST Works with Forgejo
|
|
|
|
Octokit REST methods (comments, permissions, branches, actor validation) work with Forgejo when `baseUrl` is set to the Forgejo instance's `/api/v1` endpoint. Forgejo mirrors GitHub's REST API paths. This means most of `src/github/` can be re-used directly — **we do NOT need to duplicate 20+ files**.
|
|
|
|
### What Truly Needs Forgejo-Specific Code
|
|
|
|
Only **4 areas** require new Forgejo implementations:
|
|
|
|
| Area | Why It's Different | New File |
|
|
| --------------------------- | -------------------------------------------------------------------------------- | ----------------------------------- |
|
|
| **Token handling** | No OIDC exchange with Anthropic; use `GITHUB_TOKEN`/`FORGEJO_TOKEN` directly | `src/forgejo/token.ts` |
|
|
| **Data fetching** | Forgejo has no GraphQL; must replace 3 GraphQL queries with multiple REST calls | `src/forgejo/data/fetcher.ts` |
|
|
| **Comment URL formatting** | Forgejo URLs differ from GitHub URLs (job links, PR links, branch links) | `src/forgejo/comment-logic.ts` |
|
|
| **CI status / Actions API** | Forgejo Actions API is less mature; `downloadJobLogForWorkflowRun` may not exist | `src/mcp/forgejo-actions-server.ts` |
|
|
|
|
### What Re-Uses Existing Code (No Duplication)
|
|
|
|
These `src/github/` modules work with Forgejo via Octokit REST as-is:
|
|
|
|
| Module | Why It Works |
|
|
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `validation/permissions.ts` | `octokit.repos.getCollaboratorPermissionLevel()` exists in Forgejo API |
|
|
| `validation/actor.ts` | **Skipped entirely on Forgejo** — `read:user` scope required for `getByUsername()` but unavailable; Forgejo has no bot/app accounts so check is unnecessary |
|
|
| `validation/trigger.ts` | Pure logic — reads webhook payload fields, no API calls |
|
|
| `operations/comments/create-initial.ts` | `octokit.rest.issues.createComment()` works on Forgejo |
|
|
| `operations/comments/update-claude-comment.ts` | `octokit.rest.issues.updateComment()` works on Forgejo |
|
|
| `operations/branch.ts` | `octokit.rest.git.getRef()`, `octokit.rest.repos.get()` work on Forgejo |
|
|
| `operations/git-config.ts` | Uses `GITHUB_SERVER_URL` for noreply domain — works since Forgejo sets this var |
|
|
| `utils/sanitizer.ts` | Pure logic, no API dependency |
|
|
| `utils/image-downloader.ts` | Uses Octokit REST for fetching — should work |
|
|
| `context.ts` | `@actions/github` reads `GITHUB_EVENT_PATH` — Forgejo sets this |
|
|
| `data/formatter.ts` | Pure formatting logic |
|
|
| `api/config.ts` | Reads `GITHUB_API_URL` / `GITHUB_SERVER_URL` — Forgejo sets these |
|
|
|
|
### Architecture: Lean Adapter
|
|
|
|
```
|
|
src/
|
|
├── platform/
|
|
│ └── detector.ts # NEW - Platform detection (+ action.yml `platform` input)
|
|
├── forgejo/
|
|
│ ├── token.ts # NEW - Direct token (skip OIDC)
|
|
│ ├── data/
|
|
│ │ └── fetcher.ts # NEW - REST-based data fetching (replaces GraphQL)
|
|
│ └── comment-logic.ts # NEW - Forgejo URL formatting for comments
|
|
├── mcp/
|
|
│ ├── forgejo-actions-server.ts # NEW - Forgejo CI status MCP server
|
|
│ └── install-mcp-server.ts # MODIFIED - platform routing for MCP config
|
|
├── github/ # REUSED - existing code, no modifications
|
|
│ └── ...
|
|
├── entrypoints/
|
|
│ └── run.ts # MODIFIED - platform branch for token setup
|
|
├── modes/
|
|
│ ├── tag/index.ts # MODIFIED - swap data fetcher + comment logic
|
|
│ └── agent/index.ts # MODIFIED - swap token setup
|
|
action.yml # MODIFIED - platform input, conditional steps
|
|
```
|
|
|
|
**~8 new/modified files** instead of ~25. The existing `src/github/` code is re-used, not duplicated.
|
|
|
|
### Why This Approach
|
|
|
|
| Approach | Upstream Merge Effort | Maintenance | Chosen? |
|
|
| -------------------------------------------- | ---------------------------------------------------------------- | ----------- | ------- |
|
|
| **Lean adapter (reuse + minimal new files)** | Low (3-4 conflict-prone files) | Low | **Yes** |
|
|
| Full abstraction layer (20+ new files) | Near-zero conflicts but high maintenance syncing duplicated code | High | No |
|
|
| Modify GitHub files in-place | High conflict rate on every upstream pull | Low | No |
|
|
| Complete fork with divergence | No merges possible after a while | Very high | No |
|
|
|
|
### Honest Merge-Conflict Assessment
|
|
|
|
These files **will be modified** and are the merge-conflict surface when pulling upstream:
|
|
|
|
| File | What We Change | Conflict Risk |
|
|
| ------------------------------- | ------------------------------------------------------------- | ---------------------------------------- |
|
|
| `src/entrypoints/run.ts` | Platform branch at top for token/client setup | **Medium** - upstream's most active file |
|
|
| `src/modes/tag/index.ts` | Swap `fetchGitHubData` call + comment logic based on platform | **Medium** |
|
|
| `src/modes/agent/index.ts` | Swap token setup based on platform | **Low** - simpler file |
|
|
| `src/mcp/install-mcp-server.ts` | Platform routing for MCP server selection | **Low-Medium** |
|
|
| `action.yml` | Add `platform` input, conditional Forgejo steps | **Low** - additive changes |
|
|
|
|
**Mitigation strategy**: Keep all platform changes at the **top** of functions (early return / branch pattern). Avoid restructuring existing code flow. When upstream modifies these files, conflicts will be localized to our small additions, not interleaved throughout.
|
|
|
|
## Technical Analysis
|
|
|
|
### Platform Detection Strategy
|
|
|
|
Use an **explicit `platform` input** (most reliable) with env-var auto-detection as fallback:
|
|
|
|
```typescript
|
|
// src/platform/detector.ts
|
|
export function detectPlatform(): "github" | "forgejo" {
|
|
// 1. Explicit input (most reliable)
|
|
const platformInput = process.env.PLATFORM;
|
|
if (platformInput === "forgejo") return "forgejo";
|
|
if (platformInput === "github") return "github";
|
|
|
|
// 2. Auto-detect from environment
|
|
// FORGEJO is set by Forgejo runner v7.0+ (not in older runners)
|
|
if (process.env.FORGEJO === "true") return "forgejo";
|
|
|
|
// Check GITHUB_SERVER_URL — if not github.com, likely Forgejo/Gitea
|
|
const serverUrl = process.env.GITHUB_SERVER_URL || "";
|
|
if (serverUrl && !serverUrl.includes("github.com")) {
|
|
return "forgejo";
|
|
}
|
|
|
|
return "github";
|
|
}
|
|
```
|
|
|
|
New `action.yml` input:
|
|
|
|
```yaml
|
|
platform:
|
|
description: "Platform to run on: 'auto' (default), 'github', or 'forgejo'"
|
|
required: false
|
|
default: "auto"
|
|
```
|
|
|
|
### Key Technical Differences
|
|
|
|
1. **No GraphQL**: Forgejo is REST-only. The 3 GraphQL queries in `src/github/api/queries/github.ts` (PR_QUERY, ISSUE_QUERY, USER_QUERY) must be replaced with **5-8 separate paginated REST calls**:
|
|
|
|
- `GET /repos/{owner}/{repo}/pulls/{index}` - PR details
|
|
- `GET /repos/{owner}/{repo}/pulls/{index}/files` - changed files (paginated)
|
|
- `GET /repos/{owner}/{repo}/pulls/{index}/commits` - commits (paginated)
|
|
- `GET /repos/{owner}/{repo}/issues/{index}/comments` - issue-level comments (paginated)
|
|
- `GET /repos/{owner}/{repo}/pulls/{index}/reviews` - reviews (paginated)
|
|
- For each review: `GET /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments`
|
|
- `GET /repos/{owner}/{repo}/issues/{index}` - issue details
|
|
|
|
Use `Promise.all()` to run independent calls in parallel and mitigate latency.
|
|
|
|
2. **API base URL**: Forgejo uses `/api/v1` (vs GitHub's `/api/v3`). Octokit REST methods work when `baseUrl` is set correctly since Forgejo mirrors GitHub's endpoint paths.
|
|
|
|
3. **Token handling**: No OIDC token exchange with Anthropic. The existing `OVERRIDE_GITHUB_TOKEN` code path in `token.ts` (line 130-135) already short-circuits the OIDC flow — for Forgejo we just need to use `GITHUB_TOKEN` or `FORGEJO_TOKEN` directly.
|
|
|
|
4. **Bot identity**: No GitHub App bot. The action runs as the token owner. Default `bot_id` (41898282) is meaningless on Forgejo — need sensible defaults.
|
|
|
|
5. **`pull_request_target` event**: May not exist in Forgejo. The existing `context.ts` maps it to `pull_request` (line 188), so it degrades gracefully.
|
|
|
|
6. **GitHub MCP Server**: The `ghcr.io/github/github-mcp-server` Docker image referenced in `install-mcp-server.ts` (line 214) won't work. Skip on Forgejo — it's only included when `hasGitHubMcpTools` is true.
|
|
|
|
7. **Forgejo Actions API gaps**: `actions.downloadJobLogForWorkflowRun()` used in the CI MCP server may not exist. Need to verify and implement alternative (direct API call or skip).
|
|
|
|
### `action.yml` Required Modifications
|
|
|
|
| Line(s) | Current | Problem | Fix |
|
|
| ------- | ----------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
| 103 | `default: "41898282"` (bot_id) | Meaningless on Forgejo | Make platform-aware; use token owner identity on Forgejo |
|
|
| 107 | `default: "claude[bot]"` (bot_name) | Doesn't exist on Forgejo | Same — detect from token or use configurable default |
|
|
| 163-166 | `uses: oven-sh/setup-bun@...` | References GitHub release; may fail on isolated Forgejo runners | Add conditional: if bun already available, skip; otherwise use direct curl install |
|
|
| 166 | `token: ${{ inputs.github_token \|\| github.token }}` | Used to fetch bun release from GitHub | On Forgejo, `github.token` is the Forgejo token — may not auth to GitHub; provide fallback |
|
|
| 285-294 | "Revoke app token" step | Calls `${GITHUB_API_URL}/installation/token` which doesn't exist on Forgejo | Make conditional: `if: platform != 'forgejo'` or detect and skip |
|
|
| N/A | Missing | No `platform` input | Add `platform` input (auto/github/forgejo) |
|
|
|
|
### `base-action/` Directory
|
|
|
|
`run.ts` imports directly from `base-action/src/`:
|
|
|
|
- `validate-env.ts` - checks env vars for Claude CLI (platform-agnostic)
|
|
- `setup-claude-code-settings.ts` - writes Claude settings (platform-agnostic)
|
|
- `install-plugins.ts` - installs Claude plugins (platform-agnostic)
|
|
- `prepare-prompt.ts` - prepares prompt file (platform-agnostic)
|
|
- `run-claude.ts` / `run-claude-sdk.ts` - runs Claude CLI (platform-agnostic)
|
|
|
|
**Conclusion**: `base-action/` is platform-independent. No modifications needed.
|
|
|
|
### MCP Server Naming Strategy
|
|
|
|
**Keep existing server names** (`github_comment`, `github_ci`, `github_file_ops`, `github_inline_comment`) even for Forgejo implementations. These are internal identifiers referenced in hardcoded tool name lists in `src/modes/tag/index.ts` (lines 127-152):
|
|
|
|
```typescript
|
|
"mcp__github_comment__update_claude_comment",
|
|
"mcp__github_ci__get_ci_status",
|
|
"mcp__github_file_ops__commit_files",
|
|
```
|
|
|
|
Renaming would require modifying the tool name lists — more merge-conflict surface for zero user benefit. The MCP server config in `install-mcp-server.ts` will point these names to either GitHub or Forgejo server implementations based on platform.
|
|
|
|
## CI/CD Workflows
|
|
|
|
### Handling Upstream `.github/workflows/`
|
|
|
|
The upstream repo has 13 workflows in `.github/workflows/`. Strategy:
|
|
|
|
- **Do NOT delete or modify** `.github/workflows/` files (merge conflicts)
|
|
- Create `.forgejo/workflows/` with our custom workflows
|
|
- **Configure Forgejo runner** to only read from `.forgejo/workflows/` (runner-level `DEFAULT_ACTIONS_URL` and workflow directory settings)
|
|
- **Document this as a setup requirement** — if runners aren't configured, upstream workflows will attempt to run and fail loudly (missing secrets, OIDC endpoints, etc.)
|
|
|
|
### Custom Forgejo Workflows
|
|
|
|
#### 1. CI Test Workflow (`.forgejo/workflows/ci.yml`)
|
|
|
|
- Triggers on push to main and PRs
|
|
- Runs `bun install` and `bun test`
|
|
- Lints with biome (matching upstream's toolchain)
|
|
|
|
#### 2. Action Self-Test Workflow (`.forgejo/workflows/test-action.yml`)
|
|
|
|
- **Tests the action itself** on Forgejo
|
|
- Creates a test issue via API, triggers the action with a simple prompt
|
|
- Verifies: platform detection returns "forgejo", comment is created on the issue, action completes successfully
|
|
- Validates end-to-end: token handling, Octokit REST calls, comment posting
|
|
- Runs on a schedule (weekly) and on PRs that modify `src/`, `action.yml`, or `.forgejo/`
|
|
|
|
#### 3. Upstream Sync Check (`.forgejo/workflows/upstream-sync.yml`)
|
|
|
|
- Scheduled workflow (weekly) + manual trigger
|
|
- Fetches `upstream/main`, compares with our `main` using `git rev-list`
|
|
- Creates an issue if upstream has new commits we haven't merged
|
|
- Includes commit count and summary of changed files to help assess merge effort
|
|
|
|
## Milestones
|
|
|
|
### Phase 1 - Foundation (parallel, no dependencies)
|
|
|
|
- [x] **M1: Platform detection + `action.yml` modifications** — Add `platform` input to `action.yml`. Create `src/platform/detector.ts` with explicit input + env-var auto-detection. Add conditional logic to skip "Revoke app token" step on Forgejo. Fix bun installation to handle Forgejo runners (direct curl fallback).
|
|
|
|
- Files: `action.yml` (MODIFIED), `src/platform/detector.ts` (NEW)
|
|
- Success: `detectPlatform()` returns "forgejo" in Forgejo runner, "github" in GitHub runner. `action.yml` doesn't error on Forgejo.
|
|
|
|
- [x] **M2: Forgejo token handling** — Create `src/forgejo/token.ts` that returns `GITHUB_TOKEN` / `FORGEJO_TOKEN` directly (no OIDC, no Anthropic exchange). Wire into `run.ts` with an early platform branch before the existing `setupGitHubToken()` call.
|
|
|
|
- Files: `src/forgejo/token.ts` (NEW), `src/entrypoints/run.ts` (MODIFIED — surgical addition at top of `run()`)
|
|
- Depends on: M1
|
|
- Success: Token is available without OIDC on Forgejo. GitHub path unchanged.
|
|
|
|
- [x] **M3: Forgejo CI workflows** — Created `.forgejo/workflows/` with three workflows adapted for Forgejo `grunt` runner: `ci.yml` (3 separate jobs: test, prettier, typecheck using curl-based bun install + `xternal/checkout`), `test-action.yml` (agent-mode self-test with `FORGEJO_PLATFORM_TEST_OK` marker, runs weekly + on PRs to src/action.yml/.forgejo), `upstream-sync.yml` (weekly upstream check, creates/updates issue with `upstream-sync` label including commit log, diff stat, and merge instructions).
|
|
|
|
- Files: `.forgejo/workflows/ci.yml`, `.forgejo/workflows/test-action.yml`, `.forgejo/workflows/upstream-sync.yml` (all NEW)
|
|
- Success: CI runs tests on push. Upstream `.github/workflows/` don't interfere.
|
|
|
|
### Phase 2 - Core Data Fetching (the hard part)
|
|
|
|
- [x] **M4a: Forgejo REST data fetching — PR/Issue basics** — Implement REST-based fetching for PR details, issue details, changed files, and commits. Produce output matching the `FetchDataResult` type that existing code expects.
|
|
|
|
- Files: `src/forgejo/data/fetcher.ts` (NEW)
|
|
- Depends on: M1, M2
|
|
- Success: Can fetch PR/issue title, body, author, state, files, commits from Forgejo REST API.
|
|
|
|
- [x] **M4b: Forgejo REST data fetching — Comments, reviews, inline comments** — Extend the fetcher with paginated comment/review fetching, including nested inline review comments (requires per-review API calls). Implement TOCTOU filtering using the same `filterCommentsToTriggerTime` / `filterReviewsToTriggerTime` functions (reuse from `src/github/data/fetcher.ts` — these are pure logic). Use `Promise.all()` for parallel API calls.
|
|
|
|
- Files: `src/forgejo/data/fetcher.ts` (extend from M4a)
|
|
- Depends on: M4a
|
|
- Success: Full parity with GitHub GraphQL data fetch. All comments, reviews, and inline comments included with proper TOCTOU filtering.
|
|
|
|
- [x] **M5: Forgejo comment URL formatting** — Create `src/forgejo/comment-logic.ts` with Forgejo-specific URL patterns for job links, branch links, and PR creation links (used in tracking comment updates).
|
|
- Files: `src/forgejo/comment-logic.ts` (NEW)
|
|
- Depends on: M1
|
|
- Success: Comment formatting produces correct Forgejo URLs.
|
|
|
|
### Phase 3 - Integration (wiring it together)
|
|
|
|
- [x] **M6: MCP server platform routing** — Modified `install-mcp-server.ts` to add platform detection. Skips GitHub public MCP server (`ghcr.io/github/github-mcp-server`) on Forgejo. Skips `checkActionsReadPermission` on Forgejo (workflow token has full repo access). Did NOT create `src/mcp/forgejo-actions-server.ts` — existing `github-actions-server.ts` works on Forgejo via Octokit REST + `GITHUB_API_URL` (zero duplication, easier maintenance). Server names remain `github_comment`, `github_ci`, etc.
|
|
|
|
- Files: `src/mcp/install-mcp-server.ts` (MODIFIED), `test/install-mcp-server.test.ts` (MODIFIED — 6 new Forgejo tests)
|
|
- Depends on: M4b, M5
|
|
- Success: All MCP servers route correctly on both platforms. 772 tests pass.
|
|
|
|
- [x] **M7: Entry point + mode handler integration** — Wired platform detection into mode handlers. In `tag/index.ts`: platform branch routes to `fetchForgejoData` vs `fetchGitHubData`. `createInitialComment` auto-detects platform for Forgejo spinner/URL format. `update-comment-link.ts` uses `updateForgejoCommentBody` + Forgejo PR compare URL on Forgejo. Agent mode needed NO changes (token already in `run.ts`, rest uses Octokit REST). 11 new integration tests in `test/m7-integration.test.ts`.
|
|
|
|
- Files: `src/modes/tag/index.ts` (MODIFIED), `src/entrypoints/update-comment-link.ts` (MODIFIED), `src/github/operations/comments/create-initial.ts` (MODIFIED), `src/github/operations/comments/update-with-branch.ts` (MODIFIED), `test/m7-integration.test.ts` (NEW)
|
|
- Depends on: M4b, M5, M6
|
|
- Success: All platform routing correct on both platforms. 785 tests pass.
|
|
|
|
### Phase 4 - Validation & Polish
|
|
|
|
- [x] **M8: End-to-end testing on Forgejo** — Tested agent mode (workflow_dispatch) end-to-end on Forgejo runner. Fixed multiple issues discovered during E2E: permission check switched to `repos.get()` (Forgejo lacks collaborator permission endpoint for workflow tokens), actor check skipped entirely on Forgejo (no bot accounts + `read:user` scope unavailable), `oven-sh/setup-bun` replaced with universal curl install in `action.yml` (Forgejo runner pre-fetches all `uses:` refs even when `if:` would skip them), CI test env override for `GITHUB_SERVER_URL` (module-level constants evaluated at import time). Self-test workflow passes: platform detection, token auth, actor skip, Claude Code execution, output validation all green. CI tests: 794 pass, 0 fail.
|
|
|
|
- Files: `action.yml` (MODIFIED — curl bun install), `src/github/validation/actor.ts` (MODIFIED — Forgejo skip), `test/actor.test.ts` (MODIFIED — Forgejo tests), `.forgejo/workflows/ci.yml` (MODIFIED — inline export fix)
|
|
- Depends on: M7
|
|
- Success: Agent mode works on Forgejo. Self-test workflow passes. CI tests pass. Note: tag mode (issue trigger, PR review) not yet E2E tested — code paths are wired but await real-world validation.
|
|
|
|
- [x] **M9: Documentation & upstream merge validation** — Created comprehensive `docs/forgejo.md` setup guide covering prerequisites, quick start (tag + agent mode), platform detection, GitHub vs Forgejo differences (auth, API, bun install, comment URLs), CI workflows, upstream merge process with conflict mitigation, known limitations, and troubleshooting. Updated `README.md` (Forgejo in description, feature bullet, docs link), `CLAUDE.md` (Forgejo architecture section with key files and integration points), `docs/usage.md` (`platform` input in table), `docs/faq.md` (5 Forgejo FAQ entries). Upstream merge validation: `git merge upstream/main` → zero conflicts — branch based on latest upstream `ade221f`. All 794 tests pass.
|
|
|
|
- Files: `docs/forgejo.md` (NEW), `README.md` (MODIFIED), `CLAUDE.md` (MODIFIED), `docs/usage.md` (MODIFIED), `docs/faq.md` (MODIFIED)
|
|
- Depends on: M8
|
|
- Success: Zero-conflict upstream merge. Complete Forgejo setup documentation with troubleshooting guide.
|
|
|
|
### Milestone Dependency Graph
|
|
|
|
```
|
|
M1 ──> M2 ──> M4a ──> M4b ──┬──> M6 ──> M7 ──> M8 ──> M9
|
|
M1 ──> M5 ───────────────────┘
|
|
M3 (independent, anytime)
|
|
```
|
|
|
|
**Parallel opportunities:**
|
|
|
|
- M3 is fully independent — can run anytime
|
|
- M5 and M2 can run in parallel (both only depend on M1)
|
|
- M4a can start as soon as M2 is done
|
|
- M6 and M7 are sequential (M7 depends on M6)
|
|
|
|
## Execution Plan
|
|
|
|
| Phase | Milestones | Files Touched | Parallel? |
|
|
| ----- | ------------ | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
| 1 | M1, M2, M3 | `action.yml`, `src/platform/detector.ts`, `src/forgejo/token.ts`, `src/entrypoints/run.ts`, `.forgejo/workflows/*` | M1 first, then M2+M3 in parallel |
|
|
| 2 | M4a, M4b, M5 | `src/forgejo/data/fetcher.ts`, `src/forgejo/comment-logic.ts` | M5 parallel with M4a/M4b |
|
|
| 3 | M6, M7 | `src/mcp/install-mcp-server.ts`, `src/mcp/forgejo-actions-server.ts`, `src/modes/tag/index.ts`, `src/modes/agent/index.ts` | Sequential |
|
|
| 4 | M8, M9 | Tests, docs, `CLAUDE.md` | Sequential |
|
|
|
|
## Risk Assessment
|
|
|
|
| Risk | Likelihood | Impact | Mitigation |
|
|
| -------------------------------------------------------------- | ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| Upstream refactors `run.ts` or mode handlers | Medium | High | Keep entry point changes to <10 lines; use early-return pattern; platform branch at top of functions |
|
|
| Octokit REST methods behave differently on Forgejo | Low | Medium | Test each used method early in M4a; fall back to raw `fetch()` if needed |
|
|
| Forgejo webhook payloads differ from `@octokit/webhooks-types` | Medium | Medium | Test with real Forgejo webhooks; key check: `payload.issue.pull_request` field for `is_pull` detection |
|
|
| `pull_request_target` event missing in Forgejo | High | Low | Already handled — `context.ts:188` maps it to `pull_request` |
|
|
| Forgejo Actions API missing endpoints (downloadJobLog) | Medium | Medium | Degrade gracefully — CI MCP server may offer fewer tools on Forgejo |
|
|
| `oven-sh/setup-bun` action fails on isolated Forgejo runners | **RESOLVED** | Medium | **Fixed**: Replaced `oven-sh/setup-bun` entirely with universal curl install in `action.yml`. Forgejo runner pre-fetches all `uses:` refs before evaluating `if:` conditions, so conditional skip was insufficient. Mirror created at `xternal/setup-bun` for future reference. |
|
|
| Upstream `.github/workflows/` run and fail on Forgejo | Medium | Low | Document runner configuration; provide `.forgejo/workflows/` overrides |
|
|
| Upstream adds new features requiring new GraphQL fields | Certain | Low | New features won't have Forgejo support until we add REST equivalents to `forgejo/data/fetcher.ts` |
|
|
|
|
## Success Criteria
|
|
|
|
1. Action runs on Forgejo for issue, PR, and workflow_dispatch triggers
|
|
2. Claude can read issue/PR context, post comments, create branches, and commit files on Forgejo
|
|
3. `git fetch upstream && git merge upstream/main` produces conflicts only in the 3-4 files we modified, and those conflicts are resolvable in <15 minutes
|
|
4. Self-test workflow validates the action works on every PR
|
|
5. Upstream sync workflow alerts when new upstream changes are available
|
|
6. Total new files: ~6-8 (not 25+)
|
|
|
|
## Out of Scope (for now)
|
|
|
|
- GitHub Enterprise Server support
|
|
- Gitea support (similar to Forgejo but may diverge)
|
|
- `pull_request_target` event support
|
|
- SSH signing on Forgejo (can be added later)
|
|
- GitHub MCP Server equivalent for Forgejo (the `ghcr.io/github/github-mcp-server` image)
|
|
- Full Forgejo Actions API parity (downloadJobLog may be missing)
|