GitLab CI/CD¶
This page describes how to integrate MethodAtlas into a GitLab CI/CD pipeline. The techniques can be used individually or combined:
- Merge request annotations — findings posted as MR notes via
::notice/::warningcommands - SARIF upload to Security Dashboard — findings appear in the GitLab MR security widget
- AI result caching — skips re-classification of unchanged test classes
- Security test count gate — pipeline fails when security test coverage drops
Prerequisites¶
| Requirement | Details |
|---|---|
| Java runtime | Java 21 or later; the examples use the eclipse-temurin:21-jdk Docker image |
| MethodAtlas | Downloaded at job start from the GitHub release; the binary is cached between runs using the cache directive |
| AI provider API key | Stored as a GitLab CI/CD variable (masked); not required for static inventory mode |
| GitLab tier | SARIF upload to the Security Dashboard requires GitLab Ultimate; annotation output has no tier requirement |
Project configuration¶
Store your AI provider API key as a masked, protected CI/CD variable. In the GitLab UI navigate to Settings → CI/CD → Variables and add:
| Variable | Value | Flags |
|---|---|---|
OPENAI_API_KEY |
Your OpenAI API key | Masked, Protected |
Use a different variable name and the -ai-provider flag if you are using
a provider other than OpenAI. See AI Providers.
Minimal pipeline: static inventory¶
The following job requires no AI provider and produces a CSV inventory of all test methods with their structural metadata:
methodatlas-inventory:
image: eclipse-temurin:21-jdk
stage: test
cache:
key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull-push
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- java -jar methodatlas.jar src/test/java > inventory.csv
artifacts:
paths:
- inventory.csv
expire_in: 30 days
AI-enriched scan with SARIF upload¶
GitLab CI supports SARIF reports as a first-class artefact type through the
artifacts.reports.sast key. Reports uploaded this way are parsed by GitLab
and displayed in the merge request security widget and the project Security
Dashboard (GitLab Ultimate required for the dashboard).
methodatlas-scan:
image: eclipse-temurin:21-jdk
stage: test
cache:
- key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull-push
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- |
java -jar methodatlas.jar \
-ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY \
-sarif -security-only \
-content-hash \
src/test/java \
> methodatlas.sarif
artifacts:
reports:
sast: methodatlas.sarif
paths:
- methodatlas.sarif
expire_in: 90 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
GitLab Ultimate
The artifacts.reports.sast integration and the Security Dashboard
require GitLab Ultimate. On lower tiers the SARIF file is still produced
and available as a downloadable job artefact; it can be reviewed manually
or imported into an external code scanning tool.
Caching AI results across runs¶
Use GitLab's cache directive to persist the MethodAtlas result file across
pipeline runs. The cache key is set per branch so that each branch maintains
its own classification state:
methodatlas-scan:
image: eclipse-temurin:21-jdk
stage: test
cache:
- key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull-push
- key: "methodatlas-ai-$CI_COMMIT_REF_SLUG"
paths:
- .methodatlas-cache.json
policy: pull-push
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- |
CACHE_ARG=""
if [ -f .methodatlas-cache.json ]; then
CACHE_ARG="-ai-cache .methodatlas-cache.json"
fi
# Single combined pass: classify, emit SARIF, and refresh the unified cache.
# Only changed classes call the AI provider; unchanged classes are served
# from the cache (classification and, with -detect-secrets, credentials).
java -jar methodatlas.jar \
-ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY \
-sarif -security-only \
-content-hash \
$CACHE_ARG \
-ai-cache-out .methodatlas-cache.json \
src/test/java \
> methodatlas.sarif
artifacts:
reports:
sast: methodatlas.sarif
paths:
- methodatlas.sarif
expire_in: 90 days
On the first run for a branch (cache miss) every class is classified via the
AI provider. On subsequent runs only classes whose content_hash has changed
incur an API call.
Security test count gate¶
Fail the pipeline when the number of security-relevant test methods drops compared to the baseline on the default branch:
stages:
- build
- test
- gate
save-baseline:
image: eclipse-temurin:21-jdk
stage: test
cache:
key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull-push
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- |
java -jar methodatlas.jar \
-ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY \
-security-only -content-hash \
src/test/java > baseline.csv
artifacts:
name: methodatlas-baseline
paths:
- baseline.csv
expire_in: 90 days
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
security-gate:
image: eclipse-temurin:21-jdk
stage: gate
needs:
- job: save-baseline
artifacts: true
optional: true
cache:
key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- |
java -jar methodatlas.jar \
-ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY \
-security-only \
src/test/java > current.csv
if [ ! -f baseline.csv ]; then
echo "No baseline available — skipping count gate."
exit 0
fi
baseline=$(tail -n +2 baseline.csv | wc -l)
current=$(tail -n +2 current.csv | wc -l)
echo "Baseline security tests: $baseline"
echo "Current security tests: $current"
if [ "$current" -lt "$baseline" ]; then
echo "ERROR: Security test count dropped from $baseline to $current"
exit 1
fi
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
Full pipeline¶
The following .gitlab-ci.yml combines binary caching, AI result caching,
SARIF upload, and the count gate. Adjust stage names and needs references
to match your project's existing pipeline structure.
stages:
- build
- test
variables:
METHODATLAS_JAR: methodatlas.jar
METHODATLAS_VERSION: latest # pin to a version tag for reproducibility, e.g. 1.2.0
.methodatlas-binary-cache: &methodatlas-binary-cache
key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- $METHODATLAS_JAR
policy: pull-push
.download-methodatlas: &download-methodatlas
- |
if [ ! -f "$METHODATLAS_JAR" ]; then
curl -fsSL -o "$METHODATLAS_JAR" \
"https://github.com/Accenture/MethodAtlas/releases/${METHODATLAS_VERSION}/download/methodatlas.jar"
fi
methodatlas-scan:
image: eclipse-temurin:21-jdk
stage: test
cache:
- <<: *methodatlas-binary-cache
- key: "methodatlas-ai-$CI_COMMIT_REF_SLUG"
paths:
- .methodatlas-cache.json
policy: pull-push
script:
- *download-methodatlas
- |
CACHE_ARG=""
if [ -f .methodatlas-cache.json ]; then
CACHE_ARG="-ai-cache .methodatlas-cache.json"
fi
# Single combined pass: classify, emit SARIF, and refresh the unified cache.
java -jar "$METHODATLAS_JAR" \
-ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY \
-sarif -security-only \
-content-hash \
$CACHE_ARG \
-ai-cache-out .methodatlas-cache.json \
src/test/java \
> methodatlas.sarif
artifacts:
reports:
sast: methodatlas.sarif
paths:
- methodatlas.sarif
expire_in: 90 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Scanning for hard-coded credentials¶
-detect-secrets adds a deterministic
credential scan alongside the test inventory. The deterministic layer uses no AI
and makes no network calls, so it needs no API-key variable and is safe to run on
every pipeline. Emit the findings as SARIF — GitLab ingests them through the same
artifacts.reports.sast channel as the test scan (SAST reports from multiple jobs
are merged), so credential findings appear in the merge-request security widget and
the Security Dashboard:
methodatlas-credentials:
image: eclipse-temurin:21-jdk
stage: test
cache:
- key: "methodatlas-binary-$CI_COMMIT_REF_SLUG"
paths:
- methodatlas.jar
policy: pull
script:
- |
if [ ! -f methodatlas.jar ]; then
curl -fsSL -o methodatlas.jar \
https://github.com/Accenture/MethodAtlas/releases/latest/download/methodatlas.jar
fi
- |
java -jar methodatlas.jar \
-detect-secrets \
-secrets-out methodatlas-credentials.csv \
-sarif \
src/test/java \
> methodatlas-credentials.sarif
artifacts:
reports:
sast: methodatlas-credentials.sarif
paths:
- methodatlas-credentials.sarif
- methodatlas-credentials.csv
expire_in: 90 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Secret values are masked by default in both the SARIF and the CSV. A
deterministic-only run emits every finding at warning so nothing drops below
review threshold. (The artifacts.reports.sast dashboard integration requires
GitLab Ultimate, exactly as for the test-classification SARIF above; on lower tiers
both files remain downloadable job artefacts.)
Optional AI triage
Add -ai -ai-provider openai -ai-api-key-env OPENAI_API_KEY (with the masked
OPENAI_API_KEY CI/CD variable) to have the model score each candidate's
credibility and attribute it to the endpoint it authenticates against. This
transmits the test source to the provider, so for sensitive code prefer a local
Ollama model — see the
AI trust boundary.
-secrets-include <glob> replaces the default test-class set.
Using a YAML configuration file¶
For teams that prefer to keep MethodAtlas settings in version control rather
than in pipeline YAML, create a methodatlas.yml at the project root:
Reference it from the pipeline with the -config flag:
The API key must still be supplied via an environment variable at runtime; do not store secrets in the configuration file committed to version control.