Commit d391cea2 authored by Steve Abrams's avatar Steve Abrams Committed by Tiger Watson

Add setting for duplicate generic packages

parent ff754a29
...@@ -25,6 +25,16 @@ module Mutations ...@@ -25,6 +25,16 @@ module Mutations
required: false, required: false,
description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_duplicate_exception_regex) description: copy_field_description(Types::Namespace::PackageSettingsType, :maven_duplicate_exception_regex)
argument :generic_duplicates_allowed,
GraphQL::BOOLEAN_TYPE,
required: false,
description: copy_field_description(Types::Namespace::PackageSettingsType, :generic_duplicates_allowed)
argument :generic_duplicate_exception_regex,
Types::UntrustedRegexp,
required: false,
description: copy_field_description(Types::Namespace::PackageSettingsType, :generic_duplicate_exception_regex)
field :package_settings, field :package_settings,
Types::Namespace::PackageSettingsType, Types::Namespace::PackageSettingsType,
null: true, null: true,
......
...@@ -10,5 +10,7 @@ module Types ...@@ -10,5 +10,7 @@ module Types
field :maven_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.' field :maven_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.' field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
field :generic_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
field :generic_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
end end
end end
...@@ -6,13 +6,15 @@ class Namespace::PackageSetting < ApplicationRecord ...@@ -6,13 +6,15 @@ class Namespace::PackageSetting < ApplicationRecord
PackageSettingNotImplemented = Class.new(StandardError) PackageSettingNotImplemented = Class.new(StandardError)
PACKAGES_WITH_SETTINGS = %w[maven].freeze PACKAGES_WITH_SETTINGS = %w[maven generic].freeze
belongs_to :namespace, inverse_of: :package_setting_relation belongs_to :namespace, inverse_of: :package_setting_relation
validates :namespace, presence: true validates :namespace, presence: true
validates :maven_duplicates_allowed, inclusion: { in: [true, false] } validates :maven_duplicates_allowed, inclusion: { in: [true, false] }
validates :maven_duplicate_exception_regex, untrusted_regexp: true, length: { maximum: 255 } validates :maven_duplicate_exception_regex, untrusted_regexp: true, length: { maximum: 255 }
validates :generic_duplicates_allowed, inclusion: { in: [true, false] }
validates :generic_duplicate_exception_regex, untrusted_regexp: true, length: { maximum: 255 }
class << self class << self
def duplicates_allowed?(package) def duplicates_allowed?(package)
......
# frozen_string_literal: true # frozen_string_literal: true
module Packages module Packages
DuplicatePackageError = Class.new(StandardError)
def self.table_name_prefix def self.table_name_prefix
'packages_' 'packages_'
end end
......
...@@ -5,7 +5,10 @@ module Namespaces ...@@ -5,7 +5,10 @@ module Namespaces
class UpdateService < BaseContainerService class UpdateService < BaseContainerService
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
ALLOWED_ATTRIBUTES = %i[maven_duplicates_allowed maven_duplicate_exception_regex].freeze ALLOWED_ATTRIBUTES = %i[maven_duplicates_allowed
maven_duplicate_exception_regex
generic_duplicates_allowed
generic_duplicate_exception_regex].freeze
def execute def execute
return ServiceResponse.error(message: 'Access Denied', http_status: 403) unless allowed? return ServiceResponse.error(message: 'Access Denied', http_status: 403) unless allowed?
......
...@@ -23,6 +23,10 @@ module Packages ...@@ -23,6 +23,10 @@ module Packages
.new(project, current_user, package_params) .new(project, current_user, package_params)
.execute .execute
unless Namespace::PackageSetting.duplicates_allowed?(package)
raise ::Packages::DuplicatePackageError if target_file_is_duplicate?(package)
end
package.update_column(:status, params[:status]) if params[:status] && params[:status] != package.status package.update_column(:status, params[:status]) if params[:status] && params[:status] != package.status
package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present? package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present?
...@@ -40,6 +44,10 @@ module Packages ...@@ -40,6 +44,10 @@ module Packages
::Packages::CreatePackageFileService.new(package, file_params).execute ::Packages::CreatePackageFileService.new(package, file_params).execute
end end
def target_file_is_duplicate?(package)
package.package_files.with_file_name(params[:file_name]).exists?
end
end end
end end
end end
---
title: Add setting to allow or disallow duplicates for generic packages
merge_request: 60664
author:
type: added
# frozen_string_literal: true
class AddGenericPackageDuplicateSettingsToNamespacePackageSettings < ActiveRecord::Migration[6.0]
# rubocop:disable Migration/AddLimitToTextColumns
# limit is added in 20210429193106_add_text_limit_to_namespace_package_settings_generic_duplicate_exception_regex
def change
add_column :namespace_package_settings, :generic_duplicates_allowed, :boolean, null: false, default: true
add_column :namespace_package_settings, :generic_duplicate_exception_regex, :text, null: false, default: ''
end
# rubocop:enable Migration/AddLimitToTextColumns
end
# frozen_string_literal: true
class AddTextLimitToNamespacePackageSettingsGenericDuplicateExceptionRegex < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_text_limit :namespace_package_settings, :generic_duplicate_exception_regex, 255
end
def down
remove_text_limit :namespace_package_settings, :generic_duplicate_exception_regex
end
end
c2b5ad6786e1c71ccff391b03fcd0635dfd42d69484443291a692cef9f3ffda5
\ No newline at end of file
e0898e4e439cde4e3b84808e7505490fe956cf17922f5c779b3384997d36cafd
\ No newline at end of file
...@@ -14791,6 +14791,9 @@ CREATE TABLE namespace_package_settings ( ...@@ -14791,6 +14791,9 @@ CREATE TABLE namespace_package_settings (
namespace_id bigint NOT NULL, namespace_id bigint NOT NULL,
maven_duplicates_allowed boolean DEFAULT true NOT NULL, maven_duplicates_allowed boolean DEFAULT true NOT NULL,
maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL, maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
generic_duplicates_allowed boolean DEFAULT true NOT NULL,
generic_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
CONSTRAINT check_31340211b1 CHECK ((char_length(generic_duplicate_exception_regex) <= 255)),
CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255)) CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255))
); );
...@@ -3867,6 +3867,8 @@ Input type: `UpdateNamespacePackageSettingsInput` ...@@ -3867,6 +3867,8 @@ Input type: `UpdateNamespacePackageSettingsInput`
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="mutationupdatenamespacepackagesettingsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationupdatenamespacepackagesettingsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdatenamespacepackagesettingsgenericduplicateexceptionregex"></a>`genericDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="mutationupdatenamespacepackagesettingsgenericduplicatesallowed"></a>`genericDuplicatesAllowed` | [`Boolean`](#boolean) | Indicates whether duplicate generic packages are allowed for this namespace. |
| <a id="mutationupdatenamespacepackagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. | | <a id="mutationupdatenamespacepackagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="mutationupdatenamespacepackagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. | | <a id="mutationupdatenamespacepackagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. |
| <a id="mutationupdatenamespacepackagesettingsnamespacepath"></a>`namespacePath` | [`ID!`](#id) | The namespace path where the namespace package setting is located. | | <a id="mutationupdatenamespacepackagesettingsnamespacepath"></a>`namespacePath` | [`ID!`](#id) | The namespace path where the namespace package setting is located. |
...@@ -10440,6 +10442,8 @@ Namespace-level Package Registry settings. ...@@ -10440,6 +10442,8 @@ Namespace-level Package Registry settings.
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="packagesettingsgenericduplicateexceptionregex"></a>`genericDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="packagesettingsgenericduplicatesallowed"></a>`genericDuplicatesAllowed` | [`Boolean!`](#boolean) | Indicates whether duplicate generic packages are allowed for this namespace. |
| <a id="packagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. | | <a id="packagesettingsmavenduplicateexceptionregex"></a>`mavenDuplicateExceptionRegex` | [`UntrustedRegexp`](#untrustedregexp) | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. |
| <a id="packagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean!`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. | | <a id="packagesettingsmavenduplicatesallowed"></a>`mavenDuplicatesAllowed` | [`Boolean!`](#boolean) | Indicates whether duplicate Maven packages are allowed for this namespace. |
......
...@@ -74,6 +74,8 @@ module API ...@@ -74,6 +74,8 @@ module API
Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project.id }) Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: project.id })
forbidden! forbidden!
rescue ::Packages::DuplicatePackageError
bad_request!('Duplicate package is not allowed')
end end
desc 'Download package file' do desc 'Download package file' do
......
...@@ -7,6 +7,9 @@ FactoryBot.define do ...@@ -7,6 +7,9 @@ FactoryBot.define do
maven_duplicates_allowed { true } maven_duplicates_allowed { true }
maven_duplicate_exception_regex { 'SNAPSHOT' } maven_duplicate_exception_regex { 'SNAPSHOT' }
generic_duplicates_allowed { true }
generic_duplicate_exception_regex { 'foo' }
trait :group do trait :group do
namespace { association(:group) } namespace { association(:group) }
end end
......
...@@ -25,7 +25,9 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do ...@@ -25,7 +25,9 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do
end end
RSpec.shared_examples 'updating the namespace package setting' do RSpec.shared_examples 'updating the namespace package setting' do
it_behaves_like 'updating the namespace package setting attributes', from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } it_behaves_like 'updating the namespace package setting attributes',
from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar' }
it_behaves_like 'returning a success' it_behaves_like 'returning a success'
...@@ -56,7 +58,13 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do ...@@ -56,7 +58,13 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update do
context 'with existing namespace package setting' do context 'with existing namespace package setting' do
let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) } let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
let_it_be(:params) { { namespace_path: namespace.full_path, maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } } let_it_be(:params) do
{ namespace_path: namespace.full_path,
maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'RELEASE',
generic_duplicates_allowed: false,
generic_duplicate_exception_regex: 'bar' }
end
where(:user_role, :shared_examples_name) do where(:user_role, :shared_examples_name) do
:maintainer | 'updating the namespace package setting' :maintainer | 'updating the namespace package setting'
......
...@@ -14,9 +14,12 @@ RSpec.describe Namespace::PackageSetting do ...@@ -14,9 +14,12 @@ RSpec.describe Namespace::PackageSetting do
it { is_expected.to allow_value(true).for(:maven_duplicates_allowed) } it { is_expected.to allow_value(true).for(:maven_duplicates_allowed) }
it { is_expected.to allow_value(false).for(:maven_duplicates_allowed) } it { is_expected.to allow_value(false).for(:maven_duplicates_allowed) }
it { is_expected.not_to allow_value(nil).for(:maven_duplicates_allowed) } it { is_expected.not_to allow_value(nil).for(:maven_duplicates_allowed) }
it { is_expected.to allow_value(true).for(:generic_duplicates_allowed) }
it { is_expected.to allow_value(false).for(:generic_duplicates_allowed) }
it { is_expected.not_to allow_value(nil).for(:generic_duplicates_allowed) }
end end
describe '#maven_duplicate_exception_regex' do describe 'regex values' do
let_it_be(:package_settings) { create(:namespace_package_setting) } let_it_be(:package_settings) { create(:namespace_package_setting) }
subject { package_settings } subject { package_settings }
...@@ -24,12 +27,14 @@ RSpec.describe Namespace::PackageSetting do ...@@ -24,12 +27,14 @@ RSpec.describe Namespace::PackageSetting do
valid_regexps = %w[SNAPSHOT .* v.+ v10.1.* (?:v.+|SNAPSHOT|TEMP)] valid_regexps = %w[SNAPSHOT .* v.+ v10.1.* (?:v.+|SNAPSHOT|TEMP)]
invalid_regexps = ['[', '(?:v.+|SNAPSHOT|TEMP'] invalid_regexps = ['[', '(?:v.+|SNAPSHOT|TEMP']
valid_regexps.each do |valid_regexp| [:maven_duplicate_exception_regex, :generic_duplicate_exception_regex].each do |attribute|
it { is_expected.to allow_value(valid_regexp).for(:maven_duplicate_exception_regex) } valid_regexps.each do |valid_regexp|
end it { is_expected.to allow_value(valid_regexp).for(attribute) }
end
invalid_regexps.each do |invalid_regexp| invalid_regexps.each do |invalid_regexp|
it { is_expected.not_to allow_value(invalid_regexp).for(:maven_duplicate_exception_regex) } it { is_expected.not_to allow_value(invalid_regexp).for(attribute) }
end
end end
end end
end end
...@@ -41,7 +46,7 @@ RSpec.describe Namespace::PackageSetting do ...@@ -41,7 +46,7 @@ RSpec.describe Namespace::PackageSetting do
context 'package types with package_settings' do context 'package types with package_settings' do
# As more package types gain settings they will be added to this list # As more package types gain settings they will be added to this list
[:maven_package].each do |format| [:maven_package, :generic_package].each do |format|
let_it_be(:package) { create(format, name: 'foo', version: 'beta') } # rubocop:disable Rails/SaveBang let_it_be(:package) { create(format, name: 'foo', version: 'beta') } # rubocop:disable Rails/SaveBang
let_it_be(:package_type) { package.package_type } let_it_be(:package_type) { package.package_type }
let_it_be(:package_setting) { package.project.namespace.package_settings } let_it_be(:package_setting) { package.project.namespace.package_settings }
...@@ -70,7 +75,7 @@ RSpec.describe Namespace::PackageSetting do ...@@ -70,7 +75,7 @@ RSpec.describe Namespace::PackageSetting do
end end
context 'package types without package_settings' do context 'package types without package_settings' do
[:npm_package, :conan_package, :nuget_package, :pypi_package, :composer_package, :generic_package, :golang_package, :debian_package].each do |format| [:npm_package, :conan_package, :nuget_package, :pypi_package, :composer_package, :golang_package, :debian_package].each do |format|
let_it_be(:package) { create(format) } # rubocop:disable Rails/SaveBang let_it_be(:package) { create(format) } # rubocop:disable Rails/SaveBang
let_it_be(:package_setting) { package.project.namespace.package_settings } let_it_be(:package_setting) { package.project.namespace.package_settings }
......
...@@ -12,7 +12,9 @@ RSpec.describe 'Updating the package settings' do ...@@ -12,7 +12,9 @@ RSpec.describe 'Updating the package settings' do
{ {
namespace_path: namespace.full_path, namespace_path: namespace.full_path,
maven_duplicates_allowed: false, maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'foo-.*' maven_duplicate_exception_regex: 'foo-.*',
generic_duplicates_allowed: false,
generic_duplicate_exception_regex: 'bar-.*'
} }
end end
...@@ -22,6 +24,8 @@ RSpec.describe 'Updating the package settings' do ...@@ -22,6 +24,8 @@ RSpec.describe 'Updating the package settings' do
packageSettings { packageSettings {
mavenDuplicatesAllowed mavenDuplicatesAllowed
mavenDuplicateExceptionRegex mavenDuplicateExceptionRegex
genericDuplicatesAllowed
genericDuplicateExceptionRegex
} }
errors errors
QL QL
...@@ -40,6 +44,8 @@ RSpec.describe 'Updating the package settings' do ...@@ -40,6 +44,8 @@ RSpec.describe 'Updating the package settings' do
expect(mutation_response['errors']).to be_empty expect(mutation_response['errors']).to be_empty
expect(package_settings_response['mavenDuplicatesAllowed']).to eq(params[:maven_duplicates_allowed]) expect(package_settings_response['mavenDuplicatesAllowed']).to eq(params[:maven_duplicates_allowed])
expect(package_settings_response['mavenDuplicateExceptionRegex']).to eq(params[:maven_duplicate_exception_regex]) expect(package_settings_response['mavenDuplicateExceptionRegex']).to eq(params[:maven_duplicate_exception_regex])
expect(package_settings_response['genericDuplicatesAllowed']).to eq(params[:generic_duplicates_allowed])
expect(package_settings_response['genericDuplicateExceptionRegex']).to eq(params[:generic_duplicate_exception_regex])
end end
end end
...@@ -69,8 +75,8 @@ RSpec.describe 'Updating the package settings' do ...@@ -69,8 +75,8 @@ RSpec.describe 'Updating the package settings' do
RSpec.shared_examples 'accepting the mutation request updating the package settings' do RSpec.shared_examples 'accepting the mutation request updating the package settings' do
it_behaves_like 'updating the namespace package setting attributes', it_behaves_like 'updating the namespace package setting attributes',
from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' }, from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'foo-.*' } to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'foo-.*', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar-.*' }
it_behaves_like 'returning a success' it_behaves_like 'returning a success'
it_behaves_like 'rejecting invalid regex' it_behaves_like 'rejecting invalid regex'
......
...@@ -32,7 +32,9 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do ...@@ -32,7 +32,9 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do
end end
shared_examples 'updating the namespace package setting' do shared_examples 'updating the namespace package setting' do
it_behaves_like 'updating the namespace package setting attributes', from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } it_behaves_like 'updating the namespace package setting attributes',
from: { maven_duplicates_allowed: true, maven_duplicate_exception_regex: 'SNAPSHOT', generic_duplicates_allowed: true, generic_duplicate_exception_regex: 'foo' },
to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', generic_duplicates_allowed: false, generic_duplicate_exception_regex: 'bar' }
it_behaves_like 'returning a success' it_behaves_like 'returning a success'
...@@ -60,7 +62,12 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do ...@@ -60,7 +62,12 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService do
context 'with existing namespace package setting' do context 'with existing namespace package setting' do
let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) } let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) }
let_it_be(:params) { { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE' } } let_it_be(:params) do
{ maven_duplicates_allowed: false,
maven_duplicate_exception_regex: 'RELEASE',
generic_duplicates_allowed: false,
generic_duplicate_exception_regex: 'bar' }
end
where(:user_role, :shared_examples_name) do where(:user_role, :shared_examples_name) do
:maintainer | 'updating the namespace package setting' :maintainer | 'updating the namespace package setting'
......
...@@ -6,13 +6,16 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -6,13 +6,16 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:pipeline) { create(:ci_pipeline, user: user) } let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
let_it_be(:file_name) { 'myfile.tar.gz.1' }
let(:build) { double('build', pipeline: pipeline) } let(:build) { double('build', pipeline: pipeline) }
describe '#execute' do describe '#execute' do
let_it_be(:package) { create(:generic_package, project: project) }
let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' } let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' }
let(:temp_file) { Tempfile.new("test") } let(:temp_file) { Tempfile.new("test") }
let(:file) { UploadedFile.new(temp_file.path, sha256: sha256) } let(:file) { UploadedFile.new(temp_file.path, sha256: sha256) }
let(:package) { create(:generic_package, project: project) }
let(:package_service) { double } let(:package_service) { double }
let(:params) do let(:params) do
...@@ -20,7 +23,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -20,7 +23,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
package_name: 'mypackage', package_name: 'mypackage',
package_version: '0.0.1', package_version: '0.0.1',
file: file, file: file,
file_name: 'myfile.tar.gz.1', file_name: file_name,
build: build build: build
} }
end end
...@@ -34,7 +37,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -34,7 +37,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
} }
end end
subject { described_class.new(project, user, params).execute } subject(:execute_service) { described_class.new(project, user, params).execute }
before do before do
FileUtils.touch(temp_file) FileUtils.touch(temp_file)
...@@ -47,14 +50,14 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -47,14 +50,14 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
end end
it 'creates package file', :aggregate_failures do it 'creates package file', :aggregate_failures do
expect { subject }.to change { package.package_files.count }.by(1) expect { execute_service }.to change { package.package_files.count }.by(1)
.and change { Packages::PackageFileBuildInfo.count }.by(1) .and change { Packages::PackageFileBuildInfo.count }.by(1)
package_file = package.package_files.last package_file = package.package_files.last
aggregate_failures do aggregate_failures do
expect(package_file.package.status).to eq('default') expect(package_file.package.status).to eq('default')
expect(package_file.package).to eq(package) expect(package_file.package).to eq(package)
expect(package_file.file_name).to eq('myfile.tar.gz.1') expect(package_file.file_name).to eq(file_name)
expect(package_file.size).to eq(file.size) expect(package_file.size).to eq(file.size)
expect(package_file.file_sha256).to eq(sha256) expect(package_file.file_sha256).to eq(sha256)
end end
...@@ -65,7 +68,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -65,7 +68,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
let(:package_params) { super().merge(status: 'hidden') } let(:package_params) { super().merge(status: 'hidden') }
it 'updates an existing packages status' do it 'updates an existing packages status' do
expect { subject }.to change { package.package_files.count }.by(1) expect { execute_service }.to change { package.package_files.count }.by(1)
.and change { Packages::PackageFileBuildInfo.count }.by(1) .and change { Packages::PackageFileBuildInfo.count }.by(1)
package_file = package.package_files.last package_file = package.package_files.last
...@@ -76,5 +79,32 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -76,5 +79,32 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
end end
it_behaves_like 'assigns build to package file' it_behaves_like 'assigns build to package file'
context 'with existing package' do
before do
create(:package_file, package: package, file_name: file_name)
end
it { expect { execute_service }.to change { project.package_files.count }.by(1) }
context 'when duplicates are not allowed' do
before do
package.project.namespace.package_settings.update!(generic_duplicates_allowed: false)
end
it 'does not allow duplicates' do
expect { execute_service }.to raise_error(::Packages::DuplicatePackageError)
.and change { project.package_files.count }.by(0)
end
context 'when the package name matches the exception regex' do
before do
package.project.namespace.package_settings.update!(generic_duplicate_exception_regex: '.*')
end
it { expect { execute_service }.to change { project.package_files.count }.by(1) }
end
end
end
end end
end end
...@@ -7,6 +7,8 @@ RSpec.shared_examples 'updating the namespace package setting attributes' do |fr ...@@ -7,6 +7,8 @@ RSpec.shared_examples 'updating the namespace package setting attributes' do |fr
expect { subject } expect { subject }
.to change { namespace.package_settings.reload.maven_duplicates_allowed }.from(from[:maven_duplicates_allowed]).to(to[:maven_duplicates_allowed]) .to change { namespace.package_settings.reload.maven_duplicates_allowed }.from(from[:maven_duplicates_allowed]).to(to[:maven_duplicates_allowed])
.and change { namespace.package_settings.reload.maven_duplicate_exception_regex }.from(from[:maven_duplicate_exception_regex]).to(to[:maven_duplicate_exception_regex]) .and change { namespace.package_settings.reload.maven_duplicate_exception_regex }.from(from[:maven_duplicate_exception_regex]).to(to[:maven_duplicate_exception_regex])
.and change { namespace.package_settings.reload.generic_duplicates_allowed }.from(from[:generic_duplicates_allowed]).to(to[:generic_duplicates_allowed])
.and change { namespace.package_settings.reload.generic_duplicate_exception_regex }.from(from[:generic_duplicate_exception_regex]).to(to[:generic_duplicate_exception_regex])
end end
end end
...@@ -26,6 +28,8 @@ RSpec.shared_examples 'creating the namespace package setting' do ...@@ -26,6 +28,8 @@ RSpec.shared_examples 'creating the namespace package setting' do
expect(namespace.package_setting_relation.maven_duplicates_allowed).to eq(package_settings[:maven_duplicates_allowed]) expect(namespace.package_setting_relation.maven_duplicates_allowed).to eq(package_settings[:maven_duplicates_allowed])
expect(namespace.package_setting_relation.maven_duplicate_exception_regex).to eq(package_settings[:maven_duplicate_exception_regex]) expect(namespace.package_setting_relation.maven_duplicate_exception_regex).to eq(package_settings[:maven_duplicate_exception_regex])
expect(namespace.package_setting_relation.generic_duplicates_allowed).to eq(package_settings[:generic_duplicates_allowed])
expect(namespace.package_setting_relation.generic_duplicate_exception_regex).to eq(package_settings[:generic_duplicate_exception_regex])
end end
it_behaves_like 'returning a success' it_behaves_like 'returning a success'
......
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