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_etag took 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 pass build.job_artifacts_archive and are unchanged in behavior.
  • audit_download accepts an artifact: kwarg that it forwards to Ci::ArtifactDownloadAuditor (which already supports it, and which the UI's EE controller already passes).
  • doc/api/openapi/openapi_v3.yaml is regenerated, as static-analysis enforces it via gitlab:openapi:v3:check_docs.

References

Issue: #35805 (closed)

How to set up and validate locally

  1. Pick a project with a job that produced a junit report.

  2. Fetch the report:

    curl --header "PRIVATE-TOKEN: $TOKEN" \
      --url "$GDK/api/v4/projects/$PROJECT/jobs/$JOB/artifacts?file_type=junit" \
      --output junit.xml.gz
  3. Repeat without file_type and confirm the zip archive is still returned.

  4. Request an unsupported type (file_type=trace, file_type=bogus) and confirm 400.

  5. 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:141 has a literal placeholder: The file_type attribute was added in GitLab 19.X. which needs the real milestone.
Edited by Andreas Kunze

Merge request reports

Loading
Loading