Fold the dependency malware field into dependency_malware_detection
What does this MR do and why?
Malware on the dependency list was gated by two flags at once:
dependency_malware_detection— the badge and filter token in the UI.dependency_malware_field_project— whether the API returned themalwarefield at all.
Enabling either one alone produces nothing useful: the field with no badge, or a badge with no data. The second flag is also about to gate group surfaces via !251901 (merged) and !251903, at which point its _project suffix stops being true.
This folds them into one. The backend field now goes through the same dependency_malware_detection_feature_flag_enabled? helpers on Group and Project that the frontend gating already uses, and dependency_malware_field_project is deleted. This is the arrangement agreed for the vulnerability report in !249360 (merged) and !249418 (merged), applied to the dependency list.
Callers changed: Types::Sbom::DependencyInterface, DependencyEntity, API::Entities::Dependency.
Filtering keeps its own flag, malicious_packages_dependency_list_filtering, until the Elasticsearch APIs behind it are finished.
Feature flag
| Flag | Type | Default | Gates |
|---|---|---|---|
dependency_malware_detection |
beta | off | Backend malware field, plus the UI badge and filter token |
Removed: dependency_malware_field_project. It was never enabled anywhere, so no rollout state is lost. Its rollout issue #600274 (closed) can be closed in favour of #611434.
One behaviour change: callers previously passed the project straight to Feature.enabled?. The helper walks up the namespace hierarchy, so enabling the flag on a group now also reaches its projects and subgroups. Both flags are off everywhere, so nothing changes for users today.
Database review
No database changes. No migrations, no new or modified queries, no new scopes.
How to set up and validate locally
Local testing steps
-
Confirm the old flag is gone and only the consolidated one remains:
Feature::Definition.definitions.key?(:dependency_malware_field_project) # => false Feature::Definition.definitions.key?(:dependency_malware_detection) # => true -
Use a project inside a subgroup so the walk up the hierarchy is exercised:
root = Group.find_by_full_path('your-group') subgroup = root.children.first project = subgroup.projects.first project.dependency_malware_detection_feature_flag_enabled? # => false -
Enable on the root group only, then re-check:
Feature.enable(:dependency_malware_detection, root) root.dependency_malware_detection_feature_flag_enabled? # => true subgroup.dependency_malware_detection_feature_flag_enabled? # => true project.dependency_malware_detection_feature_flag_enabled? # => true -
Confirm the project dependency API still gates correctly. With the flag on,
malwareappears on each entry:curl --header "PRIVATE-TOKEN: <token>" \ "http://gdk.test:3000/api/v4/projects/<id>/dependencies" \ | jq '[.[] | {name, malware}]'With
Feature.disable(:dependency_malware_detection, root)and the flag off for the project, themalwarekey is absent.
Before, on master: two switches. Turning on dependency_malware_field_project returns the field but renders no badge; turning on dependency_malware_detection renders a badge with no data. Enabling either for a group does not reach its projects.
After: one switch. Feature.enable(:dependency_malware_detection, root) turns on the field and the badge together, for the group and everything under it.
| Flag enabled on | Root group | Subgroup | Project |
|---|---|---|---|
| root group | true |
true |
true |
| subgroup | false |
true |
true |
| project | false |
false |
true |
| nothing | false |
false |
false |
Related
- Parent issue: #587647 (closed)
- Agreement this implements: gitlab-org#18456 (comment 3652929251)
- Flag consolidation this follows: !249360 (merged) and !249418 (merged)
- Group REST MR: !251901 (merged)
- Group GraphQL MR: !251903
- Rollout issue for the surviving flag: #611434
- Dependency list pagination fix: !251956