Skip to content

Add Repository X-ray service in monolith

What does this MR do and why?

Background

The Repository X-Ray is a tool that searches for dependency manager configuration files (aka "lock files") and then extracts a list of libraries from the content.

In #474306 (comment 2025085630), we decided to migrate the Repository X-Ray functionality into the GitLab Rails monolith. This gives us two main benefits: (i) it will eventually allow us to run the service outside of the CI pipeline, and (ii) we can maintain the parsing logic centrally so that other domains can utilize it.

Previous MRs

In !162313 (merged), we added the ConfigFiles::Base class where the intention is for each dependency manager config file type to be represented by a child class. The child class contains the parsing logic to extract a list of libraries and their versions from the file content.

In !162891 (merged), we added the ConfigFileParser class which searches through the project repository for dependency config files, matches them to the applicable config file class, and then parses them.

This MR

In this MR, we introduce a Repository Xray service which utilizes ConfigFileParser to extract the config files from a repository. Then it saves the parsed data to the xray_reports table, and outputs a service response with success/error messages. In the next MR, these messages will be logged in Sidekiq as metadata when we introduce the worker that runs this service.

Additionally, added sentry error tracking on the config file base class so we can be notified if the parsing logic needs to change.

Partially resolves #476180 (closed).

Query plan

Projects::XrayReport.upsert_all(reports_array, unique_by: [:project_id, :lang])

NOTE: The batches uploaded would always be small. We parse at most one config file per language, and we only support a few languages presently (and will unlikely support a number that would be detrimental to this bulk upsert).

INSERT INTO "xray_reports" ("project_id","payload","lang","file_checksum","created_at","updated_at")
VALUES
(32, '{"libs":[{"name":"abc.org/mylib (1.3.0)"},{"name":"golang.org/x/mod (0.5.0)"}],"checksum":"ba58588b25327d8c3d1e64e9fb57c256f3bd0e25b07edf05774d5540f201d1de","fileName":"dir1/dir2/go.mod","scannerVersion":"0.0.0"}', 'go', '\x62613538353838623235333237643863336431653634653966623537633235366633626430653235623037656466303537373464353534306632303164316465', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(32, '{"libs":[{"name":"bcrypt (3.1.20)"}],"checksum":"fc37c826eee95606926e3d62104fb8ea7a07a256ade74fea4c044a7df9ee3073","fileName":"Gemfile.lock","scannerVersion":"0.0.0"}', 'ruby', '\x66633337633832366565653935363036393236653364363231303466623865613761303761323536616465373466656134633034346137646639656533303733', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
ON CONFLICT ("project_id","lang") DO UPDATE SET updated_at=(CASE WHEN ("xray_reports"."payload" IS NOT DISTINCT FROM excluded."payload" AND "xray_reports"."file_checksum" IS NOT DISTINCT FROM excluded."file_checksum") THEN "xray_reports".updated_at ELSE CURRENT_TIMESTAMP END),"payload"=excluded."payload","file_checksum"=excluded."file_checksum" RETURNING "id"

Query plan: https://console.postgres.ai/gitlab/gitlab-production-main/sessions/31102/commands/96618

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

How to set up and validate locally

  1. Create a new blank project and commit these two files to the repo:

subdir/Gemfile.lock:

GEM
  remote: https://rubygems.org/
  specs:
    bcrypt (3.1.20)
    logger (1.5.3)
    my_lib (1.0.2)

PLATFORMS
  ruby

DEPENDENCIES
  bcrypt (~> 3.1, >= 3.1.14)
  logger (~> 1.5.3)

BUNDLED WITH
  2.5.16

pom.xml:

invalid content
  1. Run the service in the Rails console:
project = Project.last # Should be the project you created in Step 1

response = Ai::RepositoryXrayService.new(project).execute
  1. Observe that the service response is as expected:

Screenshot_2024-08-29_at_1.06.48_PM

  1. Observe that the X-ray report for the valid config file (Gemfile.lock) is recorded:
project.reload.xray_reports

Screenshot_2024-08-29_at_1.07.57_PM

Related to #476180 (closed)

Edited by Leaminn Ma

Merge request reports

Loading