Implement the update scheduler worker and service
## Why are we doing this work This issue covers the work that will handle the creation of the [CI/CD workload](https://gitlab.com/gitlab-org/gitlab/blob/2e7d3b21a017ab8eeb087b2e9989bd4ae8d1da72/app/services/ci/workloads/run_workload_service.rb#L13) > [!note] > A CI/CD workload is a new abstraction. This abstraction covers running arbitrary arbitrary workloads on the Runner infrastructure. In this case, we'll be running the dependency updates/refreshes. This worker will generate and run a CI/CD pipeline that results in the manifests and lock files updates required to update a dependency to a patched version. ## Diagram of flow ```mermaid %%{init: {'theme': 'dark'}}%% graph TD A["SBOM Ingestion Complete"] --> B["Schedule Updates Event"] B --> C["DependencyManagement::SecurityUpdate::UpdateWorker"] C --> D["DependencyManagement::SecurityUpdate::UpdateService"] D --> E["Call Finder"] E --> F["Fetch SBOM Occurrences<br/>+ Component Metadata<br/>+ Vulnerability Occurrences"] F --> G["Filter & Order Results"] G --> G1["Order by Severity<br/>Reachable First"] G --> G2["Exclude Dismissed<br/>Vulnerabilities"] G --> G3["Exclude Archived Data"] G --> G4["Only Bundler PURL Type"] G1 --> H["Vulnerability + Component Pairs"] G2 --> H G3 --> H G4 --> H H --> I["Check Solution for Each Pair"] I --> J{"Solution<br/>Available?"} J -->|No Solution| K["Filter Out Pair"] J -->|Solution Available| L["Keep for Processing"] K --> M["Filtered List of<br/>Dependency Updates"] L --> M M --> N["Group Updates<br/>by Dependency<br/>TBD"] N --> O["Trigger CI/CD Workload<br/>for Each Component"] O --> P["Generate & Run Pipeline"] P --> Q["Update Manifests<br/>& Lock Files"] style A fill:#1e3a5f,stroke:#4a9eff,color:#fff style C fill:#5f3a1e,stroke:#ffa84a,color:#fff style D fill:#5f3a1e,stroke:#ffa84a,color:#fff style E fill:#3a1e5f,stroke:#b84aff,color:#fff style J fill:#5f4a1e,stroke:#ffcc4a,color:#fff style O fill:#1e5f3a,stroke:#4aff8a,color:#fff style Q fill:#1e5f3a,stroke:#4aff8a,color:#fff` ``` ## Relevant links - [AI flow workload usage](https://gitlab.com/gitlab-org/gitlab/blob/2e7d3b21a017ab8eeb087b2e9989bd4ae8d1da72/ee/app/services/ai/flow_triggers/run_service.rb#L86) - [AI Duo workflows usage](https://gitlab.com/gitlab-org/gitlab/blob/2e7d3b21a017ab8eeb087b2e9989bd4ae8d1da72/ee/app/services/ai/duo_workflows/start_workflow_service.rb#L50) ## Non-functional requirements - [x] Documentation: We should document the priority we give to our updates publicly. - [x] Feature flag: The worker and service should respect the FF. - [x] Performance: The finder should run with a p95 of 500ms - [x] Testing: We need to test that we deterministically order (and potentially group) the dependency updates. ## Implementation plan ### MR 1: Create a finder for the vulnerabilities We'll need to create a finder that fetches the SBOM occurrences, their SBOM component metadata (purl type, version, etc.) and the associated SBOM vulnerability occurrences. - Vulnerability occurrences should return ordered from most severe to least severe. - Vulnerability order should also take into account reachable components first. - Vulnerability results should omit vulnerabilities that have been dismissed. - Archived data (projects, vulnerabilities, sbom occurrences) should be excluded. - We should only get for vulnerabilities that are associated with supported PURL types - **only Bundler is supported at this stage**! ### MR 2: Create a security update worker and service The `DependencyManagement::SecurityUpdate::UpdateWorker` worker will call the `DependencyManagement::SecurityUpdate::UpdateService` to start the process of launching new pipelines that update the dependencies. - The service calls the finder - It checks the solution for each of the vulnerability + component pairs. - If the solution matches a known "no solution is available" description, the pair is omitted/filtered out. - If the solution doesn't match then we assume that there's a solution available, and keep it for further processing. - TBD: Group dependency updates for the same dependency. - Finally we take the list and trigger a CI/CD workload to update each of the components remaining. - TBD: Should we create a separate event for this? The event chain would look like this: `(sbom ingestion done) -> (schedule updates) -> (schedule individual update)`. ## Verification steps Verify that the event is emitted when a supported dependency update (Bundler update) is run and the feature flag is toggled on.
issue