ForgeLink is a self-hosted automation bridge for Forgejo/Gitea users who want to leave GitHub without breaking deploy hooks, external CI triggers, and commit status reporting.
ForgeLink accepts Forgejo/Gitea webhooks, verifies HMAC signatures, normalizes events, matches YAML rules, queues delivery attempts, calls external providers and writes commit statuses back to the forge.
Forgejo/Gitea webhook
-> POST /hooks/forgejo/{repo_config_id}
-> verify HMAC
-> normalize event
-> match rules
-> enqueue deliveries
-> worker
-> provider adapter
-> update delivery state
-> report commit status
- A single Go binary for a VPS or homelab.
- A bridge for deploy hooks and external automation.
- A visible history of webhook events, deliveries, attempts and status reports.
- Not a GitHub clone.
- Not a full GitHub-compatible API.
- Not a CI runner.
- Not a GitHub Actions converter.
- Not a hosted SaaS relay.
go build ./cmd/forgelink
./forgelink init
cp .env.example .env
export FORGELINK_DASHBOARD_PASSWORD=change-me
export FORGELINK_SITE_WEBHOOK_SECRET=change-me
export GENERIC_CI_WEBHOOK_URL=http://localhost:9090/build
./forgelink config validate --config ./forgelink.yml
./forgelink serve --config ./forgelink.ymlDashboard: http://localhost:8080.
Start from examples/config.example.yml for local testing or provider-specific examples:
examples/vercel-only.ymlexamples/netlify-only.ymlexamples/digitalocean-only.ymlexamples/multi-destination.ymlexamples/pr-preview.yml
Secrets are referenced by environment variable names only. Do not put deploy hook URLs, tokens or webhook secrets directly into YAML.
Create a repository webhook:
- URL:
https://forgelink.example.com/hooks/forgejo/site - Content type:
application/json - Secret: value of
FORGELINK_SITE_WEBHOOK_SECRET - Events: push, tag push and pull request as needed
ForgeLink accepts X-Forgejo-Signature and X-Gitea-Signature HMAC SHA-256 signatures.
Vercel:
adapter: "vercel_deploy_hook"
hook_url_env: "VERCEL_SITE_PROD_DEPLOY_HOOK"Netlify:
adapter: "netlify_build_hook"
hook_url_env: "NETLIFY_SITE_PROD_BUILD_HOOK"DigitalOcean App Platform:
adapter: "digitalocean_app_platform"
app_id_env: "DO_APP_ID_SITE"
token_env: "DIGITALOCEAN_TOKEN"
force_build: trueVercel, Netlify and generic webhook statuses mean "trigger accepted", not "deployment finished".
DigitalOcean polling is optional and bounded by queue.worker_max_delivery_seconds; keep poll: false if you only need trigger-accepted semantics.
Set set_commit_status: true, configure status_context, and set the forge account token env var. ForgeLink posts to:
POST /api/v1/repos/{owner}/{repo}/statuses/{sha}
forgelink doctor --config ./forgelink.yml
forgelink simulate push --config ./forgelink.yml --repo site --payload examples/forgejo-webhook-push.json
forgelink events list --config ./forgelink.yml
forgelink events show <event_id> --config ./forgelink.yml
forgelink deliveries replay <delivery_id> --config ./forgelink.yml --confirm
forgelink destinations test site vercel-prod --config ./forgelink.yml --dry-run
forgelink lint-actions --path .
forgelink db prune --config ./forgelink.yml --dry-runforgelink lint-actions --path . scans .forgejo/workflows and .github/workflows and reports GitHub-specific workflow features that need review before running under Forgejo Actions. It is a linter, not a converter.
Use machine-readable output in CI:
forgelink lint-actions --path . --jsonReplay creates a new delivery linked to the original row. It never overwrites historical delivery state.
forgelink deliveries replay <delivery_id> --config ./forgelink.yml --confirmUse --dry-run first to inspect what would be replayed.
GET /metrics: Prometheus text exposition.GET /api/v1/metrics: JSON metrics.- Dashboard pages:
/,/events,/deliveries,/config,/health.
Enable Basic Auth before exposing the dashboard outside loopback.
- HMAC verification uses constant-time comparison.
- Body size and source IP allowlists are configurable.
- Provider calls use timeouts.
- Raw payload storage can be disabled with
security.store_raw_payloads: false. - Secrets are not stored in the config summary or dashboard.
Start with:
forgelink doctor --config ./forgelink.yml
curl -i http://localhost:8080/readyz
curl -s http://localhost:8080/api/v1/metricsMore detail: docs/troubleshooting.md.
Post-v1 work includes provider result polling for Vercel/Netlify, safer setup automation and a narrow compatibility facade only for proven external-tool needs.
MIT.