chore: anonymize internal URLs for public release

Replace git.wxs.ro with forgejo.example.com in tests and docs.
Add public repo guidelines to CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad MocanuandClaude Opus 4.6 committed 2026-02-27 16:36:34 +02:00
1 parent b01c498dd9
commit fba53fc8a0
5 files changed
+56 -48

No files matched your search

+8
View File
@@ -1,5 +1,13 @@
# CLAUDE.md
## Public Repository
This repo is open-source and synced to Codeberg. When making changes:
- **Never commit sensitive data** — no internal URLs, tokens, credentials, private infrastructure details, or instance-specific configuration in `src/`, `action.yml`, `base-action/`, or `docs/`. The `.forgejo/workflows/` directory is the only place with instance-specific config (runner labels, bot IDs, internal URLs) and that's fine — users write their own workflows.
- **Keep Forgejo support generic** — all Forgejo code must work for any Forgejo instance, not just ours. Don't hardcode assumptions about our setup. Use action inputs and environment variables for instance-specific values.
- **Use generic URLs in tests** — test fixtures use `forgejo.example.com` as the sample Forgejo URL. Never use real instance URLs in `src/` or `test/` code.
## Commands
```bash
+7 -7
View File
@@ -36,9 +36,9 @@ on:
jobs:
claude-response:
runs-on: grunt # Your Forgejo runner label
runs-on: ubuntu-latest # Your Forgejo runner label
steps:
- uses: https://git.wxs.ro/actions/claude-code-action@v1 # Or your mirror URL
- uses: https://your-forgejo.example.com/actions/claude-code-action@v1 # Or your mirror URL
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
platform: "forgejo"
@@ -63,9 +63,9 @@ on:
jobs:
run-claude:
runs-on: grunt
runs-on: ubuntu-latest
steps:
- uses: https://git.wxs.ro/actions/claude-code-action@v1
- uses: https://your-forgejo.example.com/actions/claude-code-action@v1
with:
prompt: ${{ github.event.inputs.task }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -260,7 +260,7 @@ curl -s "https://your-forgejo-instance/api/v1/users/claude" | jq '.id'
#### 6. Configure the workflow
```yaml
- uses: https://git.wxs.ro/actions/claude-code-action@v1
- uses: https://your-forgejo.example.com/actions/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
platform: "forgejo"
@@ -357,7 +357,7 @@ New upstream features that use GraphQL or GitHub-specific APIs won't automatical
## E2E Test Results
All execution modes and trigger types have been validated end-to-end on a Forgejo instance (git.wxs.ro):
All execution modes and trigger types have been validated end-to-end on a Forgejo instance:
| Mode | Trigger | Status | Details |
| -------------- | ------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -367,7 +367,7 @@ All execution modes and trigger types have been validated end-to-end on a Forgej
| **Tag mode** | `pull_request_review` | Validated | Claude responds to `@claude` in PR review body. Forgejo sends `pull_request_comment` instead of `pull_request_review` — the `@claude` check runs in `trigger.ts`, not the workflow `if:` condition |
| **Tag mode** | `issues` with `labeled` action | Validated | Claude responds when the configured label is applied. 3 bugs fixed: workflow `if:` expression parser rejects `#` comments, `github.event.action` not populated in `if:` context, event action is `label_updated` not `labeled` |
| **Tag mode** | `issues` with `assigned` action | Validated | Claude responds when assigned to an issue. 1 bug fixed: `assignee` field missing from top-level payload (nested under `issue.assignee` instead) |
| **Tag mode** | Code changes (branch + commits) | Validated | Claude creates branch, pushes commits, links branch in tracking comment. Bot identity (`claude <claude@wxs.ro>`) correct. PR compare URL uses `expand=1` (Forgejo) instead of `quick_pull=1` (GitHub) |
| **Tag mode** | Code changes (branch + commits) | Validated | Claude creates branch, pushes commits, links branch in tracking comment. Bot identity correct. PR compare URL uses `expand=1` (Forgejo) instead of `quick_pull=1` (GitHub) |
### Tag Mode Verified Capabilities
+35 -35
View File
@@ -17,7 +17,7 @@ import {
// Test helpers
// ---------------------------------------------------------------------------
const FORGEJO_SERVER = "https://git.wxs.ro";
const FORGEJO_SERVER = "https://forgejo.example.com";
const GITHUB_SERVER = "https://github.com";
/**
@@ -89,9 +89,9 @@ describe("createForgejoJobRunLink", () => {
afterEach(() => setServerUrl(GITHUB_SERVER));
it("creates a job run link with Forgejo server URL", () => {
const result = createForgejoJobRunLink("wxs", "myrepo", "42");
const result = createForgejoJobRunLink("myorg", "myrepo", "42");
expect(result).toBe(
"[View job run](https://git.wxs.ro/wxs/myrepo/actions/runs/42)",
"[View job run](https://forgejo.example.com/myorg/myrepo/actions/runs/42)",
);
});
@@ -110,15 +110,15 @@ describe("createForgejoBranchLink", () => {
afterEach(() => setServerUrl(GITHUB_SERVER));
it("creates a branch link with /tree/ path", () => {
const result = createForgejoBranchLink("wxs", "myrepo", "feature-branch");
const result = createForgejoBranchLink("myorg", "myrepo", "feature-branch");
expect(result).toBe(
"\n[View branch](https://git.wxs.ro/wxs/myrepo/tree/feature-branch)",
"\n[View branch](https://forgejo.example.com/myorg/myrepo/tree/feature-branch)",
);
});
it("handles branch names with slashes", () => {
const result = createForgejoBranchLink(
"wxs",
"myorg",
"myrepo",
"claude/issue-5-20240101-1200",
);
@@ -134,7 +134,7 @@ describe("createForgejoPrCompareUrl", () => {
it("builds compare URL without quick_pull=1", () => {
const result = createForgejoPrCompareUrl(
FORGEJO_SERVER,
"wxs",
"myorg",
"myrepo",
"main",
"feature-branch",
@@ -143,7 +143,7 @@ describe("createForgejoPrCompareUrl", () => {
);
expect(result).toBe(
`${FORGEJO_SERVER}/wxs/myrepo/compare/main...feature-branch?expand=1&title=Fix%20bug&body=Fixes%20issue%20%231`,
`${FORGEJO_SERVER}/myorg/myrepo/compare/main...feature-branch?expand=1&title=Fix%20bug&body=Fixes%20issue%20%231`,
);
expect(result).not.toContain("quick_pull");
});
@@ -151,7 +151,7 @@ describe("createForgejoPrCompareUrl", () => {
it("uses expand=1 parameter for Forgejo", () => {
const result = createForgejoPrCompareUrl(
FORGEJO_SERVER,
"wxs",
"myorg",
"myrepo",
"main",
"feature",
@@ -202,7 +202,7 @@ describe("createForgejoCommentBody", () => {
it("uses Forgejo spinner instead of GitHub CDN image", () => {
const result = createForgejoCommentBody(
"[View job run](https://git.wxs.ro/wxs/myrepo/actions/runs/1)",
"[View job run](https://forgejo.example.com/myorg/myrepo/actions/runs/1)",
);
expect(result).toContain(FORGEJO_SPINNER_HTML);
expect(result).not.toContain("github.com/user-attachments");
@@ -211,7 +211,7 @@ describe("createForgejoCommentBody", () => {
it("includes working message and job run link", () => {
const jobLink =
"[View job run](https://git.wxs.ro/wxs/myrepo/actions/runs/42)";
"[View job run](https://forgejo.example.com/myorg/myrepo/actions/runs/42)";
const result = createForgejoCommentBody(jobLink);
expect(result).toContain("Claude Code is working…");
expect(result).toContain("I'll analyze this and get back to you.");
@@ -220,9 +220,9 @@ describe("createForgejoCommentBody", () => {
it("includes branch link when provided", () => {
const jobLink =
"[View job run](https://git.wxs.ro/wxs/myrepo/actions/runs/42)";
"[View job run](https://forgejo.example.com/myorg/myrepo/actions/runs/42)";
const branchLink =
"\n[View branch](https://git.wxs.ro/wxs/myrepo/tree/feature)";
"\n[View branch](https://forgejo.example.com/myorg/myrepo/tree/feature)";
const result = createForgejoCommentBody(jobLink, branchLink);
expect(result).toContain(branchLink);
});
@@ -235,10 +235,10 @@ describe("createForgejoCommentBody", () => {
describe("extractOwnerRepoFromUrl", () => {
it("extracts owner/repo from Forgejo job URL", () => {
const result = extractOwnerRepoFromUrl(
"https://git.wxs.ro/wxs/myrepo/actions/runs/42",
"https://forgejo.example.com/myorg/myrepo/actions/runs/42",
FORGEJO_SERVER,
);
expect(result).toEqual({ owner: "wxs", repo: "myrepo" });
expect(result).toEqual({ owner: "myorg", repo: "myrepo" });
});
it("extracts owner/repo from GitHub job URL", () => {
@@ -251,10 +251,10 @@ describe("extractOwnerRepoFromUrl", () => {
it("extracts owner/repo from branch URL", () => {
const result = extractOwnerRepoFromUrl(
"https://git.wxs.ro/wxs/myrepo/tree/feature-branch",
"https://forgejo.example.com/myorg/myrepo/tree/feature-branch",
FORGEJO_SERVER,
);
expect(result).toEqual({ owner: "wxs", repo: "myrepo" });
expect(result).toEqual({ owner: "myorg", repo: "myrepo" });
});
it("returns null when hosts don't match", () => {
@@ -267,7 +267,7 @@ describe("extractOwnerRepoFromUrl", () => {
it("returns null for URLs with less than 2 path segments", () => {
const result = extractOwnerRepoFromUrl(
"https://git.wxs.ro/only-one-segment",
"https://forgejo.example.com/only-one-segment",
FORGEJO_SERVER,
);
expect(result).toBeNull();
@@ -299,9 +299,9 @@ describe("extractOwnerRepoFromUrl", () => {
process.env.GITHUB_SERVER_URL = FORGEJO_SERVER;
try {
const result = extractOwnerRepoFromUrl(
"https://git.wxs.ro/wxs/myrepo/actions/runs/42",
"https://forgejo.example.com/myorg/myrepo/actions/runs/42",
);
expect(result).toEqual({ owner: "wxs", repo: "myrepo" });
expect(result).toEqual({ owner: "myorg", repo: "myrepo" });
} finally {
process.env.GITHUB_SERVER_URL = originalUrl;
}
@@ -317,7 +317,7 @@ describe("updateCommentBody", () => {
currentBody: "Initial comment body",
actionFailed: false,
executionDetails: null,
jobUrl: "https://git.wxs.ro/wxs/myrepo/actions/runs/42",
jobUrl: "https://forgejo.example.com/myorg/myrepo/actions/runs/42",
branchName: undefined,
triggerUsername: undefined,
};
@@ -418,7 +418,7 @@ describe("updateCommentBody", () => {
// This is the critical fix: GitHub's version uses a hardcoded github.com regex
// which fails for Forgejo URLs. Our version uses extractOwnerRepoFromUrl.
expect(result).toContain(
"• [`claude/issue-5-20240101-1200`](https://git.wxs.ro/wxs/myrepo/tree/claude/issue-5-20240101-1200)",
"• [`claude/issue-5-20240101-1200`](https://forgejo.example.com/myorg/myrepo/tree/claude/issue-5-20240101-1200)",
);
});
@@ -439,12 +439,12 @@ describe("updateCommentBody", () => {
...forgejoBaseInput,
branchName: "feature-branch",
branchLink:
"\n[View branch](https://git.wxs.ro/wxs/myrepo/tree/feature-branch)",
"\n[View branch](https://forgejo.example.com/myorg/myrepo/tree/feature-branch)",
};
const result = updateCommentBody(input);
expect(result).toContain(
"• [`feature-branch`](https://git.wxs.ro/wxs/myrepo/tree/feature-branch)",
"• [`feature-branch`](https://forgejo.example.com/myorg/myrepo/tree/feature-branch)",
);
});
@@ -452,12 +452,12 @@ describe("updateCommentBody", () => {
const input: CommentUpdateInput = {
...forgejoBaseInput,
branchLink:
"\n[View branch](https://git.wxs.ro/wxs/myrepo/tree/auto-detected-branch)",
"\n[View branch](https://forgejo.example.com/myorg/myrepo/tree/auto-detected-branch)",
};
const result = updateCommentBody(input);
expect(result).toContain(
"• [`auto-detected-branch`](https://git.wxs.ro/wxs/myrepo/tree/auto-detected-branch)",
"• [`auto-detected-branch`](https://forgejo.example.com/myorg/myrepo/tree/auto-detected-branch)",
);
});
});
@@ -467,12 +467,12 @@ describe("updateCommentBody", () => {
const input: CommentUpdateInput = {
...forgejoBaseInput,
prLink:
"\n[Create a PR](https://git.wxs.ro/wxs/myrepo/compare/main...feature)",
"\n[Create a PR](https://forgejo.example.com/myorg/myrepo/compare/main...feature)",
};
const result = updateCommentBody(input);
expect(result).toContain(
"• [Create PR ➔](https://git.wxs.ro/wxs/myrepo/compare/main...feature)",
"• [Create PR ➔](https://forgejo.example.com/myorg/myrepo/compare/main...feature)",
);
});
@@ -480,19 +480,19 @@ describe("updateCommentBody", () => {
const input: CommentUpdateInput = {
...forgejoBaseInput,
currentBody:
"Some comment with [Create a PR](https://git.wxs.ro/wxs/myrepo/compare/main...fix)",
"Some comment with [Create a PR](https://forgejo.example.com/myorg/myrepo/compare/main...fix)",
};
const result = updateCommentBody(input);
expect(result).toContain(
"• [Create PR ➔](https://git.wxs.ro/wxs/myrepo/compare/main...fix)",
"• [Create PR ➔](https://forgejo.example.com/myorg/myrepo/compare/main...fix)",
);
expect(result).not.toContain("[Create a PR]");
});
it("handles Forgejo PR URLs with expand=1 parameter", () => {
const forgejoUrl =
"https://git.wxs.ro/wxs/myrepo/compare/main...feature?expand=1&title=Fix%20bug&body=Desc";
"https://forgejo.example.com/myorg/myrepo/compare/main...feature?expand=1&title=Fix%20bug&body=Desc";
const input: CommentUpdateInput = {
...forgejoBaseInput,
currentBody: `Done!\n\n[Create a PR](${forgejoUrl})`,
@@ -550,7 +550,7 @@ describe("updateCommentBody", () => {
actionFailed: false,
branchName: "claude-branch-123",
prLink:
"\n[Create a PR](https://git.wxs.ro/wxs/myrepo/compare/main...claude-branch-123)",
"\n[Create a PR](https://forgejo.example.com/myorg/myrepo/compare/main...claude-branch-123)",
executionDetails: { duration_ms: 65000 },
triggerUsername: "trigger-user",
};
@@ -563,7 +563,7 @@ describe("updateCommentBody", () => {
);
expect(result).toContain("—— [View job]");
expect(result).toContain(
"• [`claude-branch-123`](https://git.wxs.ro/wxs/myrepo/tree/claude-branch-123)",
"• [`claude-branch-123`](https://forgejo.example.com/myorg/myrepo/tree/claude-branch-123)",
);
expect(result).toContain("• [Create PR ➔]");
@@ -610,7 +610,7 @@ describe("updateCommentBody", () => {
const input: CommentUpdateInput = {
...forgejoBaseInput,
currentBody:
"Some work done\n[View job run](https://git.wxs.ro/wxs/myrepo/actions/runs/1)",
"Some work done\n[View job run](https://forgejo.example.com/myorg/myrepo/actions/runs/1)",
triggerUsername: "user",
};
@@ -623,7 +623,7 @@ describe("updateCommentBody", () => {
const input: CommentUpdateInput = {
...forgejoBaseInput,
currentBody:
"Some work done\n[View branch](https://git.wxs.ro/wxs/myrepo/tree/old-branch)",
"Some work done\n[View branch](https://forgejo.example.com/myorg/myrepo/tree/old-branch)",
branchName: "new-branch",
triggerUsername: "user",
};
+5 -5
View File
@@ -70,7 +70,7 @@ describe("M7: Platform routing for mode handlers", () => {
it('returns "forgejo" when GITHUB_SERVER_URL is not github.com', () => {
delete process.env.PLATFORM;
delete process.env.FORGEJO;
process.env.GITHUB_SERVER_URL = "https://git.wxs.ro";
process.env.GITHUB_SERVER_URL = "https://forgejo.example.com";
expect(detectPlatform()).toBe("forgejo");
});
@@ -139,7 +139,7 @@ describe("M7: Forgejo PR compare URL format", () => {
);
const url = createForgejoPrCompareUrl(
"https://git.wxs.ro",
"https://forgejo.example.com",
"owner",
"repo",
"main",
@@ -150,7 +150,7 @@ describe("M7: Forgejo PR compare URL format", () => {
expect(url).toContain("expand=1");
expect(url).not.toContain("quick_pull=1");
expect(url).toContain("git.wxs.ro");
expect(url).toContain("forgejo.example.com");
expect(url).toContain("compare/main...claude/fix-bug");
});
});
@@ -167,10 +167,10 @@ describe("M7: unified updateCommentBody handles both platforms", () => {
const result = updateCommentBody({
currentBody:
"Claude Code is working… ⏳\n\nI'll analyze this and get back to you.\n\n[View job run](https://git.wxs.ro/owner/repo/actions/runs/123)",
"Claude Code is working… ⏳\n\nI'll analyze this and get back to you.\n\n[View job run](https://forgejo.example.com/owner/repo/actions/runs/123)",
actionFailed: false,
executionDetails: { duration_ms: 30000 },
jobUrl: "https://git.wxs.ro/owner/repo/actions/runs/123",
jobUrl: "https://forgejo.example.com/owner/repo/actions/runs/123",
triggerUsername: "testuser",
});
+1 -1
View File
@@ -75,7 +75,7 @@ describe("detectPlatform", () => {
describe("GITHUB_SERVER_URL heuristic", () => {
it("should return 'forgejo' for non-github.com server URLs", () => {
process.env.GITHUB_SERVER_URL = "https://git.wxs.ro";
process.env.GITHUB_SERVER_URL = "https://forgejo.example.com";
expect(detectPlatform()).toBe("forgejo");
});