Commit a39207b3 authored by Sashi's avatar Sashi Committed by Mayra Cabrera

Organize package models by package type

parent 84046205
---
title: Organize package models by package type
merge_request: 31346
author: Sashi Kumar
type: other
...@@ -196,8 +196,8 @@ information like the file `name`, `side`, `sha1`, etc. ...@@ -196,8 +196,8 @@ information like the file `name`, `side`, `sha1`, etc.
If there is specific data necessary to be stored for only one package system support, If there is specific data necessary to be stored for only one package system support,
consider creating a separate metadata model. See `packages_maven_metadata` table consider creating a separate metadata model. See `packages_maven_metadata` table
and `Packages::MavenMetadatum` model as an example for package specific data, and `packages_conan_file_metadata` table and `Packages::Maven::Metadatum` model as an example for package specific data, and `packages_conan_file_metadata` table
and `Packages::ConanFileMetadatum` model as an example for package file specific data. and `Packages::Conan::FileMetadatum` model as an example for package file specific data.
If there is package specific behavior for a given package manager, add those methods to the metadata models and If there is package specific behavior for a given package manager, add those methods to the metadata models and
delegate from the package model. delegate from the package model.
......
# frozen_string_literal: true
module Packages
module Conan
def self.table_name_prefix
'packages_conan_'
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
class Packages::ConanFileMetadatum < ApplicationRecord class Packages::Conan::FileMetadatum < ApplicationRecord
belongs_to :package_file, inverse_of: :conan_file_metadatum belongs_to :package_file, inverse_of: :conan_file_metadatum
validates :package_file, presence: true validates :package_file, presence: true
......
# frozen_string_literal: true # frozen_string_literal: true
class Packages::ConanMetadatum < ApplicationRecord class Packages::Conan::Metadatum < ApplicationRecord
belongs_to :package, -> { where(package_type: :conan) }, inverse_of: :conan_metadatum belongs_to :package, -> { where(package_type: :conan) }, inverse_of: :conan_metadatum
validates :package, presence: true validates :package, presence: true
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
class Packages::DependencyLink < ApplicationRecord class Packages::DependencyLink < ApplicationRecord
belongs_to :package, inverse_of: :dependency_links belongs_to :package, inverse_of: :dependency_links
belongs_to :dependency, inverse_of: :dependency_links, class_name: 'Packages::Dependency' belongs_to :dependency, inverse_of: :dependency_links, class_name: 'Packages::Dependency'
has_one :nuget_metadatum, inverse_of: :dependency_link, class_name: 'Packages::NugetDependencyLinkMetadatum' has_one :nuget_metadatum, inverse_of: :dependency_link, class_name: 'Packages::Nuget::DependencyLinkMetadatum'
validates :package, :dependency, presence: true validates :package, :dependency, presence: true
......
# frozen_string_literal: true
module Packages
module Maven
def self.table_name_prefix
'packages_maven_'
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
class Packages::MavenMetadatum < ApplicationRecord class Packages::Maven::Metadatum < ApplicationRecord
belongs_to :package, -> { where(package_type: :maven) } belongs_to :package, -> { where(package_type: :maven) }
validates :package, presence: true validates :package, presence: true
......
# frozen_string_literal: true
module Packages
module Nuget
def self.table_name_prefix
'packages_nuget_'
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
class Packages::NugetDependencyLinkMetadatum < ApplicationRecord class Packages::Nuget::DependencyLinkMetadatum < ApplicationRecord
self.primary_key = :dependency_link_id self.primary_key = :dependency_link_id
belongs_to :dependency_link, inverse_of: :nuget_metadatum belongs_to :dependency_link, inverse_of: :nuget_metadatum
......
...@@ -9,9 +9,9 @@ class Packages::Package < ApplicationRecord ...@@ -9,9 +9,9 @@ class Packages::Package < ApplicationRecord
has_many :package_files, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :package_files, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :dependency_links, inverse_of: :package, class_name: 'Packages::DependencyLink' has_many :dependency_links, inverse_of: :package, class_name: 'Packages::DependencyLink'
has_many :tags, inverse_of: :package, class_name: 'Packages::Tag' has_many :tags, inverse_of: :package, class_name: 'Packages::Tag'
has_one :conan_metadatum, inverse_of: :package has_one :conan_metadatum, inverse_of: :package, class_name: 'Packages::Conan::Metadatum'
has_one :pypi_metadatum, inverse_of: :package has_one :pypi_metadatum, inverse_of: :package, class_name: 'Packages::Pypi::Metadatum'
has_one :maven_metadatum, inverse_of: :package has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum'
has_one :build_info, inverse_of: :package has_one :build_info, inverse_of: :package
accepts_nested_attributes_for :conan_metadatum accepts_nested_attributes_for :conan_metadatum
......
...@@ -8,7 +8,7 @@ class Packages::PackageFile < ApplicationRecord ...@@ -8,7 +8,7 @@ class Packages::PackageFile < ApplicationRecord
belongs_to :package belongs_to :package
has_one :conan_file_metadatum, inverse_of: :package_file has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum'
accepts_nested_attributes_for :conan_file_metadatum accepts_nested_attributes_for :conan_file_metadatum
...@@ -24,7 +24,7 @@ class Packages::PackageFile < ApplicationRecord ...@@ -24,7 +24,7 @@ class Packages::PackageFile < ApplicationRecord
scope :with_conan_file_type, ->(file_type) do scope :with_conan_file_type, ->(file_type) do
joins(:conan_file_metadatum) joins(:conan_file_metadatum)
.where(packages_conan_file_metadata: { conan_file_type: ::Packages::ConanFileMetadatum.conan_file_types[file_type] }) .where(packages_conan_file_metadata: { conan_file_type: ::Packages::Conan::FileMetadatum.conan_file_types[file_type] })
end end
scope :with_conan_package_reference, ->(conan_package_reference) do scope :with_conan_package_reference, ->(conan_package_reference) do
......
# frozen_string_literal: true
module Packages
module Pypi
def self.table_name_prefix
'packages_pypi_'
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
class Packages::PypiMetadatum < ApplicationRecord class Packages::Pypi::Metadatum < ApplicationRecord
self.primary_key = :package_id self.primary_key = :package_id
belongs_to :package, -> { where(package_type: :pypi) }, inverse_of: :pypi_metadatum belongs_to :package, -> { where(package_type: :pypi) }, inverse_of: :pypi_metadatum
......
...@@ -42,7 +42,7 @@ module Packages ...@@ -42,7 +42,7 @@ module Packages
def search_for_single_package(query) def search_for_single_package(query)
name, version, username, _ = query.split(/[@\/]/) name, version, username, _ = query.split(/[@\/]/)
full_path = Packages::ConanMetadatum.full_path_from(package_username: username) full_path = Packages::Conan::Metadatum.full_path_from(package_username: username)
project = Project.find_by_full_path(full_path) project = Project.find_by_full_path(full_path)
return unless current_user.can?(:read_package, project) return unless current_user.can?(:read_package, project)
......
...@@ -41,7 +41,7 @@ module Packages ...@@ -41,7 +41,7 @@ module Packages
} }
end end
::Gitlab::Database.bulk_insert(::Packages::NugetDependencyLinkMetadatum.table_name, rows.compact) ::Gitlab::Database.bulk_insert(::Packages::Nuget::DependencyLinkMetadatum.table_name, rows.compact)
end end
def raw_dependency_for(dependency) def raw_dependency_for(dependency)
......
...@@ -7,7 +7,7 @@ module Packages ...@@ -7,7 +7,7 @@ module Packages
def execute def execute
::Packages::Package.transaction do ::Packages::Package.transaction do
Packages::PypiMetadatum.upsert( Packages::Pypi::Metadatum.upsert(
package_id: created_package.id, package_id: created_package.id,
required_python: params[:requires_python] required_python: params[:requires_python]
) )
......
...@@ -64,7 +64,7 @@ class Gitlab::Seeder::Packages ...@@ -64,7 +64,7 @@ class Gitlab::Seeder::Packages
params = { params = {
package_name: name, package_name: name,
package_version: version, package_version: version,
package_username: ::Packages::ConanMetadatum.package_username_from(full_path: project.full_path), package_username: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path),
package_channel: 'stable' package_channel: 'stable'
} }
......
...@@ -193,7 +193,7 @@ module API ...@@ -193,7 +193,7 @@ module API
authorize!(:read_package, project) authorize!(:read_package, project)
status 200 status 200
upload_urls = package_upload_urls(::Packages::ConanFileMetadatum::PACKAGE_FILES) upload_urls = package_upload_urls(::Packages::Conan::FileMetadatum::PACKAGE_FILES)
present upload_urls, with: EE::API::Entities::ConanPackage::ConanUploadUrls present upload_urls, with: EE::API::Entities::ConanPackage::ConanUploadUrls
end end
...@@ -206,7 +206,7 @@ module API ...@@ -206,7 +206,7 @@ module API
authorize!(:read_package, project) authorize!(:read_package, project)
status 200 status 200
upload_urls = recipe_upload_urls(::Packages::ConanFileMetadatum::RECIPE_FILES) upload_urls = recipe_upload_urls(::Packages::Conan::FileMetadatum::RECIPE_FILES)
present upload_urls, with: EE::API::Entities::ConanPackage::ConanUploadUrls present upload_urls, with: EE::API::Entities::ConanPackage::ConanUploadUrls
end end
......
...@@ -78,7 +78,7 @@ module API ...@@ -78,7 +78,7 @@ module API
def project def project
strong_memoize(:project) do strong_memoize(:project) do
full_path = ::Packages::ConanMetadatum.full_path_from(package_username: params[:package_username]) full_path = ::Packages::Conan::Metadatum.full_path_from(package_username: params[:package_username])
Project.find_by_full_path(full_path) Project.find_by_full_path(full_path)
end end
end end
...@@ -105,7 +105,7 @@ module API ...@@ -105,7 +105,7 @@ module API
conan_package_reference: params[:conan_package_reference] conan_package_reference: params[:conan_package_reference]
).execute! ).execute!
track_event('pull_package') if params[:file_name] == ::Packages::ConanFileMetadatum::PACKAGE_BINARY track_event('pull_package') if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
present_carrierwave_file!(package_file.file) present_carrierwave_file!(package_file.file)
end end
...@@ -115,7 +115,7 @@ module API ...@@ -115,7 +115,7 @@ module API
end end
def track_push_package_event def track_push_package_event
if params[:file_name] == ::Packages::ConanFileMetadatum::PACKAGE_BINARY && params['file.size'].positive? if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY && params['file.size'].positive?
track_event('push_package') track_event('push_package')
end end
end end
......
...@@ -8,7 +8,7 @@ module EE ...@@ -8,7 +8,7 @@ module EE
class_methods do class_methods do
def conan_file_name_regex def conan_file_name_regex
@conan_file_name_regex ||= @conan_file_name_regex ||=
%r{\A#{(::Packages::ConanFileMetadatum::RECIPE_FILES + ::Packages::ConanFileMetadatum::PACKAGE_FILES).join("|")}\z}.freeze %r{\A#{(::Packages::Conan::FileMetadatum::RECIPE_FILES + ::Packages::Conan::FileMetadatum::PACKAGE_FILES).join("|")}\z}.freeze
end end
def conan_package_reference_regex def conan_package_reference_regex
......
...@@ -71,7 +71,7 @@ FactoryBot.define do ...@@ -71,7 +71,7 @@ FactoryBot.define do
conan_metadatum conan_metadatum
after :build do |package| after :build do |package|
package.conan_metadatum.package_username = Packages::ConanMetadatum.package_username_from( package.conan_metadatum.package_username = Packages::Conan::Metadatum.package_username_from(
full_path: package.project.full_path full_path: package.project.full_path
) )
end end
...@@ -223,7 +223,7 @@ FactoryBot.define do ...@@ -223,7 +223,7 @@ FactoryBot.define do
end end
end end
factory :maven_metadatum, class: 'Packages::MavenMetadatum' do factory :maven_metadatum, class: 'Packages::Maven::Metadatum' do
association :package, package_type: :maven association :package, package_type: :maven
path { 'my/company/app/my-app/1.0-SNAPSHOT' } path { 'my/company/app/my-app/1.0-SNAPSHOT' }
app_group { 'my.company.app' } app_group { 'my.company.app' }
...@@ -231,18 +231,18 @@ FactoryBot.define do ...@@ -231,18 +231,18 @@ FactoryBot.define do
app_version { '1.0-SNAPSHOT' } app_version { '1.0-SNAPSHOT' }
end end
factory :conan_metadatum, class: 'Packages::ConanMetadatum' do factory :conan_metadatum, class: 'Packages::Conan::Metadatum' do
association :package, factory: [:conan_package, :without_loaded_metadatum] association :package, factory: [:conan_package, :without_loaded_metadatum]
package_username { 'username' } package_username { 'username' }
package_channel { 'stable' } package_channel { 'stable' }
end end
factory :pypi_metadatum, class: 'Packages::PypiMetadatum' do factory :pypi_metadatum, class: 'Packages::Pypi::Metadatum' do
association :package, package_type: :pypi association :package, package_type: :pypi
required_python { '>=2.7' } required_python { '>=2.7' }
end end
factory :conan_file_metadatum, class: 'Packages::ConanFileMetadatum' do factory :conan_file_metadatum, class: 'Packages::Conan::FileMetadatum' do
package_file package_file
recipe_revision { '0' } recipe_revision { '0' }
...@@ -274,7 +274,7 @@ FactoryBot.define do ...@@ -274,7 +274,7 @@ FactoryBot.define do
end end
end end
factory :nuget_dependency_link_metadatum, class: 'Packages::NugetDependencyLinkMetadatum' do factory :nuget_dependency_link_metadatum, class: 'Packages::Nuget::DependencyLinkMetadatum' do
target_framework { '.NETStandard2.0' } target_framework { '.NETStandard2.0' }
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::ConanFileMetadatum, type: :model do RSpec.describe Packages::Conan::FileMetadatum, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:package_file) } it { is_expected.to belong_to(:package_file) }
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::ConanMetadatum, type: :model do RSpec.describe Packages::Conan::Metadatum, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:package) } it { is_expected.to belong_to(:package) }
end end
......
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::MavenMetadatum, type: :model do RSpec.describe Packages::Maven::Metadatum, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:package) } it { is_expected.to belong_to(:package) }
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::NugetDependencyLinkMetadatum, type: :model do RSpec.describe Packages::Nuget::DependencyLinkMetadatum, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:dependency_link) } it { is_expected.to belong_to(:dependency_link) }
end end
......
...@@ -267,7 +267,7 @@ RSpec.describe Packages::Package, type: :model do ...@@ -267,7 +267,7 @@ RSpec.describe Packages::Package, type: :model do
describe '.with_conan_username' do describe '.with_conan_username' do
subject do subject do
described_class.with_conan_username( described_class.with_conan_username(
Packages::ConanMetadatum.package_username_from(full_path: package.project.full_path) Packages::Conan::Metadatum.package_username_from(full_path: package.project.full_path)
) )
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::Pypi::Metadatum, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:package) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:package) }
end
end
...@@ -218,7 +218,7 @@ describe API::ConanPackages do ...@@ -218,7 +218,7 @@ describe API::ConanPackages do
shared_examples 'rejects recipe for not found package' do shared_examples 'rejects recipe for not found package' do
context 'with invalid recipe path' do context 'with invalid recipe path' do
let(:recipe_path) do let(:recipe_path) do
'aa/bb/%{project}/ccc' % { project: ::Packages::ConanMetadatum.package_username_from(full_path: project.full_path) } 'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
end end
it 'returns not found' do it 'returns not found' do
...@@ -232,13 +232,13 @@ describe API::ConanPackages do ...@@ -232,13 +232,13 @@ describe API::ConanPackages do
shared_examples 'empty recipe for not found package' do shared_examples 'empty recipe for not found package' do
context 'with invalid recipe url' do context 'with invalid recipe url' do
let(:recipe_path) do let(:recipe_path) do
'aa/bb/%{project}/ccc' % { project: ::Packages::ConanMetadatum.package_username_from(full_path: project.full_path) } 'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
end end
it 'returns not found' do it 'returns not found' do
allow(::Packages::Conan::PackagePresenter).to receive(:new) allow(::Packages::Conan::PackagePresenter).to receive(:new)
.with( .with(
'aa/bb@%{project}/ccc' % { project: ::Packages::ConanMetadatum.package_username_from(full_path: project.full_path) }, 'aa/bb@%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) },
user, user,
project, project,
any_args any_args
...@@ -568,7 +568,7 @@ describe API::ConanPackages do ...@@ -568,7 +568,7 @@ describe API::ConanPackages do
it_behaves_like 'a project is not found' it_behaves_like 'a project is not found'
context 'tracking the conan_package.tgz download' do context 'tracking the conan_package.tgz download' do
let(:package_file) { package.package_files.find_by(file_name: ::Packages::ConanFileMetadatum::PACKAGE_BINARY) } let(:package_file) { package.package_files.find_by(file_name: ::Packages::Conan::FileMetadatum::PACKAGE_BINARY) }
it_behaves_like 'a gitlab tracking event', described_class.name, 'pull_package' it_behaves_like 'a gitlab tracking event', described_class.name, 'pull_package'
end end
...@@ -802,7 +802,7 @@ describe API::ConanPackages do ...@@ -802,7 +802,7 @@ describe API::ConanPackages do
it_behaves_like 'rejects invalid recipe' it_behaves_like 'rejects invalid recipe'
it_behaves_like 'uploads a package file' it_behaves_like 'uploads a package file'
context 'tracking the conan_package.tgz upload' do context 'tracking the conan_package.tgz upload' do
let(:file_name) { ::Packages::ConanFileMetadatum::PACKAGE_BINARY } let(:file_name) { ::Packages::Conan::FileMetadatum::PACKAGE_BINARY }
it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package' it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package'
end end
......
...@@ -517,7 +517,7 @@ describe API::MavenPackages do ...@@ -517,7 +517,7 @@ describe API::MavenPackages do
it 'creates package and stores package file' do it 'creates package and stores package file' do
expect { upload_file_with_token(params) }.to change { project.packages.count }.by(1) expect { upload_file_with_token(params) }.to change { project.packages.count }.by(1)
.and change { Packages::MavenMetadatum.count }.by(1) .and change { Packages::Maven::Metadatum.count }.by(1)
.and change { Packages::PackageFile.count }.by(1) .and change { Packages::PackageFile.count }.by(1)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
......
...@@ -13,7 +13,7 @@ describe Packages::Conan::CreatePackageService do ...@@ -13,7 +13,7 @@ describe Packages::Conan::CreatePackageService do
{ {
package_name: 'my-pkg', package_name: 'my-pkg',
package_version: '1.0.0', package_version: '1.0.0',
package_username: ::Packages::ConanMetadatum.package_username_from(full_path: project.full_path), package_username: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path),
package_channel: 'stable' package_channel: 'stable'
} }
end end
......
...@@ -12,7 +12,7 @@ describe Packages::Nuget::CreateDependencyService do ...@@ -12,7 +12,7 @@ describe Packages::Nuget::CreateDependencyService do
expect { subject } expect { subject }
.to change { Packages::Dependency.count }.by(dependency_count) .to change { Packages::Dependency.count }.by(dependency_count)
.and change { Packages::DependencyLink.count }.by(dependency_link_count) .and change { Packages::DependencyLink.count }.by(dependency_link_count)
.and change { Packages::NugetDependencyLinkMetadatum.count }.by(dependencies_with_metadata.size) .and change { Packages::Nuget::DependencyLinkMetadatum.count }.by(dependencies_with_metadata.size)
expect(expected_dependency_names).to contain_exactly(*dependency_names) expect(expected_dependency_names).to contain_exactly(*dependency_names)
expect(package.dependency_links.map(&:dependency_type).uniq).to contain_exactly('dependencies') expect(package.dependency_links.map(&:dependency_type).uniq).to contain_exactly('dependencies')
......
...@@ -37,7 +37,7 @@ describe Packages::Nuget::UpdatePackageFromMetadataService do ...@@ -37,7 +37,7 @@ describe Packages::Nuget::UpdatePackageFromMetadataService do
.to change { ::Packages::Package.count }.by(-1) .to change { ::Packages::Package.count }.by(-1)
.and change { Packages::Dependency.count }.by(0) .and change { Packages::Dependency.count }.by(0)
.and change { Packages::DependencyLink.count }.by(0) .and change { Packages::DependencyLink.count }.by(0)
.and change { Packages::NugetDependencyLinkMetadatum.count }.by(0) .and change { Packages::Nuget::DependencyLinkMetadatum.count }.by(0)
expect(package_file.reload.file_name).to eq(package_file_name) expect(package_file.reload.file_name).to eq(package_file_name)
expect(package_file.package).to eq(existing_package) expect(package_file.package).to eq(existing_package)
end end
...@@ -60,7 +60,7 @@ describe Packages::Nuget::UpdatePackageFromMetadataService do ...@@ -60,7 +60,7 @@ describe Packages::Nuget::UpdatePackageFromMetadataService do
.to change { ::Packages::Package.count }.by(1) .to change { ::Packages::Package.count }.by(1)
.and change { Packages::Dependency.count }.by(4) .and change { Packages::Dependency.count }.by(4)
.and change { Packages::DependencyLink.count }.by(4) .and change { Packages::DependencyLink.count }.by(4)
.and change { Packages::NugetDependencyLinkMetadatum.count }.by(2) .and change { Packages::Nuget::DependencyLinkMetadatum.count }.by(2)
expect(package.reload.name).to eq(package_name) expect(package.reload.name).to eq(package_name)
expect(package.version).to eq(package_version) expect(package.version).to eq(package_version)
......
...@@ -6,7 +6,7 @@ RSpec.shared_examples 'PyPi package creation' do |user_type, status, add_member ...@@ -6,7 +6,7 @@ RSpec.shared_examples 'PyPi package creation' do |user_type, status, add_member
expect { subject } expect { subject }
.to change { project.packages.pypi.count }.by(1) .to change { project.packages.pypi.count }.by(1)
.and change { Packages::PackageFile.count }.by(1) .and change { Packages::PackageFile.count }.by(1)
.and change { Packages::PypiMetadatum.count }.by(1) .and change { Packages::Pypi::Metadatum.count }.by(1)
expect(response).to have_gitlab_http_status(status) expect(response).to have_gitlab_http_status(status)
package = project.reload.packages.pypi.last package = project.reload.packages.pypi.last
......
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