# OpenProject Gitea Integration An OpenProject module that integrates [Gitea](https://gitea.com) pull requests with OpenProject work packages — following the same patterns as the bundled GitHub and GitLab integrations. ## Overview When a pull request in Gitea references an OpenProject work package (via a URL or `OP#`), this plugin: - Records the pull request in OpenProject and links it to the work package - Posts automated journal comments on the work package when the PR is opened, merged, closed, or reopened - Shows a **Gitea** tab on the work package split-view listing all linked pull requests with their state and labels - Reacts to PR comments that mention a work package ## Supported webhook events | Gitea event | Effect in OpenProject | |---|---| | `pull_request` — opened | Links PR to work package; posts "PR Opened" comment | | `pull_request` — closed (not merged) | Updates PR state; posts "PR Closed" comment | | `pull_request` — closed (merged) | Updates PR state to merged; posts "PR Merged" comment | | `pull_request` — reopened | Updates PR state; posts "PR Reopened" comment | | `pull_request` — edited / synchronized | Updates the stored PR record (no comment) | | `issue_comment` — created | Posts a comment on any work package referenced in the comment body | ## Referencing work packages In a pull request title, description, or comment, reference a work package using: - Its semantic ID: `KS-10`, `PROJ-42` — matched automatically, no prefix needed - A prefixed numeric ID: `OP#42` — prefix required to avoid collision with Gitea issue numbers - A full OpenProject URL: `https://openproject.example.com/work_packages/42` Multiple references in the same text are all picked up. ## Requirements - OpenProject ≥ 13 - Ruby 3.4+ - The `openproject-webhooks` gem (bundled with OpenProject) ## Installation ### Packaged (DEB/RPM) installation Create a custom Gemfile (e.g. `/etc/openproject/Gemfile.custom`): ```ruby group :opf_plugins do gem 'openproject-gitea_integration', '~> 1.0' end ``` Tell OpenProject to use it and trigger a recompile of frontend assets: ```shell openproject config:set CUSTOM_PLUGIN_GEMFILE=/etc/openproject/Gemfile.custom openproject config:set RECOMPILE_ANGULAR_ASSETS=true sudo openproject configure ``` ### Docker / docker-compose installation The official OpenProject Docker image bakes all gems and frontend assets in at build time, so installing a third-party plugin requires building a custom image. The `docker-compose.yml` provided by OpenProject is overwritten on every update, so all local changes go into `docker-compose.override.yml` and a separate `Dockerfile` that you own. #### 1. Clone the plugin ```shell git clone https://github.com/quafzi/openproject-gitea-plugin.git \ openproject-gitea-plugin ``` Place it anywhere convenient — this guide assumes it sits next to your `docker-compose.yml`. #### 2. Create `Dockerfile.gitea` ```dockerfile FROM openproject/openproject:15 USER root # Copy the plugin source into the image COPY --chown=app:app openproject-gitea-plugin \ /app/modules/gitea_integration # Register the gem and recompile assets RUN echo 'group :opf_plugins do\n gem "openproject-gitea_integration", path: "modules/gitea_integration"\nend' \ > /app/Gemfile.plugins && \ cd /app && \ bundle install --without development test && \ RAILS_ENV=production bundle exec rake \ openproject:plugins:register_frontend \ assets:precompile USER app ``` #### 3. Create `docker-compose.override.yml` This file is never touched by OpenProject updates. Point both `web` and `worker` at your custom image — they must use the same image so the plugin is loaded in both processes. ```yaml services: web: build: context: . dockerfile: Dockerfile.gitea image: openproject-with-gitea:latest worker: build: context: . dockerfile: Dockerfile.gitea image: openproject-with-gitea:latest ``` #### 4. Build and start ```shell docker compose build docker compose up -d docker compose exec web bundle exec rails db:migrate ``` #### Updating the plugin ```shell cd openproject-gitea_integration && git pull && cd .. docker compose build --no-cache docker compose up -d docker compose exec web bundle exec rails db:migrate ``` ### Manual / monorepo installation 1. Clone this repository next to your OpenProject checkout, or place it at `modules/gitea_integration/` inside the OpenProject source tree. 2. Add the gem to your `Gemfile.plugins` (or `Gemfile.modules`): ```ruby group :opf_plugins do # from RubyGems: gem 'openproject-gitea_integration', '~> 1.0' # or from a local path: # gem 'openproject-gitea_integration', path: 'modules/gitea_integration' end ``` 3. Install dependencies: ```bash bundle install ``` 4. Run the database migration: ```bash bundle exec rails db:migrate ``` 5. Rebuild the frontend: ```bash cd frontend && npm ci && npm run build ``` ## Configuration ### 1. Create a bot user in OpenProject Create a dedicated OpenProject user that will post automated comments on work packages. Add this user to every project where you want the integration to be active, with a role that allows: - Viewing work packages - Adding work package comments Generate an **API token** for this user: 1. Log in as the bot user. 2. Go to **My Account → Access Tokens**. 3. Click **Generate** in the API row and copy the token. ### 2. Configure the plugin in OpenProject Go to **Administration → Integrations → Gitea** and set: - **Gitea actor** — the bot user created above. When set, only webhook requests authenticated with this user's API token are accepted. - **Webhook secret** — a shared secret used to verify the HMAC-SHA256 signature on incoming requests. Leaving this blank disables signature verification (not recommended). ### 3. Create a webhook in Gitea In each Gitea repository (or at the organisation level), go to **Settings → Webhooks → Add Webhook → Gitea**. | Field | Value | |---|---| | Target URL | `https://your-openproject.example.com/webhooks/gitea?key=` | | HTTP Method | POST | | Content Type | `application/json` | | Secret | The same value entered as the **Webhook secret** in OpenProject | | Trigger | **Custom events** → check **Pull Request** and **Issue Comment** | Replace `` with the API token generated for the bot user. > **Same-host installs:** If Gitea and OpenProject run on the same machine you may need to allow local network requests in Gitea's configuration (`[webhook] ALLOWED_HOST_LIST`). ### 4. Enable the Gitea module per project In each OpenProject project go to **Project Settings → Modules** and enable the **Gitea** module. This makes the Gitea tab visible on work packages. ## How it works ``` Gitea ──webhook──▶ /webhooks/gitea?key= │ HookHandler • verifies HMAC-SHA256 signature • checks user matches configured bot • dispatches OpenProject::Notifications event │ ┌────────────┴────────────┐ ▼ ▼ NotificationHandler NotificationHandler ::PullRequest ::IssueComment │ UpsertPullRequest / UpsertGiteaUser │ work_package.gitea_pull_requests (HABTM) │ WorkPackages::UpdateService (posts journal comment) ``` The work package split-view tab fetches linked pull requests via: ``` GET /api/v3/work_packages/:id/gitea_pull_requests ``` ## Development Run the OpenProject test suite against this module: ```bash bundle exec rspec modules/gitea_integration/spec ``` Lint Ruby: ```bash bundle exec rubocop modules/gitea_integration ``` Lint TypeScript: ```bash cd frontend && npx eslint src/ ``` ## License GNU General Public License v3 — see [LICENSE](../../LICENSE).