Commit fe2699c5 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '34209-load-software-licenses' into 'master'

Allow selection of licenses from the SPDX catalogue

See merge request gitlab-org/gitlab!34961
parents 39694dce f01387c6
...@@ -100,7 +100,8 @@ module Projects ...@@ -100,7 +100,8 @@ module Projects
read_license_policies_endpoint: expose_path(api_v4_projects_managed_licenses_path(id: @project.id)), read_license_policies_endpoint: expose_path(api_v4_projects_managed_licenses_path(id: @project.id)),
write_license_policies_endpoint: write_license_policies_endpoint, write_license_policies_endpoint: write_license_policies_endpoint,
documentation_path: help_page_path('user/compliance/license_compliance/index'), documentation_path: help_page_path('user/compliance/license_compliance/index'),
empty_state_svg_path: helpers.image_path('illustrations/Dependency-list-empty-state.svg') empty_state_svg_path: helpers.image_path('illustrations/Dependency-list-empty-state.svg'),
software_licenses: SoftwareLicense.unclassified_licenses_for(project).pluck_names
} }
end end
end end
......
...@@ -73,6 +73,7 @@ module EE ...@@ -73,6 +73,7 @@ module EE
has_many :protected_environments has_many :protected_environments
has_many :software_license_policies, inverse_of: :project, class_name: 'SoftwareLicensePolicy' has_many :software_license_policies, inverse_of: :project, class_name: 'SoftwareLicensePolicy'
has_many :software_licenses, through: :software_license_policies
accepts_nested_attributes_for :software_license_policies, allow_destroy: true accepts_nested_attributes_for :software_license_policies, allow_destroy: true
has_many :packages, class_name: 'Packages::Package' has_many :packages, class_name: 'Packages::Package'
has_many :package_files, through: :packages, class_name: 'Packages::PackageFile' has_many :package_files, through: :packages, class_name: 'Packages::PackageFile'
......
...@@ -14,6 +14,15 @@ class SoftwareLicense < ApplicationRecord ...@@ -14,6 +14,15 @@ class SoftwareLicense < ApplicationRecord
scope :spdx, -> { where.not(spdx_identifier: nil) } scope :spdx, -> { where.not(spdx_identifier: nil) }
scope :unknown, -> { where(spdx_identifier: nil) } scope :unknown, -> { where(spdx_identifier: nil) }
scope :grouped_by_name, -> { group(:name) } scope :grouped_by_name, -> { group(:name) }
scope :unreachable_limit, -> { limit(500) }
def self.unclassified_licenses_for(project)
spdx.id_not_in(project.software_licenses).ordered.unreachable_limit
end
def self.pluck_names
pluck(:name)
end
def self.create_policy_for!(project:, name:, classification:) def self.create_policy_for!(project:, name:, classification:)
project.software_license_policies.create!( project.software_license_policies.create!(
......
...@@ -24,16 +24,28 @@ RSpec.describe Projects::LicensesController do ...@@ -24,16 +24,28 @@ RSpec.describe Projects::LicensesController do
project.add_reporter(user) project.add_reporter(user)
end end
it 'responds to an HTML request' do context "when requesting HTML" do
get :index, params: params subject { get :index, params: params }
expect(response).to have_gitlab_http_status(:ok) let_it_be(:mit_license) { create(:software_license, :mit) }
let_it_be(:apache_license) { create(:software_license, :apache_2_0) }
let_it_be(:custom_license) { create(:software_license, :user_entered) }
before do
subject
end
it 'returns the necessary licenses app data' do
licenses_app_data = assigns(:licenses_app_data) licenses_app_data = assigns(:licenses_app_data)
expect(response).to have_gitlab_http_status(:ok)
expect(licenses_app_data[:project_licenses_endpoint]).to eql(controller.helpers.project_licenses_path(project, detected: true, format: :json)) expect(licenses_app_data[:project_licenses_endpoint]).to eql(controller.helpers.project_licenses_path(project, detected: true, format: :json))
expect(licenses_app_data[:read_license_policies_endpoint]).to eql(controller.helpers.api_v4_projects_managed_licenses_path(id: project.id)) expect(licenses_app_data[:read_license_policies_endpoint]).to eql(controller.helpers.api_v4_projects_managed_licenses_path(id: project.id))
expect(licenses_app_data[:write_license_policies_endpoint]).to eql('') expect(licenses_app_data[:write_license_policies_endpoint]).to eql('')
expect(licenses_app_data[:documentation_path]).to eql(help_page_path('user/compliance/license_compliance/index')) expect(licenses_app_data[:documentation_path]).to eql(help_page_path('user/compliance/license_compliance/index'))
expect(licenses_app_data[:empty_state_svg_path]).to eql(controller.helpers.image_path('illustrations/Dependency-list-empty-state.svg')) expect(licenses_app_data[:empty_state_svg_path]).to eql(controller.helpers.image_path('illustrations/Dependency-list-empty-state.svg'))
expect(licenses_app_data[:software_licenses]).to eql([apache_license.name, mit_license.name])
end
end end
it 'counts usage of the feature' do it 'counts usage of the feature' do
......
...@@ -13,5 +13,9 @@ FactoryBot.define do ...@@ -13,5 +13,9 @@ FactoryBot.define do
spdx_identifier { 'Apache-2.0' } spdx_identifier { 'Apache-2.0' }
name { 'Apache 2.0 License' } name { 'Apache 2.0 License' }
end end
trait :user_entered do
spdx_identifier { nil }
end
end end
end end
...@@ -85,4 +85,27 @@ RSpec.describe SoftwareLicense do ...@@ -85,4 +85,27 @@ RSpec.describe SoftwareLicense do
it { expect(build(:software_license, name: 'MIT License', spdx_identifier: nil).canonical_id).to eq('mit license') } it { expect(build(:software_license, name: 'MIT License', spdx_identifier: nil).canonical_id).to eq('mit license') }
end end
end end
describe '.unclassified_licenses_for' do
subject { described_class.unclassified_licenses_for(project) }
let_it_be(:mit_license) { create(:software_license, :mit) }
let_it_be(:apache_license) { create(:software_license, :apache_2_0) }
let_it_be(:nonstandard_license) { create(:software_license, :user_entered) }
let_it_be(:project) { create(:project) }
context 'when a project has not classified licenses' do
it 'returns each license in the SPDX catalogue ordered by name' do
expect(subject.to_a).to eql([apache_license, mit_license])
end
end
context 'when some of the licenses are classified' do
let_it_be(:mit_policy) { create(:software_license_policy, project: project, software_license: mit_license) }
it 'returns each license in the SPDX catalogue that has not been classified' do
expect(subject).to contain_exactly(apache_license)
end
end
end
end end
...@@ -469,6 +469,7 @@ project: ...@@ -469,6 +469,7 @@ project:
- prometheus_alert_events - prometheus_alert_events
- self_managed_prometheus_alert_events - self_managed_prometheus_alert_events
- software_license_policies - software_license_policies
- software_licenses
- project_registry - project_registry
- packages - packages
- package_files - package_files
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment