# GitLab merge request reviews

DBGorilla reviews merge requests on **GitLab.com**, on every plan including Free,
and on **self-managed GitLab**, Community and Enterprise editions, tested with
18.11, 19.2 and 19.4.  Setup takes about 15 minutes, from a GitLab group to the
first review.

[Pull request reviews](/docs/integrations/pull-request-reviews/) covers what a review
contains and what the connected review adds.

## Before you start

- The GitLab card is available in your DBGorilla account.  It is the
  **DBGorilla Review for GitLab** card under **Admin › Integrations**.  It is
  available to every account at once.  If it is not there, GitLab reviews are
  not available yet.
- You are a workspace admin in DBGorilla.  Connecting GitLab is an admin
  setting.
- You are an Owner of the GitLab group, so you can create the bot and its
  tokens, and a Maintainer of each project you want reviewed, so you can add
  its webhook.
- On self-managed GitLab, DBGorilla and your GitLab can reach each other over
  HTTPS.  DBGorilla calls your GitLab's API, and GitLab sends merge request
  events to DBGorilla.  If your GitLab sits behind a firewall, ask DBGorilla
  support which addresses to allow.  GitLab.com needs nothing extra.
- For connected reviews, a database connected to DBGorilla.  Projects that are
  not linked to one still get reviews, from the diff alone.

## The three tokens

DBGorilla uses separate tokens so each one has only the access it needs.  The bot
token and the read-only token must belong to a bot user, never a person, so
reviews are never posted under a teammate's name.

The bot user you use depends on where your GitLab runs:

| Your GitLab | Bot user | Bot and read-only tokens |
| :-- | :-- | :-- |
| GitLab.com | A group service account with the Developer role.  Available on every plan, including Free, and it does not use a paid seat. | Two tokens on the same service account |
| Self-managed | Group access tokens, on any tier.  Each token comes with its own bot user. | Two group access tokens |

| Token | What it does | Role | Scopes | Kept by DBGorilla |
| :-- | :-- | :-- | :-- | :-- |
| Bot token | Posts review comments and the commit status | Developer | `api` | Yes, encrypted |
| Read-only token | Lets the reviewer read code in the projects you turn on | Reporter or higher.  A service account's Developer role is fine. | `read_api` only. `read_repository` and `read_user` are also accepted. | Yes, encrypted |
| Maintainer token | Adds or removes a project's webhook | Maintainer on the project | `api` | No.  Used once, then discarded |

## 1. Create the bot and its two tokens

This step happens in GitLab.

**On GitLab.com**, go to your group, then **Settings › Service accounts**:

1. Select **Add service account**, and name it something your team will
   recognise in merge requests, such as `dbgorilla-review`.
2. Add the service account to the group with the **Developer** role, under
   **Manage › Members**.
3. Create two personal access tokens for the service account: the **bot token**
   with the `api` scope, and the **read-only token** with the `read_api` scope
   only.

**On self-managed GitLab**, go to your group, then **Settings › Access tokens**,
and select **Add new token** twice:

1. The bot token: a name such as `dbgorilla-review-bot`, the **Developer**
   role and the `api` scope.
2. The read-only token: the **Reporter** role and the `read_api` scope only.

Either way, set an expiration date on both tokens and replace them before they
expire (see [Managing the connection](#managing-the-connection)).  Copy each token
when GitLab shows it, because GitLab displays a token only once.

The group you create the tokens in is the group DBGorilla connects to.  To connect
only part of your GitLab, use a subgroup.

## 2. Connect the group

This step happens in DBGorilla.  Go to **Admin › Integrations**.  In the
**DBGorilla Review for GitLab** card, enter:

- **GitLab address**: `https://gitlab.com`, or your GitLab's HTTPS address with no
  path, such as `https://gitlab.example.com`.
- **Group**: the group's path (`acme` or `acme/platform`) or its numeric ID.
- The bot token and the read-only token.

Select **Connect GitLab**.  DBGorilla checks both tokens before saving anything.
If something is wrong, the card says what to fix.  See
[If something goes wrong](#if-something-goes-wrong).

## 3. Choose which projects are reviewed

Once connected, the card lists the group's projects.  For each project you want
reviewed:

1. Paste a Maintainer token for that project into the **Maintainer token**
   field.  A personal access token with the `api` scope from any Maintainer of
   the project works.
2. Select **Review this project**.

DBGorilla adds a webhook to the project for merge request and comment events,
then clears the token from the page.  The Maintainer token is never stored.  The
project then shows **Reviewing**.

## 4. Link the project to its database

This step needs a database connected to DBGorilla.  If you do not have one yet,
see [Connect a database](/docs/integrations/pull-request-reviews/#connect-a-database).

1. Open the component in DBGorilla, then go to its **Settings** tab.
2. Under **GitLab Projects**, choose the project from **Link a project**.

From then on, reviews of that project read the component's live database: table
sizes, query traffic, and test runs on a copy of the database.

## 5. Open a merge request

Within a few minutes of a merge request opening, and after each new push, the
bot posts its summary comment, its inline findings and the **DBGorilla Review**
commit status.  GitLab shows the status as an external pipeline.

GitLab keeps one commit status per branch.  If the same branch is opened as two
merge requests, for example into `main` and into a release branch, both are
reviewed, and they share the status from whichever review finished last.

### Block merges on a failing review

In the project, go to **Settings › Merge requests** and turn on **Pipelines must
succeed** under merge checks.  A merge request with a blocking database risk then
cannot be merged until the risk is fixed.  A review that could not run also fails
the status, so it blocks the merge too until a later review passes.

## Tell us how a review did

Reply to any bot comment, mention the bot, and say what was right or wrong.
Include 👍 or 👎 in your reply to rate it.  Emoji reactions on the comment itself
are not read.  A sentence like "this should be a concern, not a block" helps the
reviewer improve more than a thumb alone.

GitLab gives the bot a generated username: `@service_account_group_…` for a
service account, or `@group_…_bot_…` for a group access token.  Type the start of
it and pick the bot from GitLab's suggestions.

## Managing the connection

| To | Do this |
| :-- | :-- |
| Replace an expiring token | Create the new token in GitLab, then connect the same group again with both tokens.  DBGorilla replaces the stored tokens.  Reviews already posted stay recognised as the bot's, even when the new token belongs to a new bot user. |
| Stop reviewing a project | Paste a Maintainer token and select **Stop reviewing**.  DBGorilla removes the webhook too.  Without a token, DBGorilla stops reviewing and you remove the webhook yourself in GitLab under **Settings › Webhooks**. |
| Unlink a project from its database | Remove it under **GitLab Projects** on the component's **Settings** tab.  Reviews continue from the diff alone. |
| Disconnect the group | Select **Disconnect**.  DBGorilla deletes the stored tokens, the project list and the database links.  Project webhooks stay in GitLab until you remove them, and DBGorilla ignores their deliveries. |
| Connect another group | Use the empty form under your existing connections. |

Comments and statuses already posted stay on your merge requests in every case.

## If something goes wrong

| DBGorilla says | What to do |
| :-- | :-- |
| Use your GitLab's https:// address… | Enter the `https://` address.  Tokens are only sent over HTTPS. |
| Enter only your GitLab's address… | Remove any path, such as `/users/sign_in`, from the address. |
| DBGorilla cannot connect to that address. | The address points somewhere DBGorilla cannot reach, such as a private network.  Use the address GitLab is published on, or ask DBGorilla support about network access. |
| GitLab could not be reached.  Try again shortly. | Your GitLab did not answer in time.  Check it is up and reachable over HTTPS, then try again. |
| The bot token needs the api scope. | Create the bot token again with the `api` scope. |
| The read token must be read-only… | Create the read-only token again with `read_api` only. |
| …belongs to a person. | Use a group access token or a service account token instead of a personal token. |
| …needs at least the Developer (or Reporter) role in the group. | Create the token again with the role from [the token table](#the-three-tokens). |
| …was not accepted by GitLab. / …has expired. / …is revoked or inactive. | Create a new token and connect again. |
| That token cannot add webhooks to this project. | Use a token from someone with the Maintainer role on that project. |
| This GitLab group is already connected to another DBGorilla workspace. | A group belongs to one workspace.  Disconnect it there first. |
| This group has more projects than DBGorilla can list. | Connect a smaller subgroup instead. |

### No review on a merge request

Check that the project shows **Reviewing** in
DBGorilla, and that its webhook is enabled in GitLab under **Settings ›
Webhooks**.  GitLab switches a webhook off after repeated failed deliveries;
re-enable it there.  DBGorilla also checks reviewed projects regularly and
reviews any merge request whose event never arrived.

## Security

- The bot token and the read-only token are encrypted at rest.  The Maintainer
  token is used for one request and never stored.
- DBGorilla reads only the projects you turn on, using the read-only token.
- Webhook deliveries are verified before DBGorilla acts on them: with a signature
  on GitLab versions that sign webhooks, and with a per-project secret otherwise.
- DBGorilla posts only as the bot user, and refuses a token that belongs to a
  person.