GitLab Merged Results Pipelines

GitLab's merged results pipelines run against the result of merging the source and target branches, rather than against the source branch alone. This catches integration issues that branch-only pipelines miss.

Unfortunately, GitLab does not expose an API for third-party CI platforms to participate in merged results pipelines directly. GitLab only supports one top-level pipeline per merge request and exposes no webhook or trigger that fires against the merged-result SHA, so the only way to run RWX against the merged result is to dispatch the RWX run from a job inside the GitLab pipeline.

By incorporating RWX runs into a merged results pipeline:

  • RWX tests the merged result, rather than the branch tip.
  • Run status is reported on the top-level pipeline for each merge request, rather than buried in a secondary pipeline.

This requires two changes: dispatching the RWX run from your GitLab CI configuration, and updating your RWX run definition to accept that dispatch.

Dispatch RWX from .gitlab-ci.yml

Add a job to your .gitlab-ci.yml that dispatches an RWX run and waits for it to finish, keeping the GitLab pipeline in an "in progress" state until the run completes:

kick-off-rwx:
  image: ubuntu:24.04
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  before_script: |
    if [ -z "$RWX_ACCESS_TOKEN" ]; then
      echo "RWX_ACCESS_TOKEN is not set"
      exit 1
    fi
    apt-get update && apt-get install -y --no-install-recommends curl ca-certificates jq
  script: |
    curl -fsSL https://github.com/rwx-cloud/rwx/releases/download/latest/rwx-linux-x86_64 > rwx
    chmod +x rwx

    title="CI: ${CI_MERGE_REQUEST_TITLE:-$CI_COMMIT_TITLE}"
    dispatch_result=$(./rwx dispatch merge-request-pipeline --ref $CI_COMMIT_SHA --title "$title" --wait --json) || exit_code=$?
    run_url=$(echo "$dispatch_result" | tail -1 | jq -r '.RunURL')
    echo "RWX run finished. See $run_url"
    exit 0

A few notes on this snippet:

  • The if: $CI_PIPELINE_SOURCE == "merge_request_event" rule scopes the job to merge request pipelines.
  • The before_script installs curl, ca-certificates, and jq. If you maintain your own base image, consider moving these dependencies upstream so the job can skip the install step.
  • RWX_ACCESS_TOKEN must be set as a pipeline variable. Create one from Access Tokens.
  • merge-request-pipeline is the dispatch key — it must match the key in the RWX run's dispatch trigger (covered below).
  • The "kickoff" job always exits successfully. RWX reports its own status check on the merge request, so the run's pass/fail surfaces there instead. Clicking through to RWX gives much richer context than the GitLab job logs would.

Configure a dispatch trigger in RWX

Configure your RWX run definition to use a dispatch trigger instead of the GitLab merge request trigger. The dispatch trigger only fires when the merged results pipeline calls it, so the run only ever tests the merged result.

on:
  dispatch:
    key: merge-request-pipeline
    status-checks: true
    init:
      commit-sha: ${{ event.git.sha }}
  • key must match the key passed to rwx dispatch in .gitlab-ci.yml (merge-request-pipeline in this example).
  • status-checks: true opts the dispatched run into reporting status back to the GitLab pipeline. Status checks are on by default for GitLab merge request triggers, but opt-in for dispatched runs.
  • commit-sha pulls the merged-result SHA out of the dispatch event so downstream tasks can check out the right commit.

Make sure your git/clone task uses that init parameter, so it clones the merged result rather than the branch tip:

tasks:
  - key: code
    call: git/clone 2.0.7
    with:
      repository: [email protected]:YOUR_ORG/YOUR_REPO.git
      ref: ${{ init.commit-sha }}
      ssh-key: ${{ gitlab['YOUR_ORG/YOUR_REPO'].ssh-key }}