GitLab CI integration
API testing in GitLab CI
A first-party Docker image and CLI for Total Shift Left. Run test packs in any GitLab CI job, gate merge requests on pass-rate thresholds, and publish JUnit reports natively in the GitLab UI.
What this integration gives you
The Shift-Left API GitLab CI plugin runs as a Docker image inside any GitLab Runner. It connects to your Shift-Left API deployment, triggers a test pack, polls until completion, applies a quality gate, and publishes JUnit XML and JSON artifacts. Use it to gate merge requests, run scheduled regression suites, or chain into broader release pipelines on GitLab.com or self-managed GitLab.
Native JUnit reporting
GitLab parses JUnit XML and renders test summaries on pipelines and merge requests automatically.
Self-managed friendly
Works with self-managed GitLab + self-hosted Shift-Left API in air-gapped environments. Mirror the image into your internal registry.
Protected variable support
Credentials stay masked in logs and only expose on protected branches via GitLab's built-in CI/CD variable scoping.
Matrix parallelism
Run multiple test packs concurrently with parallel:matrix or independent test-stage jobs.
.gitlab-ci.yml example
Drop this into your .gitlab-ci.yml. Stores credentials as protected, masked CI/CD variables, runs on every merge request and main-branch push, applies a 95% pass-rate gate, and publishes JUnit results natively.
stages:
- test
api-tests:
stage: test
image: totalshiftleft/shift-left-api-runner:latest
variables:
SHIFTLEFT_URL: $SHIFTLEFT_URL
SHIFTLEFT_EMAIL: $SHIFTLEFT_EMAIL
SHIFTLEFT_PASSWORD: $SHIFTLEFT_PASSWORD
SHIFTLEFT_TEST_PACK_ID: $SHIFTLEFT_TEST_PACK_ID
PASS_THRESHOLD: "95"
FAIL_ON_ERROR_TESTS: "true"
script:
- shift-left-runner run \
--server-url "$SHIFTLEFT_URL" \
--email "$SHIFTLEFT_EMAIL" \
--password "$SHIFTLEFT_PASSWORD" \
--test-pack-id "$SHIFTLEFT_TEST_PACK_ID" \
--pass-threshold "$PASS_THRESHOLD" \
--fail-on-error-tests "$FAIL_ON_ERROR_TESTS" \
--junit-output api-results.xml \
--json-output api-summary.json
artifacts:
when: always
paths:
- api-results.xml
- api-summary.json
reports:
junit: api-results.xml
expire_in: 30 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"CI/CD variables
Configure these as GitLab CI/CD variables at the project, group, or instance level. Use the Protected and Masked flags for any value containing credentials.
| Variable | Description |
|---|---|
| SHIFTLEFT_URL | Base URL of your Shift-Left API deployment. Store as a CI/CD variable; mark as masked. |
| SHIFTLEFT_EMAIL / SHIFTLEFT_PASSWORD | Authentication credentials. Store as masked, protected CI/CD variables. |
| SHIFTLEFT_TEST_PACK_ID | ID of the test pack to execute. Project- or group-level variable. |
| PASS_THRESHOLD | Minimum pass-rate percentage. 0 disables the gate; 95 is a common starting point. |
| FAIL_ON_ERROR_TESTS | Boolean. If true, ERROR test results fail the job regardless of pass-rate. |
Quality gates on merge requests
Combine the plugin's built-in gates with GitLab's merge request settings to block merges on API quality regressions:
- In GitLab: Settings → Merge Requests → Pipelines must succeed.
- Set
PASS_THRESHOLDon the pipeline (e.g.,"95"). - Set
FAIL_ON_ERROR_TESTSto"true"to fail on infrastructure-error tests independently of pass-rate. - Optional: require a manual approver from the QE / Architecture team for protected branches.
For data-flow specifics — including how the runner reaches a self-hosted Shift-Left API — see the security page and deployment page.
GitLab CI integration — FAQ
Does this work with self-managed GitLab and self-hosted Shift-Left API?
Yes. The Docker image runs on any GitLab Runner — shared or self-managed. For air-gapped environments, mirror the Docker image into your internal registry and reference it from your .gitlab-ci.yml. For self-hosted Shift-Left deployments, use a GitLab Runner inside the same network as the Shift-Left API.How do I gate merge requests on API test results?
The job exits non-zero when the pass-rate threshold or ERROR-test policy fails. Combine with GitLab's "Pipelines must succeed" merge request setting under Settings → Merge Requests to block merges on API test failures.How do I view the JUnit results in the GitLab UI?
The example uses artifacts.reports.junit to publish JUnit XML, which GitLab parses and displays as a Test summary on the pipeline and merge request pages. Failed tests are highlighted with traces and timings.Can I run multiple test packs in parallel?
Yes. Use a parallel:matrix block with different SHIFTLEFT_TEST_PACK_ID values, or define multiple jobs in the test stage. Each job is independent and runs on its own runner.How do credentials reach the runner safely?
Use protected, masked CI/CD variables defined at the project, group, or instance level. Protected variables are exposed only on protected branches and tags. Masked variables are scrubbed from job logs. Never inline credentials in .gitlab-ci.yml.What's the relationship between the Docker image and the public REST API?
The Docker image bundles a thin CLI that calls the same /api/v1 endpoints the public REST API exposes. If you need behavior the CLI doesn't support, you can call the REST API directly from any GitLab CI job using curl or a custom script.
More CI/CD integrations
Add API testing to your GitLab pipelines
Forever-free Citizen Developer or 15-day Enterprise trial. Drop the job into .gitlab-ci.yml and you're testing on the next merge request.