# CI and builds

> Connect GitHub Actions, GitLab CI, CircleCI, Jenkins or Buildkite so reviews tie failing jobs to the lines that caused them, and PR chat answers why CI failed.

When a check fails on a pull request's head commit, MergeHarbor reads the end of the failed job's log and points the review at the changed lines it names. In PR chat and chat apps, ask "Why did CI fail?" to get the same answer.

## What it does in reviews

- **Finds the failed checks.** When a review runs, MergeHarbor asks the code host for the failed checks and commit statuses of the pull request's head commit. A failed check is read only when the CI that reported it is connected and allowed for the repository.
- **Reads the end of the log.** For each failed job, MergeHarbor reads the last 64 KB of its log, keeps the error lines (at most 60) and the file and line references in them, and adds any annotations the job left. Text that looks like a secret is redacted before it is cached or sent to a model.
- **Points at the cause.** Frames in files the pull request changes come first, so the review can tie a failing test or build step to the change that broke it. No extra model call is made.
- **Reads each job once.** A job's excerpt is cached for up to 6 hours. A re-run is a new job and is read again.

Nothing is listed or polled in the background: MergeHarbor reads CI only when a review runs or someone asks about CI in PR chat.

## "Why did CI fail?" in PR chat

With **Answer "Why did CI fail?" in PR chat and chat apps** on (the default for CI connections), questions about failed builds, tests, checks or pipelines in the pull request conversation, [Slack](https://mergeharbor.com/docs/slack), [Microsoft Teams](https://mergeharbor.com/docs/microsoft-teams) or [Google Chat](https://mergeharbor.com/docs/google-chat) read the failed jobs of the head commit and answer with the failing step and the lines behind it. Other questions never read CI. Turn the setting off in the connection's **Settings** to keep CI logs out of chat answers; reviews still use them.

## Per-repository settings

Open **Settings** on a CI connection to limit it to some repositories. Reviews and chat answers for other repositories never read it.

## Limits

- At most 3 failed jobs are read per review or chat question (`CI_MAX_JOBS` on self-hosted installations).
- At most the last 64 KB of each job's log is read (`CI_LOG_TAIL_BYTES`), and at most 60 error lines of it are kept.
- If a CI service is slow or refuses a request, the review continues without it and the connection shows the error in the console.

## What is read and what is never read

- **Read:** the names, links and conclusions of failed checks on the head commit, their annotations, and the end of each failed job's log.
- **Never read:** passing jobs, artifacts, caches, test reports, environment variables, secrets, pipeline configuration, and any job on a commit other than the pull request's head. MergeHarbor never re-runs, cancels or changes a build.

Excerpts are cached for up to 6 hours and never written to logs. Tokens are encrypted at rest and never shown again.

## GitHub Actions

GitHub Actions uses your GitHub App installation, so there is nothing to paste.

1. Make sure the MergeHarbor GitHub App has the **Actions: Read** and **Commit statuses: Read** permissions. Installations made before these permissions were added must approve them: an owner of each GitHub organization or account opens **Settings → GitHub Apps → MergeHarbor → Review request** and accepts. See [Code host permissions](https://mergeharbor.com/docs/permissions).
2. In the console, open **Integrations** and choose **Turn on** on **GitHub Actions** (under **CI & builds**). You need the `settings.manage` permission.
3. Choose **Test connection**. It lists the CI runs of one of your repositories; if GitHub refuses, the permission has not been approved yet.

## GitLab CI

GitLab CI uses your existing GitLab connection, on GitLab.com or GitLab Self-Managed, so there is nothing to paste.

1. In the console, open **Integrations** and choose **Turn on** on **GitLab CI** (under **CI & builds**).
2. Choose **Test connection**. It lists the pipelines of one of your projects. The connection's `api` scope already allows reading pipelines and job logs; an access token needs at least `read_api`.

## CircleCI

1. In CircleCI, open **User settings → Personal API tokens** and create a token. It can read the projects you can see, so consider a user that only follows the projects MergeHarbor reviews.
2. In the console, choose **Connect** on **CircleCI**, paste the token and choose **Test connection**.

MergeHarbor reads the output of a failed job's failed steps. It finds the job from the check or status CircleCI reports on the head commit.

## Jenkins

1. In Jenkins, open your user (or a dedicated user with **Overall/Read** and **Job/Read** only) → **Security → API Token → Add new token**.
2. In the console, choose **Connect** on **Jenkins** and enter your Jenkins URL (for example `https://ci.example.com`), the user name and the API token. Choose **Test connection**.

MergeHarbor reads the end of a failed build's console log. It only reads builds whose commit status on the head commit links to the Jenkins URL you entered.

## Buildkite

1. In Buildkite, open **Personal settings → API access tokens** and create a token with only the `read_builds` and `read_build_logs` scopes, for the organizations MergeHarbor should read.
2. In the console, choose **Connect** on **Buildkite**, paste the token and choose **Test connection**.

MergeHarbor reads the logs of a failed build's failed jobs, found from the check or status Buildkite reports on the head commit.

## Disconnect

Open the connection in **Integrations** and choose **Disconnect**. MergeHarbor deletes its token and cached excerpts. For CircleCI, Jenkins and Buildkite, then delete the token in the service. GitHub Actions and GitLab CI have no token of their own; turning them off stops the reads.

## Self-hosted installations

GitHub Actions and GitLab CI appear when the installation has a GitHub App or GitLab connection; register the GitHub App with the **Actions** and **Commit statuses** read permissions (`docs/OAUTH_APPS.md`, "GitHub App"). CircleCI, Jenkins and Buildkite need no setup. `CI_MAX_JOBS` (default `3`) and `CI_LOG_TAIL_BYTES` (default `65536`) bound what each review reads.
