No description
  • Go 91.6%
  • Makefile 8.4%
Find a file
Jovan Djokic-Sumarac 72114d3612
Initial commit: Forgejo webhook bot for Mattermost
Relays Forgejo events (issues, PRs, comments, reviews, pushes,
releases, forks) to a configured Mattermost channel via plugin.
2026-07-13 23:41:40 +02:00
server Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
.gitignore Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
go.mod Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
go.sum Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
Makefile Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
plugin.json Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00
README.md Initial commit: Forgejo webhook bot for Mattermost 2026-07-13 23:41:40 +02:00

Forgejo Bot — Mattermost Plugin

Relays Forgejo webhook events (issues, pull requests, comments, reviews, pushes, releases) into a Mattermost channel. Runs inside Mattermost — no external relay service needed.

How it works

Forgejo (webhook) ──POST──► Mattermost plugin (ServeHTTP) ──CreatePost──► target channel
  1. A Forgejo repository fires a webhook on an event (issue opened, PR merged, comment posted, etc.)
  2. The webhook POSTs a JSON payload to the plugin's HTTP endpoint on the Mattermost server
  3. The plugin verifies the HMAC-SHA256 signature and skips duplicate deliveries
  4. The plugin formats a Markdown message and posts it to the configured channel using the bot user

Event types handled

Event Example message
issues alice opened issue #42 Fix login in org/repo
pull_request bob merged PR #18 Add cache in org/repo
issue_comment carol commented on issue #42 Fix login:\n> Looks good, ...
pull_request_review dave approved PR #18 Add cache in org/repo
pull_request_review_comment dave commented on PR #18 Add cache:\n> Nice approach, ...
push eve pushed to main in org/repo
create eve created refs/heads/feature-x in org/repo
delete eve deleted refs/heads/feature-x in org/repo
fork frank forked org/repo
release grace released v1.3.0 in org/repo

Installation on a self-hosted Mattermost instance

Prerequisites

  • Mattermost server 7.1+ (for EnsureBotUser API)
  • Go 1.21+ for building
  • Admin access to the Mattermost server filesystem and System Console

Step 1: Build the plugin

git clone <this-repo> forgejo-bot
cd forgejo-bot
make package

This produces forgejo-bot.tar.gz with the plugin binary and manifest.

If you don't have Go installed on the Mattermost host, cross-compile on your dev machine:

# From your dev machine:
make build
# Copy server/dist/ and plugin.json to the Mattermost host

Step 2: Install the plugin

Copy the tarball to the Mattermost server and extract it into the plugins directory:

# On the Mattermost server:
cd /opt/mattermost
mkdir -p plugins/cool.bonsai.forgejo-bot
tar -xzf /path/to/forgejo-bot.tar.gz -C plugins/cool.bonsai.forgejo-bot

# Ensure correct permissions:
chown -R mattermost:mattermost plugins/cool.bonsai.forgejo-bot
chmod +x plugins/cool.bonsai.forgejo-bot/server/dist/plugin-linux-amd64

Step 3: Enable and configure the plugin

  1. Go to System Console → Plugins → Plugin Management
  2. Find "Forgejo Bot" and click Enable
  3. Go to System Console → Plugins → Forgejo Bot
  4. Fill in the settings:
Setting Value
Webhook Secret A random string, e.g. openssl rand -hex 32. Keep a copy for Forgejo.
Target Team The Mattermost team URL name, e.g. main-team
Target Channel The channel name, e.g. git-activity

Step 4: Verify the bot user exists

After enabling the plugin, check that the bot user was created:

  • Go to System Console → Users
  • You should see a user named "forgejo" with type "Bot"

If not, disable and re-enable the plugin to trigger OnActivate again.

Step 5: Configure the webhook in Forgejo

For each repository (or at the organization level):

  1. Go to Settings → Webhooks (/:username/:reponame/settings/hooks)
  2. Click Add Webhook, choose Forgejo
  3. Fill in:
Field Value
Target URL https://mattermost.example.com/plugins/cool.bonsai.forgejo-bot
HTTP Method POST
POST Content Type application/json
Secret The same secret you set in the plugin config
Trigger On Select custom events: Issues, Pull Request, Issue Comments, Pull Request Reviews, Pull Request Review Comments, Push, Create, Delete, Fork, Release
Active Checked
  1. Click Add Webhook, then click Test Delivery to verify

If the test delivery succeeds, you should see a message appear in the target Mattermost channel.

Docker installation

For Mattermost instances running in Docker (official mattermost/mattermost-team-edition image).

Step 1: Build the plugin

On your dev machine:

git clone <this-repo> forgejo-bot
cd forgejo-bot
make package

Step 2: Extract plugin into the host's plugins volume

# Create the plugin directory on the Docker host
mkdir -p /opt/mattermost/plugins/cool.bonsai.forgejo-bot

# Extract the tarball
tar -xzf forgejo-bot.tar.gz -C /opt/mattermost/plugins/cool.bonsai.forgejo-bot

# Ensure correct ownership (container runs as UID 2000 by default)
chown -R 2000:2000 /opt/mattermost/plugins/cool.bonsai.forgejo-bot
chmod +x /opt/mattermost/plugins/cool.bonsai.forgejo-bot/server/dist/plugin-linux-amd64

Step 2 (alternative): Copy into running container

# Extract on the host first
mkdir -p /tmp/forgejo-bot-plugin
tar -xzf forgejo-bot.tar.gz -C /tmp/forgejo-bot-plugin

# Copy into the container
docker cp /tmp/forgejo-bot-plugin/. mattermost:/mattermost/plugins/cool.bonsai.forgejo-bot/

# Fix ownership inside the container (UID 2000)
docker exec mattermost chown -R 2000:2000 /mattermost/plugins/cool.bonsai.forgejo-bot
docker exec mattermost chmod +x /mattermost/plugins/cool.bonsai.forgejo-bot/server/dist/plugin-linux-amd64

docker-compose setup

If using docker-compose.yml, mount a plugins directory so the plugin survives container restarts:

services:
  mattermost:
    image: mattermost/mattermost-team-edition:latest
    volumes:
      - ./volumes/app/mattermost/config:/mattermost/config:rw
      - ./volumes/app/mattermost/data:/mattermost/data:rw
      - ./volumes/app/mattermost/logs:/mattermost/logs:rw
      - ./volumes/app/mattermost/plugins:/mattermost/plugins:rw
      - ./volumes/app/mattermost/client/plugins:/mattermost/client/plugins:rw

After adding the plugin to ./volumes/app/mattermost/plugins/, restart the container:

docker compose restart mattermost

Step 3: Enable and configure

Same as bare-metal installation steps 3-5 above.

Note: If the plugin doesn't appear in System Console after restart, run docker exec mattermost ls /mattermost/plugins/ to verify it was extracted correctly.

Troubleshooting

No messages appearing:

  • Check Mattermost server logs: journalctl -u mattermost -f or /opt/mattermost/logs/mattermost.log
  • Verify the secret matches exactly between Forgejo and the plugin config
  • Verify the team and channel names match exactly (case-sensitive)
  • Check that the bot user exists in System Console → Users
  • Check the Forgejo webhook delivery history at the webhook settings page

"channel not found" in logs:

  • The team or channel name in plugin config doesn't match. Team name is the URL slug (lowercase, hyphens), not the display name.
  • The bot user must be a member of the team (Mattermost auto-adds bots to teams, but verify in System Console → Teams).

"unauthorized" in logs:

  • The webhook secret is empty or doesn't match between Forgejo and the plugin.

Architecture notes

Plugin endpoint

The plugin listens at GET/POST /plugins/cool.bonsai.forgejo-bot. Only POST with a valid HMAC signature and X-Forgejo-Event header is processed. GET returns 405.

Idempotency

Duplicate deliveries (same X-Forgejo-Delivery UUID) are detected via the KV store and silently dropped. The KV store lives in the Mattermost database, so it survives plugin restarts.

Configuration

Settings are stored in the Mattermost PluginKeyValueStore via the System Console. The ForgejoSecret field is marked secret: true, so it's masked in the UI and API responses.

Bot user

A bot named forgejo is created on plugin activation. All messages are posted as this bot, keeping activity distinct from real users. The bot ID is persisted in the KV store for efficiency.

Building from source

# First time: download the Mattermost server dependency and generate go.sum
go mod tidy
# Then build
make build          # compile for all platforms
make package        # build + tar.gz
make clean          # remove build artifacts

License

MIT