> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qa.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# GitLab Merge Request Reviews and CI/CD

> Set up automated GitLab merge request reviews and API-driven test runs

Use GitLab with QA.tech in two ways:

1. **GitLab MR Reviews (AI exploratory testing)** via the GitLab integration in QA.tech.
2. **API-driven CI/CD test runs** via the QA.tech REST API.

This page covers both.

## What GitLab MR reviews do

When enabled, QA.tech can:

* detect merge request activity from your connected repository
* post an introduction or progress comment on merge requests
* run exploratory and end-to-end testing against your merge request
* publish a final results-based review comment back on the merge request

## What QA.tech Writes on GitLab MRs

QA.tech posts comments and review notes on merge requests when the integration is triggered.

| Operation                    | When                          | Description                                                                                                                  |
| :--------------------------- | :---------------------------- | :--------------------------------------------------------------------------------------------------------------------------- |
| **MR comment (in progress)** | When the agent starts testing | Comment with link to the QA.tech conversation and details (project, MR number, branch, event type). Lets you track progress. |
| **MR review note**           | After tests complete          | MR note with verdict (Approved, Changes Requested, or Comment), summary, test results table, and evaluation details.         |

<Note>
  QA.tech uses your connected GitLab OAuth integration to call GitLab APIs. That
  means MR comments and review updates are posted through your connected GitLab
  integration identity.
</Note>

<Note>
  Automatic MR review triggering requires native GitLab deployment and
  environment signals. If your flow does not publish those signals, use the
  manual or CI-assisted `@qa.tech` trigger path below.
</Note>

## Set up GitLab MR reviews

<Steps>
  <Step title="Connect GitLab in Organization Connections">
    Go to [Settings → Organization → Connections](https://app.qa.tech/current-project/settings/organization/connections) and connect GitLab.
  </Step>

  <Step title="Choose a repository in project integrations">
    Open [Settings → Integrations](https://app.qa.tech/current-project/settings/integrations), select **GitLab**, then choose the repository you want QA.tech to review.
  </Step>

  <Step title="Configure MR review behavior">
    In the GitLab integration settings, configure:

    * **Review Context** (optional instructions for reviews)
    * **Auto-run on Merge Requests**
    * **Include Draft Merge Requests**
    * **Post Comment on Opened MR** (post an introductory QA.tech comment when an MR is opened, including waiting/progress guidance)
    * **Environment Mapping** (map GitLab environments to QA.tech applications)
  </Step>

  <Step title="Save integration">
    Saving creates or refreshes the GitLab webhook connection for your selected repository so QA.tech can process merge request, note, deployment, and pipeline events.
  </Step>
</Steps>

## Triggering a merge request review

### Option A: Automatic trigger for native GitLab deployments

If **Auto-run on Merge Requests** is enabled, QA.tech can auto-trigger reviews when deployment data is ready from native GitLab deployments and environments.

High-level behavior:

1. MR is opened or updated.
2. QA.tech checks if the MR commit is the latest and deployment(s) for that commit are ready.
3. If deployments are ready, QA.tech starts the review flow automatically.
4. If deployments are not ready, QA.tech can post a waiting comment (based on your setting) and wait for deployment readiness or a manual `@qa.tech` trigger.

### Option B: Manual trigger using a GitLab comment

Comment on the merge request and mention `@qa.tech`.

Include the preview deployment URL in the same comment. QA.tech parses URLs from MR comments and uses that URL as deployment context for the review run. In practice, this is required for reliable review targeting.

Example:

```text theme={null}
@qa.tech https://preview.example.com
```

### Option C: CI-assisted manual trigger

If your deployment process is custom, have CI post an MR comment that mentions `@qa.tech` and includes the preview URL. This gives you a consistent trigger pattern without requiring developers to comment manually each time.

## GitLab MR review troubleshooting

**No review starts after MR open**

* Verify the repository is selected in GitLab integration settings.
* Check whether **Auto-run on Merge Requests** is enabled.
* Confirm deployment status is successful for the latest MR commit, or manually trigger with `@qa.tech`.
* If you are not using native GitLab deployment/environment signals, use the manual `@qa.tech` trigger with a preview URL.

**Draft MRs are skipped**

* Enable **Include Draft Merge Requests** if you want draft MRs reviewed.

**Manual trigger did nothing**

* Make sure the comment is on the merge request and includes `@qa.tech` (case-insensitive).
* If you expect preview-aware testing, include the preview URL in that same comment.

## API-driven GitLab CI/CD (manual test plan runs)

You can trigger QA.tech test plans from GitLab CI/CD using the REST API.

### Prerequisites

You need two values before configuring your pipeline:

* **API Token** - Your QA.tech API token
* **Test Plan Short ID** - From your test plan (e.g. `pln_abc123`)

### Configure CI/CD variables

Store your API token securely:

1. Go to **Settings → CI/CD → Variables**
2. Add variable:
   * **Key**: `QA_TECH_API_TOKEN`
   * **Value**: Your API token
   * **Protected**: ✅
   * **Masked**: ✅

## API implementation patterns

### Basic setup

```yaml theme={null}
trigger_qatech:
  stage: test
  variables:
    API_TOKEN: $QA_TECH_API_TOKEN
    QATECH_REQUEST_BODY: '{"testPlanShortId": "pln_abc123"}'
  script: >
    curl --request POST
    --url "https://api.qa.tech/v1/run"
    --header "Authorization: Bearer $API_TOKEN"
    --header "Content-Type: application/json"
    --data "${QATECH_REQUEST_BODY}"
```

Replace `pln_abc123` with your test plan short ID (from your test plan page).

### Run test plans on merge requests

```yaml theme={null}
test_mr:
  stage: test
  only:
    - merge_requests
  variables:
    API_TOKEN: $QA_TECH_API_TOKEN
    QATECH_REQUEST_BODY: '{"testPlanShortId": "pln-smoke-tests_abc123"}'
  script: >
    curl --request POST
    --url "https://api.qa.tech/v1/run"
    --header "Authorization: Bearer $API_TOKEN"
    --header "Content-Type: application/json"
    --data "${QATECH_REQUEST_BODY}"
```

### Test preview deployments via API

Pass dynamic URLs between jobs using dotenv artifacts:

```yaml theme={null}
stages:
  - deploy
  - test

deploy_preview:
  stage: deploy
  script:
    - echo "PREVIEW_URL=https://preview-${CI_MERGE_REQUEST_IID}.yourdomain.com" >> deploy.env
  artifacts:
    reports:
      dotenv: deploy.env

test_preview:
  stage: test
  dependencies:
    - deploy_preview
  variables:
    API_TOKEN: $QA_TECH_API_TOKEN
  before_script:
    - |
      echo '{"testPlanShortId":"pln-regression-suite_abc123","applications":[{"applicationShortId":"app-frontend_abc123","environment":{"url":"'$PREVIEW_URL'","name":"MR-'$CI_MERGE_REQUEST_IID'"}}]}' > /tmp/request.json
  script: >
    curl --request POST
    --url "https://api.qa.tech/v1/run"
    --header "Authorization: Bearer $API_TOKEN"
    --header "Content-Type: application/json"
    --data @/tmp/request.json
```

<Note>
  You can also override device presets in the same request by adding `devicePresetShortId` to each application object in the `applications` array. For example, to test the preview deployment on a mobile device preset: `"applications":[{"applicationShortId":"app_frontend","environment":{"url":"'$PREVIEW_URL'"},"devicePresetShortId":"preset_abc123"}]`. See [Start Run API](/api-reference/start-run) for details.
</Note>

### Scheduled testing

```yaml theme={null}
nightly_tests:
  stage: test
  only:
    - schedules
  variables:
    API_TOKEN: $QA_TECH_API_TOKEN
    QATECH_REQUEST_BODY: '{"testPlanShortId": "pln-full-regression_abc123"}'
  script: >
    curl --request POST
    --url "https://api.qa.tech/v1/run"
    --header "Authorization: Bearer $API_TOKEN"
    --header "Content-Type: application/json"
    --data "${QATECH_REQUEST_BODY}"
```

Set up schedules at **CI/CD → Schedules → New schedule**.

<Accordion title="GitLab Schedules vs QA.tech Schedules">
  **Use GitLab schedules when:**

  * Tests should run as part of your CI/CD pipeline
  * You need GitLab context (branch, commit SHA)
  * You want to gate deployments on scheduled test results

  **Use QA.tech schedules when:**

  * Tests should run independently of CI/CD infrastructure
  * You prefer managing schedules in QA.tech UI
  * You want to avoid consuming GitLab runner minutes

  See [Test Plans](/core-concepts/test-plans#scheduled-execution) for QA.tech scheduling.
</Accordion>

## API tips

For shared API concepts and platform-agnostic workflows, see [CI/CD Integration](/configuration/ci-cd-integration) and [Start Run API](/api-reference/start-run). The examples below focus on GitLab-specific usage.

### Finding your test plan short ID

1. Go to [Test Plans](https://app.qa.tech/current-project/test-plans)
2. Click on a test plan
3. Check the URL: `https://app.qa.tech/.../test-plans/abc123`
4. Use the test plan short ID in API payloads (for example: `pln_abc123`)

### Building JSON payloads

For complex payloads with dynamic values, write to a file first:

```yaml theme={null}
before_script:
  - |
    echo '{"key": "'$VARIABLE'"}' > /tmp/request.json
script:
  - curl ... --data @/tmp/request.json
```

### Custom Slack notifications

Override notification channels per-run. See [Notifications](/core-concepts/notifications#per-run-api-overrides-slack-only) for details.

### Blocking mode

Wait for test completion before proceeding with deployments:

```yaml theme={null}
trigger_qatech:
  stage: test
  variables:
    API_TOKEN: $QA_TECH_API_TOKEN
  script:
    # Start run and capture shortId
    - |
      RESPONSE=$(curl -s -X POST \
        "https://api.qa.tech/v1/run" \
        -H "Authorization: Bearer $API_TOKEN" \
        -H "Content-Type: application/json" \
        -d "{\"testPlanShortId\": \"pln_abc123\"}")
      SHORT_ID=$(echo "$RESPONSE" | jq -r '.run.shortId')

    # Poll until completion (see Run Status API for details)
    - |
      while true; do
        RESPONSE=$(curl -s \
          "https://api.qa.tech/v1/run/$SHORT_ID" \
          -H "Authorization: Bearer $API_TOKEN")
        STATUS=$(echo "$RESPONSE" | jq -r '.status')
        if [[ "$STATUS" == "COMPLETED" || "$STATUS" == "ERROR" || "$STATUS" == "CANCELLED" ]]; then
          RESULT=$(echo "$RESPONSE" | jq -r '.result')
          [[ "$RESULT" == "PASSED" ]] && exit 0 || exit 1
        fi
        sleep 30
      done
```

See [Run Status API](/api-reference/run-status) for polling logic details and error handling.

## Related Documentation

* **[CI/CD Integration](/configuration/ci-cd-integration)** - Overview of integration modes
* **[GitHub App for PR Reviews](/configuration/github-app)** - GitHub version of exploratory PR reviews
* **[API Reference](/api-reference/start-run)** - Complete API documentation
* **[Test Plans](/core-concepts/test-plans)** - Create and organize test plans
* **[Preview Environments](/core-concepts/applications-and-environments#preview-environments)** - Dynamic preview testing
