GitLab CI/CD: Architecting, Deploying, and Optimizing Pipelines
Continuous Integration with GitLab
Pipeline Configure Coverage and Archive Reports
In this guide, you’ll learn how to set up a parallel code coverage job alongside unit tests in GitLab CI/CD, archive reports, and surface coverage metrics in the UI.
Base Unit Testing Job
This unit_testing job runs in the test stage, installs dependencies, executes tests, and collects JUnit reports:
stages:
- test
variables:
MONGO_URI: 'mongodb+srv://superCluster.d83jj.mongodb.net/superData'
MONGO_USERNAME: superuser
MONGO_PASSWORD: $M_DB_PASSWORD
unit_testing:
stage: test
image: node:17-alpine3.14
before_script:
- npm install
script:
- npm test
artifacts:
when: always
expire_in: 3 days
name: Moca-Test-Result
paths:
- test-results.xml
reports:
junit: test-results.xml
Adding a Parallel Code Coverage Job
Create a code_coverage job that reuses the Node.js image and installs dependencies. The npm run coverage command (powered by NYC) generates a Cobertura XML report.
code_coverage:
stage: test
image: node:17-alpine3.14
before_script:
- npm install
script:
- npm run coverage
artifacts:
name: Code-Coverage-Result
when: always
expire_in: 3 days
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
coverage: '/All files[^|]*\|[^|]*\s+([0-9.]+)%/'
Supported Artifact Report Types
GitLab CI/CD supports multiple report formats under artifacts:reports. Use the table below to choose the appropriate type:
| Report Type | Description | Example |
|---|---|---|
| junit | JUnit XML test reports | reports:\n junit: test-results.xml |
| coverage_report | Cobertura coverage results | reports:\n coverage_report:\n coverage_format: cobertura\n path: coverage/cobertura-coverage.xml |
| codequality | Static code analysis (Code Quality) | reports:\n codequality: gl-code-quality-report.json |
| dependency_scanning | Dependency vulnerability report | reports:\n dependency_scanning: gl-dependency-scanning-report.json |

Coverage Report Configuration
To enable GitLab’s built-in coverage display, specify the Cobertura format and the XML path in artifacts:reports:
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
Extracting Coverage Percentage
GitLab can parse test logs and extract a coverage percentage using a regular expression. For NYC’s “All files” summary line, use:
coverage: '/All files[^|]*\|[^|]*\s+([0-9.]+)%/'
Note
Make sure your coverage tool prints a summary line matching this pattern. Adjust the regex if your output differs.

Full CI Configuration with a Dependent Sample Job
Combine both jobs and add a sample-job that depends on code_coverage. This ensures downstream work only runs if coverage passes (or you enable allow_failure).
stages:
- test
variables:
MONGO_URI: 'mongodb+srv://superCluster.d83jj.mongodb.net/superData'
MONGO_USERNAME: superuser
MONGO_PASSWORD: $M_DB_PASSWORD
unit_testing:
stage: test
image: node:17-alpine3.14
before_script:
- npm install
script:
- npm test
artifacts:
when: always
expire_in: 3 days
name: Moca-Test-Result
paths:
- test-results.xml
reports:
junit: test-results.xml
code_coverage:
stage: test
image: node:17-alpine3.14
before_script:
- npm install
script:
- npm run coverage
artifacts:
name: Code-Coverage-Result
when: always
expire_in: 3 days
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
coverage: '/All files[^|]*\|[^|]*\s+([0-9.]+)%/'
sample-job:
stage: test
needs:
- code_coverage
image: node:17-alpine3.14
script:
- echo "Running sample job"
Once you push this .gitlab-ci.yml, the GitLab pipeline graph clearly shows unit_testing, code_coverage, and sample-job in parallel:

Pipeline Execution and Coverage Failure
If the coverage threshold defined in your package.json isn’t met, the code_coverage job fails and downstream jobs are skipped by default.
Warning
A failed coverage check will block any jobs that depend on it. To continue the pipeline regardless of coverage, you can set allow_failure: true on the coverage job.

Example logs from NYC:
> nyc --reporter cobertura --reporter lcov --reporter text --reporter json-summary mocha app-test.js --timeout 10000 --exit
...
ERROR: Coverage for lines (88.88%) does not meet global threshold (90%)
| File | % Branch | % Funcs | % Lines | Uncovered Line #s |
|------------|----------|---------|---------|-------------------|
| All files | 88.88 | 50 | 87.50 | 88.88 |
Your package.json might include:
{
"scripts": {
"coverage": "nyc --reporter cobertura --reporter lcov --reporter text --reporter json-summary mocha app-test.js"
},
"nyc": {
"check-coverage": true,
"lines": 90
}
}
Coverage Percentage in the GitLab UI
With the coverage regex in place, GitLab extracts the percentage (e.g., 88.88%) and displays it in the pipeline view:

In this scenario, coverage is below the 90% threshold, causing code_coverage to fail and skipping sample-job:

Next, we’ll look at strategies to allow selective failures and continue pipeline execution even when coverage checks fail.
Watch Video
Watch video content