feat(api): Add file_type parameter to job artifacts API
What does this MR do and why?
The REST API endpoint GET /projects/:id/jobs/:job_id/artifacts
currently can only serve the archive artifact. If a job produces report
artifacts they are only reachable through the UI route
/<project_path>/-/jobs/<id>/artifacts/download?file_type=<type>.
This is session-oriented and not available via the API. Scripts or other
integrations have no supported way to fetch report artifacts other than
duplicating the reports into artifacts:paths.
This MR adds an optional file_type parameter (default "archive") so the API
mirrors what the UI already does. The resolution logic is reused as-is:
Ci::Build#artifact_for_type, the same method the UI controller calls.
Accepted values are restricted to
Enums::Ci::JobArtifact.downloadable_types, which excludes metadata and
trace (trace already has its own endpoint). An unrecognized value returns
400.
Only the job-ID endpoint gains the parameter. The ref-name endpoints keep their archive-only behavior.
Authorization
The existing build-level authorize_read_job_artifacts!(build) reads the
archive's accessibility, so a non-archive type needs its own check. Otherwise a
private dotenv on a job whose archive is public would become world-readable. The
per-artifact authorize!(:read_job_artifacts, job_artifact) is layered on top
rather than replacing the build-level gate, and is skipped when the artifact is
absent.
Incidental changes
artifact_etagtook a build and derived the archive from it. Its first argument is now the artifact record, so it can produce an ETag for any type. The three archive-serving call sites passbuild.job_artifacts_archiveand are unchanged in behavior.audit_downloadaccepts anartifact:kwarg that it forwards toCi::ArtifactDownloadAuditor(which already supports it, and which the UI's EE controller already passes).doc/api/openapi/openapi_v3.yamlis regenerated, asstatic-analysisenforces it viagitlab:openapi:v3:check_docs.
References
Issue: #35805 (closed)
How to set up and validate locally
-
Pick a project with a job that produced a
junitreport. -
Fetch the report:
curl --header "PRIVATE-TOKEN: $TOKEN" \ --url "$GDK/api/v4/projects/$PROJECT/jobs/$JOB/artifacts?file_type=junit" \ --output junit.xml.gz -
Repeat without file_type and confirm the zip archive is still returned.
-
Request an unsupported type (file_type=trace, file_type=bogus) and confirm 400.
-
On a project where the report artifact has private or none accessibility, request it as a guest and confirm 403 while the archive still downloads.
TODO
-
lib/api/ci/job_artifacts.rb:141has a literal placeholder:The file_type attribute was added in GitLab 19.X.which needs the real milestone.