Adds a dependency-resolution-service command to the dependency-scanning analyzer to support automatic Maven dependency resolution in CI pipelines (part of gitlab-org/gitlab#588765).
The problem: Maven projects have no lockfile mechanism. Accurate dependency scanning requires a maven.graph.json file, which today users must generate themselves via a custom CI job. This creates friction and makes it impossible to enforce scanning policies at scale.
The solution: A new dependency-resolution-service subcommand that runs as a CI service container alongside the user's Maven build job. It:
.gitlab_ds/ready_${CI_JOB_ID})pom.xml files) using the existing finder infrastructure.gitlab_ds/dependency_resolution.sh that runs mvn dependency:tree for each projectmaven.graph.json files that the scanner can then consumeExample .gitlab-ci.yml usage:
dependency-resolution::maven:
image: maven:3.9-eclipse-temurin-21
stage: .pre
services:
- name: $DS_ANALYZER_IMAGE
alias: ds-analyzer
command: ["/analyzer", "dependency-resolution-service", "--project-types", "maven"]
script:
- mkdir -p .gitlab_ds && chmod 777 .gitlab_ds
- touch .gitlab_ds/env && chmod 666 .gitlab_ds/env
- for var in $DS_MAVEN_RESOLUTION_EXPORTED_VARS; do echo "${var}=${!var}" >> .gitlab_ds/env; done
- touch .gitlab_ds/ready_${CI_JOB_ID} && chmod 666 .gitlab_ds/ready_${CI_JOB_ID}
# Wait for dependency_resolution.sh to be written by the service container
- |
TIMEOUT=60
ELAPSED=0
while [ ! -f .gitlab_ds/dependency_resolution.sh ] && [ $ELAPSED -lt $TIMEOUT ]; do
sleep 1
ELAPSED=$((ELAPSED + 1))
done
if [ ! -f .gitlab_ds/dependency_resolution.sh ]; then
echo "Timeout waiting for resolve.sh after $TIMEOUT seconds"
fi
# Display service container logs for debugging
- cat .gitlab_ds/service.log || echo "ERROR - no service logs found"
# Execute the generated script if it exists
- if [ -f .gitlab_ds/dependency_resolution.sh ]; then sh -x .gitlab_ds/dependency_resolution.sh; else echo "ERROR - dependency resolution script not found"; exit 1; fi
artifacts:
paths:
- '**/maven.graph.json'
rules:
- if: '"$[[ inputs.disabled_resolution_jobs ]]" =~ /\bmaven\b/ || $DS_DISABLED_RESOLUTION_JOBS =~ /\bmaven\b/'
when: never
- exists:
- '**/pom.xml'
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
N/A — no UI changes.
| Before | After |
|---|---|
This part is under construction as we converge on a working template and an integration test suite to automate basic checks. However, this is an example of what is working currently as an example: https://gitlab.com/gitlab-org/secure/tests/ifrenkel/dependency-resolution/test-1
Shouldn't we test for
MY_ENV_VAR="hello"
So what if we have quotes?
Question: How are the env files created?
Question: Does that mean that any logs before this point will be lost forever?
Question: What happens if you get an error here? Shouldn't we print a warning once?
praise: Awesome
Question: So if the service health server doesn't start up for any reason we just continue? Isn't this a problem?
Suggestion (non-blocking):
sequenceDiagram
participant Job as Maven Build Job
participant Service as DS Analyzer Service
participant FS as Filesystem (.gitlab_ds/)
Job->>FS: mkdir .gitlab_ds
Job->>FS: touch .gitlab_ds/ready_${CI_JOB_ID}
Note over Job,FS: Signals source checkout complete
Service->>FS: Poll for ready_${CI_JOB_ID}
Service->>FS: Detect pom.xml files
Service->>FS: Write dependency_resolution.sh
Note over Service,FS: Script contains mvn dependency:tree commands
Job->>FS: Read dependency_resolution.sh
Note over Job: Wait for script (timeout 60s)
Job->>Job: Execute dependency_resolution.sh
Note over Job: Runs mvn dependency:tree for each project
Job->>FS: Generate maven.graph.json files
Note over Job,FS: Artifacts for DS Analyzer to consume
Service->>FS: Read service.log
Note over Service: Logs written during resolution
The analyzer runs as a sidecar [service](https://docs.gitlab.com/ci/services/) container alongside a dedicated resolution job in your pipeline:Minor (non-blocking): Shall we mention that this is used for Dependency Resolution?