Skip to content

Code hosts: GitHub, GitLab, Azure DevOps, Bitbucket, Gitea and Forgejo ​

CodeLotse reviews, triages and assigns on GitHub, GitLab, Azure DevOps, Bitbucket, Gitea and Forgejo. GitHub uses GitHub Apps that an instance admin registers in the setup wizard. GitLab (gitlab.com and self-managed), Azure DevOps Repos (Services and Server), Bitbucket Cloud, Bitbucket Data Center, Gitea and Forgejo use connections: a tenant admin connects a host with a token, CodeLotse imports the repositories in scope, and the host sends events to a webhook that belongs to the connection. What works where is listed in the feature parity matrix.

GitHub App permission for CI failure analysis ​

CI failure analysis reads the logs of failed GitHub Actions jobs and needs the repository permission Actions: read on the review app, in addition to Checks, Contents: read and Pull requests: write. It subscribes to no new event: the check_run event the review app already receives is delivered for check runs of every app, including GitHub Actions.

  • Apps created from the setup wizard from this release on request Actions: read in their manifest.
  • A manifest only applies when an app is created. Owners of an existing app add the permission themselves: GitHub (or GHES) → Settings → Developer settings → GitHub Apps → CodeLotse → Permissions & events → Repository permissions → Actions: Read-only → Save changes.
  • GitHub then asks every installation to accept the new permission (organisation Settings → GitHub Apps → CodeLotse → Review request). Until an installation accepts, everything else keeps working; the CI section of the repository policy shows "missing permission actions:read" and no analysis runs for that installation. CodeLotse picks up the accepted permission from the installation webhook without a restart.
  • Logs are downloaded from the address GitHub redirects to, without the GitHub token, over https only, at most 20 MiB per job. In the enterprise edition the download uses the guarded HTTP client (no private addresses, no further redirects); self-hosted instances may download from internal storage of a GHES host.

Other code hosts do not report check runs to CodeLotse; CI failure analysis is not available there (ciLogs capability none).

Connections ​

Organisation Settings → Code hosts → Connect a code host. Only tenant admins can manage connections; every change is written to the audit log.

FieldGitLabAzure DevOps
Base URLhttps://gitlab.com or the URL of your instance, including a path prefix if GitLab runs under onehttps://dev.azure.com/<organization>; Azure DevOps Server: the collection URL, for example https://ado.example.com/tfs/DefaultCollection
Scope (one entry per line)Group paths (all projects of the group and its subgroups) or project paths (group/subgroup/project)Project names (all repositories of the project) or project/repository
CredentialGroup or project access token (recommended) or personal access tokenPersonal access token (default) or a Microsoft Entra application
FieldBitbucket CloudBitbucket Data CenterGitea and Forgejo
Base URLAlways https://bitbucket.orgURL of the instance, including a context pathURL of the instance, for example https://codeberg.org
Scope (one entry per line)Workspaces (all repositories) or workspace/repositoryProject keys (all repositories) or PROJECT/repositoryOrganisations or users (all repositories they own) or owner/repository
CredentialRepository, project or workspace access tokenProject or repository HTTP access token (personal tokens work too)Access token of a dedicated bot user

After saving, CodeLotse shows the webhook URL and the webhook secret. The secret is shown exactly once; store it in the host's webhook settings right away. Rotate webhook secret issues a new one (the old one stops working within a minute) and shows it once.

Sync now checks the credential, records the account the token belongs to (CodeLotse recognises its own comments by it), and imports the repositories in scope. Run it after changing the scope or the credential. Repositories that left the scope are removed from CodeLotse together with their pull requests, issues and policies. New repositories start with every feature off, as on GitHub; enable them per repository.

Deleting a connection removes its credential and suspends its repositories; nothing is posted for them any more.

Security &ZeroWidthSpace;

  • The credential and the webhook secret are encrypted with the instance key (AES-256-GCM, bound to the connection id) and re-encrypted by quavon keys rotate. The API never returns them; the settings show the last four characters of the credential only.
  • Webhook requests are authenticated before anything is stored: GitLab sends the secret in X-Gitlab-Token, Azure DevOps as the password of HTTP basic authentication. Bitbucket Cloud and Data Center sign the raw body with HMAC-SHA256 (X-Hub-Signature: sha256=…), Gitea in X-Gitea-Signature and Forgejo in X-Forgejo-Signature (hex HMAC-SHA256, no prefix). Secrets and signatures are compared in constant time. Unknown connections and wrong secrets get the same 401; repeated failures from one source are rate limited like the GitHub webhook.
  • Every delivery is stored once per connection (GitLab X-Gitlab-Event-UUID, Azure DevOps notification id, Bitbucket Cloud X-Request-UUID, Bitbucket Data Center X-Request-Id, Gitea X-Gitea-Delivery, Forgejo X-Forgejo-Delivery), so redeliveries are not processed twice.
  • In the enterprise edition the base URL must use https and resolve to a public address, and all calls to the host go through the guarded HTTP client (no redirects, no private addresses at connect time). Self-hosted instances may use http for hosts on a private network.
  • Calls to every host go through the same request budget as GitHub, per connection. Retry-After, GitLab RateLimit-* and Azure DevOps X-RateLimit-* headers are honoured; a throttled connection pauses instead of failing jobs.

GitLab &ZeroWidthSpace;

  1. Create a group access token on the group in scope (Settings → Access tokens) with role Developer and scope api. Developer can comment, set commit statuses, labels, assignees and reviewers. A token with only read_api is accepted for shadow mode; CodeLotse then only reads. Personal access tokens work too, but every comment then appears under that person's name.
  2. Add the connection in CodeLotse and click Sync now.
  3. Add a webhook on the group (Premium and Ultimate) or on each project (Settings → Webhooks):
    • URL: the webhook URL of the connection
    • Secret token: the webhook secret
    • Trigger: Merge request events, Comments, Issues events, Push events. Do not enable confidential issue or confidential comment events; CodeLotse ignores them.
    • Enable SSL verification.

On self-managed GitLab the instance must be able to reach the CodeLotse URL; if CodeLotse runs on a private network, an administrator has to allow webhooks to local addresses (Admin → Settings → Network → Outbound requests).

How CodeLotse uses GitLab:

  • Reviews are posted atomically: inline comments are created as draft notes on the latest merge request version (with position base/start/head SHAs, old_line/new_line and line_range for multi-line findings) and published together with the summary. Suggestions use GitLab's native ```suggestion:-N+0 syntax and can be applied in the merge request.
  • The review result is a commit status named CodeLotse on the head commit. Because commit statuses carry only a short description, the severity table and the acceptance-criteria summary are part of the review summary note.
  • CODEOWNERS is read from CODEOWNERS, docs/CODEOWNERS or .gitlab/CODEOWNERS with GitLab semantics: sections ([Section], optional ^[Section], approval counts) and section default owners. Approval rules stay enforced by GitLab; reviewers requested by CodeLotse are added to the existing ones.
  • Merge request webhooks do not contain the base commit; CodeLotse reads it from the API when the event arrives.

Azure DevOps &ZeroWidthSpace;

  1. Create a personal access token for a dedicated service account with the scopes Code (Read & write), Code (Status), Identity (Read) and Project and Team (Read), limited to the organization. Alternatively, register a Microsoft Entra application, add its service principal to the organization (Basic access, Contributor in the projects in scope) and enter the directory (tenant) id, client id and a client secret; CodeLotse requests tokens with the client-credentials flow.
  2. Add the connection in CodeLotse and click Sync now.
  3. In each project: Project settings → Service hooks → Create subscription → Web Hooks, once per event: Pull request created, Pull request updated, Pull request commented on, Code pushed. Settings: URL = webhook URL of the connection, basic authentication user name = any value (for example codelotse), password = webhook secret, resource details to send = All, resource version = latest.

How CodeLotse uses Azure DevOps:

  • Findings are posted as pull request threads anchored with threadContext (rightFileStart/rightFileEnd, or the left side for removed lines) on the latest iteration; the summary is posted as its own thread last. Fixed findings resolve their thread (status Fixed).
  • Azure Repos has no committable suggestions. Suggested code is shown as a plain code block under "Suggested change" with a note that it has to be applied manually.
  • The review result is a commit status (CodeLotse, genre quavon) on the head commit, and the severity table is part of the summary thread.
  • Azure Repos does not return unified diffs; CodeLotse computes them from the file contents at the merge base and the head of the latest iteration (at most 300 files and 1 MB per file; larger files are listed without a diff).
  • Required reviewers stay enforced by branch policies; reviewers requested by CodeLotse are added as optional reviewers.
  • Azure Repos has no issues. Triage and auto-replies need Azure Boards, which is connected separately as a work tracker.

Bitbucket Cloud &ZeroWidthSpace;

  1. Create a repository access token (Repository settings → Access tokens), a project access token or, on Premium, a workspace access token with the scopes Repositories: Read and Pull requests: Write. With read scopes only, CodeLotse runs in shadow mode. App passwords are no longer accepted by Bitbucket; Atlassian API tokens bound to a person are not supported because comments would appear under that person's name.
  2. Add the connection with base URL https://bitbucket.org and click Sync now.
  3. Add a webhook on the repository or the workspace (Repository settings → Webhooks):
    • URL: the webhook URL of the connection
    • Secret: the webhook secret
    • Triggers: Repository push and the pull request triggers Created, Updated, Approved, Approval removed, Changes request created, Merged, Declined, Comment created, Comment updated and Comment deleted.

How CodeLotse uses Bitbucket Cloud:

  • Findings are posted as inline comments (inline.to for the new side, inline.from for removed lines, start_to/start_from for multi-line findings), followed by the summary comment. Bitbucket has no review object, so comments are created one by one.
  • The review result is a Code Insights report (codelotse-review) on the head commit with one annotation per finding (at most 1000). A report fails when the policy blocks on critical findings; make it required with the Code Insights merge check where your plan offers it.
  • Fixed findings resolve their comment thread.
  • Access tokens cannot read their own account through the API. The connection therefore shows no bot account; CodeLotse recognises its own comments as app-user comments (shown with a [bot] suffix).
  • Bitbucket Cloud has no pull request labels; its issue tracker is not used (connect Jira as the work tracker). Bitbucket adds code owners (.bitbucket/CODEOWNERS) as reviewers itself, so CodeLotse does not read that file.

Bitbucket Data Center &ZeroWidthSpace;

Supported versions: 9.4 LTS and later (10.2 LTS is the main target). Earlier versions lack multi-line comment anchors (9.2), and 9.4 is the oldest release still supported by Atlassian. Older instances may work but are not tested.

  1. Create a project or repository HTTP access token (Project or Repository settings → HTTP access tokens) with Repository write permission. A personal HTTP access token of a service user works too.
  2. Add the connection with the instance URL and click Sync now. CodeLotse reads the token's user from the X-AUSERNAME response header.
  3. Add a webhook on the repository or project (Settings → Webhooks) with the webhook URL and the webhook secret, and select Repository push and the pull request events Opened, Source branch updated, Modified, Merged, Declined, Reviewers updated, Approved, Unapproved, Needs work, Comment added, Comment edited and Comment deleted.

How CodeLotse uses Bitbucket Data Center:

  • Findings are posted as comments with an anchor (path, line, lineType ADDED/REMOVED/CONTEXT, fileType FROM/TO, diffType EFFECTIVE, multilineMarker for multi-line findings), followed by the summary comment.
  • Suggestions use Bitbucket's ```suggestion blocks and can be applied in the pull request.
  • The review result is a Code Insights report with annotations; require it with the Code Insights merge check if critical findings should block merging.
  • Fixed findings resolve their thread (threadResolved).

Gitea and Forgejo &ZeroWidthSpace;

Gitea and Forgejo share one adapter. Supported versions: Gitea 1.26 and later (including 28.x) and Forgejo 15 LTS and later.

  1. Create a bot user, give it write access to the repositories in scope, and create an access token for it with the scopes write:repository, write:issue, read:user and read:organization.
  2. Add the connection (platform Gitea or Forgejo) and click Sync now.
  3. Add a webhook on the repository or organisation (Settings → Webhooks → Add webhook → Gitea or Forgejo) with the webhook URL as target URL, content type application/json and the webhook secret. Choose custom events: Push, Issues, Issue comment, Pull request, Pull request synchronized, Pull request reviewed and Pull request review requested. If CodeLotse runs on a private network, allow it in [webhook] ALLOWED_HOST_LIST (Forgejo) or [security] ALLOWED_HOST_LIST (Gitea 28).

How CodeLotse uses Gitea and Forgejo:

  • A review is posted as one pull request review with line comments (new_position for the new side, old_position for removed lines), so it appears atomically. Multi-line comments and committable suggestions are not available; suggested code is shown as a plain code block.
  • The review result is a commit status named CodeLotse on the head commit; the severity table is part of the review body.
  • Triage applies labels by name, assigns issues, and reviewers are requested through the API.
  • Gitea resolves the conversations of fixed findings. Forgejo has no API for this; its conversations stay open.
  • Gitea and Forgejo read CODEOWNERS with regular expressions and request those reviewers themselves; CodeLotse does not read the file.
  • There is no API to reply inside a review conversation; chat replies are posted as pull request comments.

Limitations of connections &ZeroWidthSpace;

  • Issue → draft PR, SARIF upload and code-scanning alerts are GitHub only. A SARIF upload for any other host is skipped with an audit entry; the findings stay in the review.
  • GitLab OAuth applications are not supported for the bot identity; use group or project access tokens. For Azure DevOps use a PAT or an Entra application; Azure DevOps OAuth apps are not supported.
  • GitLab draft notes belong to the token user. If two reviews of the same merge request publish at the same moment, or a crashed run left drafts behind, they are published together.
  • Missed deliveries are not fetched again: unlike GitHub, CodeLotse does not reconcile webhooks of connections. Both hosts show failed deliveries in their webhook settings, and GitLab disables a hook after repeated failures; re-enable it there. A new push to the merge request triggers a fresh review.
  • GitLab and Azure DevOps blame data has no host user ids; expertise ranking on these hosts relies on commit and merge-request history.
  • Bitbucket, Gitea and Forgejo have no API for user availability or open review load; assignment there ranks by expertise only. Bitbucket Cloud cannot look up users by name, so reviewers are matched against workspace members.
  • Gitea and Forgejo review incrementally against the full pull request diff; their API has no diff between two arbitrary commits.

The open core is released under the Apache License 2.0.