Add classification reason for the license_types unknown fallback
Backend half of a two-MR follow-up. Frontend half is stacked on top of this one.
What does this MR do and why?
SCA::LicenseCompliance can classify a compound SPDX expression as allowed or denied through the license_types unknown fallback introduced in !257138 (merged), but the resulting SCA::LicensePolicy carries no signal that this happened. A reviewer sees the real detected expression (for example MIT AND Apache-2.0) labeled Allowed with no indication that neither operand was individually vetted, since it was treated as unknown and happens to be allow-listed under that name.
SCA::LicensePolicy gains a classification_reason attribute, nil by default. allowed_license_expression? now returns [allowed, reason] instead of a bare boolean, setting the reason to :license_types_unknown_fallback only on the branch that actually takes the fallback. Every other path (direct matches, the licenses property's per-operand evaluation, the plus-suffix path, the flag disabled) keeps a nil reason.
Security::LicensePolicyEntity exposes the reason inside the existing classification hash, so both consumers of this data (the merge request widget and the pipeline Licenses tab) get it without any further change, since both already go through this entity.
This MR is backend-only. The widget does not read or render the new field yet; that is the stacked frontend follow-up.
How to set up and validate locally
This MR has no independent user-facing behavior; the new field is inert until the frontend follow-up reads it. Validate by inspecting the API response directly.
Preconditions: GitLab Ultimate. Merge request approval policies are an Ultimate-tier feature.
-
Enable the feature flag on the rails console:
Feature.enable(:license_types_unknown_expression_fallback) -
Create a project.
-
Go to Secure > Policies.
-
Select New policy.
-
Select Merge request approval policy.
-
Switch to .yaml mode.
-
Paste the following policy:
approval_policy: - name: Approved licenses enabled: true rules: - type: license_finding match_on_inclusion_license: false license_states: - newly_detected branch_type: protected license_types: - unknown actions: - type: require_approval approvals_required: 1 role_approvers: - developer - type: send_bot_message enabled: true -
Merge the merge request this creates, to activate the policy.
-
Add an empty
Gemfile.lockfile to the project. -
Add a file called
gl-sbom-gem-bundler.cdx.jsonreporting the license expressionMIT AND Apache-2.0:{ "bomFormat": "CycloneDX", "specVersion": "1.4", "serialNumber": "urn:uuid:a15e529c-2113-4a11-a694-6bc3ea4e2b53", "version": 1, "metadata": { "timestamp": "2022-02-23T08:02:39Z", "tools": [ { "vendor": "GitLab", "name": "Gemnasium", "version": "2.34.0" } ], "authors": [ { "name": "GitLab", "email": "support@gitlab.com" } ], "properties": [ { "name": "gitlab:dependency_scanning:input_file:path", "value": "Gemfile.lock" }, { "name": "gitlab:dependency_scanning:package_manager:name", "value": "bundler" }, { "name": "gitlab:meta:schema_version", "value": "1" } ] }, "components": [ { "name": "sidekiq", "version": "4.2.10", "purl": "pkg:gem/sidekiq@4.2.10", "type": "library", "bom-ref": "pkg:gem/sidekiq@4.2.10", "licenses": [ { "license": { "name": "MIT AND Apache-2.0" } } ] } ] } -
Create a new merge request adding a
.gitlab-ci.ymlfile with the content:include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml gemnasium-dependency_scanning: stage: test script: 'pwd' artifacts: reports: cyclonedx: gl-sbom-gem-bundler.cdx.json -
Wait for that merge request's pipeline to finish.
-
Open that merge request's
/-/reports/license-complianceAPI response (or inspect it via Reports > License compliance's network request in the browser). -
Verify the
classificationobject for theMIT AND Apache-2.0dependency now includes"reason": "license_types_unknown_fallback", alongside the existingid,name, andapproval_statuskeys. -
Verify a dependency resolved by a direct policy match (not a compound expression) has
"reason": null.
References
- Follows up !257138 (merged) (merged)
- Implements #630591