Forgejo and Codeberg
The Forgejo provider covers Codeberg and self-hosted Forgejo instances. It reads and writes issues and pull requests. It also covers notifications, commit statuses, releases, repository contents and repository and organisation webhooks. The Gitea provider uses the same implementation.
| Detail | Value |
|---|---|
| Import | forges/forgejo |
| Factories | forgejo(), forgejoLite() |
| Auth | token, anonymous |
Authentication
The provider accepts an access token. OAuth2 applications on Forgejo issue user tokens, which you pass the same way:
import { forgejo } from 'forges/forgejo'
const forge = forgejo({
auth: { type: 'token', token: process.env.CODEBERG_TOKEN! },
}).create()
Without auth, the provider makes anonymous public reads.
Instance
The default instance is https://codeberg.org. For a self-hosted instance, set baseUrl to the root of the instance. The provider appends /api/v1:
forgejo({ baseUrl: 'https://git.example.com', auth })
refreshCapabilities() reads the instance version from /version.
Marking notifications done
Forgejo notifications have a read state but no done state. markDone() is 'emulated': it marks the notification read and unsubscribes from the thread.
Merging
If you don't pass method, merge() reads the merge styles that the repository allows. When exactly one style is allowed, it uses that style. When several are allowed, it throws MergeMethodRequiredError. With whenChecksPass, Forgejo merges the pull request after its checks succeed.
Reviews
Reviews are native. createReview() without an event creates a pending review, and submitReview() submits it. The API doesn't expose whether a review conversation is resolved, so resolveReviewThread() is unavailable.
Checks and CI
checks.list() reads commit statuses, and checks.report() writes them. Forgejo Actions has no stable API for runs and jobs, so checks.rerun() and the ci methods are unavailable.
Changed files
threads.files() and contents.compare() return line counts for each file, but no patch. Forgejo serves diffs only for a whole pull request.
Search
search.threads() searches across repositories. It has no involves filter and returns results newest first. Passing involves adds a filter_unsupported warning. Passing a sort other than relevance adds a sort_unsupported warning.
Webhooks
Set webhookSecret to the secret configured on the hook:
const forge = forgejo({
webhookSecret: process.env.FORGEJO_WEBHOOK_SECRET,
}).create()
const events = await forge.webhooks.ingest({
headers: request.headers,
body: await request.text(),
})
Forgejo sends these headers with each delivery:
| Header | Content |
|---|---|
X-Forgejo-Signature | The hex HMAC-SHA256 of the body |
X-Forgejo-Event | The event name |
X-Forgejo-Delivery | The delivery ID |
The provider also accepts the X-Gitea-* version of each header.
A label delivery doesn't say which labels were added or removed. A changed label set becomes a label event with the edited action, and removing every label becomes one with the unlabelled action.
webhooks.deliveries() and webhooks.redeliver() are unavailable.
Recording fixtures
CODEBERG_TOKEN=... FIXTURE_FORGEJO_REPO=owner/repo \
FIXTURE_FORGEJO_PULL=1 pnpm record-fixtures forgejo
To add an issue, set FIXTURE_FORGEJO_ISSUE. To record another instance, set CODEBERG_BASE_URL.
Capabilities
Generated by pnpm capability-matrix; do not edit by hand.
| Capability | Support |
|---|---|
experimental | ❌ |
sources.poll | ✅ |
sources.webhook | ✅ |
sources.subscribe | ❌ |
repos.get | ✅ |
users.get | ✅ |
repos.list | ✅ |
repos.labels | ✅ |
repos.createLabel | experimental |
repos.milestones | ✅ |
repos.collaborators | ✅ |
repos.permissionFor | experimental |
repos.addCollaborator | experimental |
repos.assignableUsers | ✅ |
repos.reviewerCandidates | experimental |
threads.get | issue, PR, commit (experimental) |
threads.list | issue, PR |
threads.getMany | ✅ |
comments.list | issue, PR |
comments.edit | issue (experimental), PR (experimental) |
comments.delete | issue (experimental), PR (experimental) |
reactions.list | issue, PR |
notifications.list | ✅ |
notifications.markRead | ✅ |
notifications.markDone | emulated |
notifications.unsubscribe | ✅ |
notifications.markAllRead | ✅ |
notifications.markAllDone | ❌ |
notifications.unreadCount | ✅ |
writes.comment | issue (experimental), PR |
writes.upsertComment | issue (emulated), PR (emulated) |
writes.close | issue (experimental), PR |
writes.reopen | issue (experimental), PR |
writes.create | issue (experimental), PR (experimental) |
writes.update | issue (experimental), PR (experimental) |
writes.setLabels | issue (experimental), PR (experimental) |
writes.addLabels | issue (experimental), PR (experimental) |
writes.removeLabels | issue (experimental), PR (experimental) |
writes.setMilestone | issue (experimental), PR (experimental) |
writes.react | issue (experimental), PR (experimental) |
writes.setAssignees | issue (experimental), PR (experimental) |
writes.requestReview | PR (experimental) |
writes.merge | ✅ |
writes.approveAndMerge | ✅ |
writes.transfer | ❌ |
writes.markDuplicate | ❌ |
subscriptions.get | issue, PR |
subscriptions.set | issue, PR |
installations | ❌ |
checks.thread | PR |
checks.list | ✅ |
checks.report | experimental |
checks.rerun | ❌ |
ci.runs | ❌ |
ci.run | ❌ |
ci.jobs | ❌ |
ci.log | ❌ |
contents.file | ✅ |
contents.tree | ✅ |
contents.branches | ✅ |
contents.tags | ✅ |
contents.resolveRef | ✅ |
contents.commits | ✅ |
contents.commit | ✅ |
contents.compare | ✅ |
contents.threadFiles | ✅ |
contents.threadCommits | ✅ |
reviews.list | ✅ |
reviews.create | experimental |
reviews.submit | experimental |
reviews.approve | experimental |
reviews.resolveThread | ❌ |
releases.list | ✅ |
releases.get | ✅ |
releases.latest | ✅ |
releases.getByTag | ✅ |
releases.downloadAsset | experimental |
webhooks.list | experimental |
webhooks.create | experimental |
webhooks.update | experimental |
webhooks.delete | experimental |
webhooks.rotateSecret | experimental |
webhooks.deliveries | ❌ |
webhooks.redeliver | ❌ |
search.threads | ✅ |
search.repos | ✅ |
search.commits | ❌ |
securityAlerts | ❌ |
eventKinds | native |
auth | token, anonymous |
limits | unknown |