GitLab CI¶
Minimal pipeline¶
variables:
DD_PRODUCT_TYPE_NAME: "GitLab Projects"
DD_PRODUCT_NAME: "$CI_PROJECT_PATH"
DD_ENGAGEMENT_NAME: "$CI_COMMIT_REF_SLUG"
DD_AUTO_CREATE_CONTEXT: "true"
# DD_URL and DD_API_KEY are set as protected/masked GitLab variables.
stages:
- test
- upload
trivy:
stage: test
image: aquasec/trivy:latest
script:
- trivy fs --format json -o trivy.json .
artifacts:
paths: [trivy.json]
expire_in: 1 day
upload_trivy:
stage: upload
image: ghcr.io/osamamahmood/dd-cli:2
needs: [trivy]
variables:
DD_TEST_NAME: "Trivy"
DD_TEST_TYPE_NAME: "Trivy Scan"
DD_FILE_NAME: "trivy.json"
script:
- dd-reimport-findings
Multi-scanner pipeline¶
variables:
DD_PRODUCT_TYPE_NAME: "GitLab Projects"
DD_PRODUCT_NAME: "$CI_PROJECT_PATH"
DD_ENGAGEMENT_NAME: "$CI_COMMIT_REF_SLUG"
DD_BUILD_ID: "$CI_PIPELINE_ID"
DD_COMMIT_HASH: "$CI_COMMIT_SHA"
DD_BRANCH_TAG: "$CI_COMMIT_REF_NAME"
DD_AUTO_CREATE_CONTEXT: "true"
.dd_upload: &dd_upload
stage: upload
image: ghcr.io/osamamahmood/dd-cli:2
script: [dd-reimport-findings]
stages:
- scan
- upload
trivy:
stage: scan
image: aquasec/trivy:latest
script: [trivy fs --format json -o trivy.json .]
artifacts:
paths: [trivy.json]
expire_in: 1 day
bandit:
stage: scan
image: python:3.12-slim
before_script: [pip install bandit]
script: [bandit -r src/ -f json -o bandit.json || true]
artifacts:
paths: [bandit.json]
expire_in: 1 day
cloc:
stage: scan
image: node:20-alpine
before_script: [npm install -g cloc]
script: [cloc src --json --out cloc.json]
artifacts:
paths: [cloc.json]
expire_in: 1 day
upload_trivy:
<<: *dd_upload
needs: [trivy]
variables:
DD_TEST_NAME: "Trivy"
DD_TEST_TYPE_NAME: "Trivy Scan"
DD_FILE_NAME: "trivy.json"
upload_bandit:
<<: *dd_upload
needs: [bandit]
variables:
DD_TEST_NAME: "Bandit"
DD_TEST_TYPE_NAME: "Bandit Scan"
DD_FILE_NAME: "bandit.json"
upload_cloc:
<<: *dd_upload
needs: [cloc]
variables:
DD_FILE_NAME: "cloc.json"
script: [dd-import-languages] # different shim
Notes¶
- Image pinning. Pin to a major version (
:2) so dependabot bumps catch patches and minors but not breaking changes. - Secrets. Set
DD_URLandDD_API_KEYat the project or group level as protected, masked CI/CD variables. - Per-stage env. GitLab merges
.dd_uploadtemplate variables with per-jobvariables:, so the per-job block only needs the scanner-specific bits. - GitLab Runner registries. If your runner caches Docker images, the
dd-cliimage pull will be near-instant after the first run.
Branching on typed exit codes¶
dd-reimport-findings flattens errors to exit 1 (legacy contract). For typed exit codes, use the new command:
upload_trivy:
stage: upload
image: ghcr.io/osamamahmood/dd-cli:2
needs: [trivy]
script:
- |
set +e
dd import findings \
--file trivy.json \
--scanner "Trivy Scan" \
--product-type "$DD_PRODUCT_TYPE_NAME" \
--product "$DD_PRODUCT_NAME" \
--auto-create --yes
rc=$?
set -e
case $rc in
0) echo "ok";;
3) echo "auth failed — rotate DD_API_KEY"; exit 1;;
8) echo "network blip"; exit $rc;;
*) echo "upload failed: $rc"; exit $rc;;
esac
See migration for the full code map.