Commit a1f81a88 authored by Steve Abrams's avatar Steve Abrams

Packages and package file build_infos

Create a new relationship between package_files and
pipelines named package_file_build_infos.

Change existing packages_build_infos relationship from
1:1 to 1:many, removing the unique index.
parent f298a22b
# frozen_string_literal: true # frozen_string_literal: true
class Packages::BuildInfo < ApplicationRecord class Packages::BuildInfo < ApplicationRecord
belongs_to :package, inverse_of: :build_info belongs_to :package, inverse_of: :build_infos
belongs_to :pipeline, class_name: 'Ci::Pipeline' belongs_to :pipeline, class_name: 'Ci::Pipeline'
end end
...@@ -3,6 +3,7 @@ class Packages::Package < ApplicationRecord ...@@ -3,6 +3,7 @@ class Packages::Package < ApplicationRecord
include Sortable include Sortable
include Gitlab::SQL::Pattern include Gitlab::SQL::Pattern
include UsageStatistics include UsageStatistics
include Gitlab::Utils::StrongMemoize
belongs_to :project belongs_to :project
belongs_to :creator, class_name: 'User' belongs_to :creator, class_name: 'User'
...@@ -16,7 +17,8 @@ class Packages::Package < ApplicationRecord ...@@ -16,7 +17,8 @@ class Packages::Package < ApplicationRecord
has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum' has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum'
has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum' has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum'
has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum' has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum'
has_one :build_info, inverse_of: :package has_many :build_infos, inverse_of: :package
has_many :pipelines, through: :build_infos
accepts_nested_attributes_for :conan_metadatum accepts_nested_attributes_for :conan_metadatum
accepts_nested_attributes_for :maven_metadatum accepts_nested_attributes_for :maven_metadatum
...@@ -59,7 +61,7 @@ class Packages::Package < ApplicationRecord ...@@ -59,7 +61,7 @@ class Packages::Package < ApplicationRecord
scope :with_version, ->(version) { where(version: version) } scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) } scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) } scope :with_package_type, ->(package_type) { where(package_type: package_type) }
scope :including_build_info, -> { includes(build_info: { pipeline: :user }) } scope :including_build_info, -> { includes(pipelines: :user) }
scope :including_project_route, -> { includes(project: { namespace: :route }) } scope :including_project_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) } scope :including_tags, -> { includes(:tags) }
...@@ -166,8 +168,16 @@ class Packages::Package < ApplicationRecord ...@@ -166,8 +168,16 @@ class Packages::Package < ApplicationRecord
.order(:version) .order(:version)
end end
# Technical debt: to be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/281937
def original_build_info
strong_memoize(:original_build_info) do
build_infos.first
end
end
# Technical debt: to be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/281937
def pipeline def pipeline
build_info&.pipeline original_build_info&.pipeline
end end
def tag_names def tag_names
......
...@@ -8,6 +8,8 @@ class Packages::PackageFile < ApplicationRecord ...@@ -8,6 +8,8 @@ class Packages::PackageFile < ApplicationRecord
belongs_to :package belongs_to :package
has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum' has_one :conan_file_metadatum, inverse_of: :package_file, class_name: 'Packages::Conan::FileMetadatum'
has_many :package_file_build_infos, inverse_of: :package_file, class_name: 'Packages::PackageFileBuildInfo'
has_many :pipelines, through: :package_file_build_infos
accepts_nested_attributes_for :conan_file_metadatum accepts_nested_attributes_for :conan_file_metadatum
......
# frozen_string_literal: true
class Packages::PackageFileBuildInfo < ApplicationRecord
belongs_to :package_file, inverse_of: :package_file_build_infos
belongs_to :pipeline, class_name: 'Ci::Pipeline'
end
...@@ -29,7 +29,8 @@ module Packages ...@@ -29,7 +29,8 @@ module Packages
package_detail[:composer_metadatum] = @package.composer_metadatum if @package.composer_metadatum package_detail[:composer_metadatum] = @package.composer_metadatum if @package.composer_metadatum
package_detail[:conan_metadatum] = @package.conan_metadatum if @package.conan_metadatum package_detail[:conan_metadatum] = @package.conan_metadatum if @package.conan_metadatum
package_detail[:dependency_links] = @package.dependency_links.map(&method(:build_dependency_links)) package_detail[:dependency_links] = @package.dependency_links.map(&method(:build_dependency_links))
package_detail[:pipeline] = build_pipeline_info(@package.build_info.pipeline) if @package.build_info package_detail[:pipeline] = build_pipeline_info(@package.pipeline) if @package.pipeline
package_detail[:pipelines] = build_pipeline_infos(@package.pipelines) if @package.pipelines.present?
package_detail package_detail
end end
...@@ -37,12 +38,20 @@ module Packages ...@@ -37,12 +38,20 @@ module Packages
private private
def build_package_file_view(package_file) def build_package_file_view(package_file)
{ file_view = {
created_at: package_file.created_at, created_at: package_file.created_at,
download_path: package_file.download_path, download_path: package_file.download_path,
file_name: package_file.file_name, file_name: package_file.file_name,
size: package_file.size size: package_file.size
} }
file_view[:pipelines] = build_pipeline_infos(package_file.pipelines) if package_file.pipelines.present?
file_view
end
def build_pipeline_infos(pipeline_infos)
pipeline_infos.map { |pipeline_info| build_pipeline_info(pipeline_info) }
end end
def build_pipeline_info(pipeline_info) def build_pipeline_info(pipeline_info)
......
...@@ -9,7 +9,7 @@ module Packages ...@@ -9,7 +9,7 @@ module Packages
end end
def execute def execute
package.package_files.create!( package_file = package.package_files.build(
file: params[:file], file: params[:file],
size: params[:size], size: params[:size],
file_name: params[:file_name], file_name: params[:file_name],
...@@ -17,6 +17,13 @@ module Packages ...@@ -17,6 +17,13 @@ module Packages
file_sha256: params[:file_sha256], file_sha256: params[:file_sha256],
file_md5: params[:file_md5] file_md5: params[:file_md5]
) )
if params[:build].present?
package_file.package_file_build_infos << package_file.package_file_build_infos.build(pipeline: params[:build].pipeline)
end
package_file.save!
package_file
end end
end end
end end
...@@ -28,7 +28,8 @@ module Packages ...@@ -28,7 +28,8 @@ module Packages
file: params[:file], file: params[:file],
size: params[:file].size, size: params[:file].size,
file_sha256: params[:file].sha256, file_sha256: params[:file].sha256,
file_name: params[:file_name] file_name: params[:file_name],
build: params[:build]
} }
::Packages::CreatePackageFileService.new(package, file_params).execute ::Packages::CreatePackageFileService.new(package, file_params).execute
......
...@@ -6,7 +6,7 @@ module Packages ...@@ -6,7 +6,7 @@ module Packages
def execute def execute
find_or_create_package!(::Packages::Package.package_types['generic']) do |package| find_or_create_package!(::Packages::Package.package_types['generic']) do |package|
if params[:build].present? if params[:build].present?
package.build_info = Packages::BuildInfo.new(pipeline: params[:build].pipeline) package.build_infos.new(pipeline: params[:build].pipeline)
end end
end end
end end
......
...@@ -6,7 +6,7 @@ module Packages ...@@ -6,7 +6,7 @@ module Packages
app_group, _, app_name = params[:name].rpartition('/') app_group, _, app_name = params[:name].rpartition('/')
app_group.tr!('/', '.') app_group.tr!('/', '.')
package = create_package!(:maven, create_package!(:maven,
maven_metadatum_attributes: { maven_metadatum_attributes: {
path: params[:path], path: params[:path],
app_group: app_group, app_group: app_group,
...@@ -14,11 +14,6 @@ module Packages ...@@ -14,11 +14,6 @@ module Packages
app_version: params[:version] app_version: params[:version]
} }
) )
build = params[:build]
package.create_build_info!(pipeline: build.pipeline) if build.present?
package
end end
end end
end end
......
...@@ -38,8 +38,7 @@ module Packages ...@@ -38,8 +38,7 @@ module Packages
package_params = { package_params = {
name: package_name, name: package_name,
path: params[:path], path: params[:path],
version: version, version: version
build: params[:build]
} }
package = package =
...@@ -47,6 +46,8 @@ module Packages ...@@ -47,6 +46,8 @@ module Packages
.execute .execute
end end
package.build_infos.create!(pipeline: params[:build].pipeline) if params[:build].present?
package package
end end
end end
......
...@@ -18,7 +18,7 @@ module Packages ...@@ -18,7 +18,7 @@ module Packages
package = create_package!(:npm, name: name, version: version) package = create_package!(:npm, name: name, version: version)
if build.present? if build.present?
package.create_build_info!(pipeline: build.pipeline) package.build_infos.create!(pipeline: build.pipeline)
end end
::Packages::CreatePackageFileService.new(package, file_params).execute ::Packages::CreatePackageFileService.new(package, file_params).execute
...@@ -75,7 +75,8 @@ module Packages ...@@ -75,7 +75,8 @@ module Packages
file: CarrierWaveStringFile.new(Base64.decode64(attachment['data'])), file: CarrierWaveStringFile.new(Base64.decode64(attachment['data'])),
size: attachment['length'], size: attachment['length'],
file_sha1: version_data[:dist][:shasum], file_sha1: version_data[:dist][:shasum],
file_name: package_file_name file_name: package_file_name,
build: params[:build]
} }
end end
......
---
title: Associate multiple pipelines with packages and package files
merge_request: 44348
author:
type: added
# frozen_string_literal: true
class CreatePackagesPackageFileBuildInfos < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
unless table_exists?(:packages_package_file_build_infos)
with_lock_retries do
create_table :packages_package_file_build_infos do |t|
t.references :package_file, index: true,
null: false,
foreign_key: { to_table: :packages_package_files, on_delete: :cascade },
type: :bigint
t.references :pipeline, index: true,
null: true,
foreign_key: { to_table: :ci_pipelines, on_delete: :nullify },
type: :bigint
end
end
end
end
def down
with_lock_retries do
drop_table :packages_package_file_build_infos
end
end
end
# frozen_string_literal: true
class UpdatePackagesBuildInfosIndex < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
NEW_INDEX_NAME = 'idx_packages_build_infos_on_package_id'
OLD_INDEX_NAME = 'index_packages_build_infos_on_package_id'
def up
add_concurrent_index :packages_build_infos, :package_id, name: NEW_INDEX_NAME
remove_concurrent_index_by_name :packages_build_infos, OLD_INDEX_NAME
end
def down
# No op. It is possible records would validate the UNIQUE constraint, so it
# cannot be added back to the index.
end
end
a3117169b472fffd6302a4da17850a11474c196fd06ebeb3f6b28705d59c74ba
\ No newline at end of file
af006a3c01620c258a253b5c9ccca6faa4cb46a97dddbfeecc0ecc4454eb46e6
\ No newline at end of file
...@@ -14451,6 +14451,21 @@ CREATE TABLE packages_nuget_metadata ( ...@@ -14451,6 +14451,21 @@ CREATE TABLE packages_nuget_metadata (
CONSTRAINT packages_nuget_metadata_project_url_constraint CHECK ((char_length(project_url) <= 255)) CONSTRAINT packages_nuget_metadata_project_url_constraint CHECK ((char_length(project_url) <= 255))
); );
CREATE TABLE packages_package_file_build_infos (
id bigint NOT NULL,
package_file_id bigint NOT NULL,
pipeline_id bigint
);
CREATE SEQUENCE packages_package_file_build_infos_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE packages_package_file_build_infos_id_seq OWNED BY packages_package_file_build_infos.id;
CREATE TABLE packages_package_files ( CREATE TABLE packages_package_files (
id bigint NOT NULL, id bigint NOT NULL,
package_id bigint NOT NULL, package_id bigint NOT NULL,
...@@ -18057,6 +18072,8 @@ ALTER TABLE ONLY packages_events ALTER COLUMN id SET DEFAULT nextval('packages_e ...@@ -18057,6 +18072,8 @@ ALTER TABLE ONLY packages_events ALTER COLUMN id SET DEFAULT nextval('packages_e
ALTER TABLE ONLY packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('packages_maven_metadata_id_seq'::regclass); ALTER TABLE ONLY packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('packages_maven_metadata_id_seq'::regclass);
ALTER TABLE ONLY packages_package_file_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_package_file_build_infos_id_seq'::regclass);
ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('packages_package_files_id_seq'::regclass); ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('packages_package_files_id_seq'::regclass);
ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass); ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass);
...@@ -19342,6 +19359,9 @@ ALTER TABLE ONLY packages_nuget_dependency_link_metadata ...@@ -19342,6 +19359,9 @@ ALTER TABLE ONLY packages_nuget_dependency_link_metadata
ALTER TABLE ONLY packages_nuget_metadata ALTER TABLE ONLY packages_nuget_metadata
ADD CONSTRAINT packages_nuget_metadata_pkey PRIMARY KEY (package_id); ADD CONSTRAINT packages_nuget_metadata_pkey PRIMARY KEY (package_id);
ALTER TABLE ONLY packages_package_file_build_infos
ADD CONSTRAINT packages_package_file_build_infos_pkey PRIMARY KEY (id);
ALTER TABLE ONLY packages_package_files ALTER TABLE ONLY packages_package_files
ADD CONSTRAINT packages_package_files_pkey PRIMARY KEY (id); ADD CONSTRAINT packages_package_files_pkey PRIMARY KEY (id);
...@@ -20015,6 +20035,8 @@ CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_c ...@@ -20015,6 +20035,8 @@ CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_c
CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name); CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type); CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON packages_dependency_links USING btree (package_id, dependency_id, dependency_type); CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON packages_dependency_links USING btree (package_id, dependency_id, dependency_type);
...@@ -21407,8 +21429,6 @@ CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_ ...@@ -21407,8 +21429,6 @@ CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_
CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list_id ON operations_strategies_user_lists USING btree (strategy_id, user_list_id); CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list_id ON operations_strategies_user_lists USING btree (strategy_id, user_list_id);
CREATE UNIQUE INDEX index_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id); CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha); CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
...@@ -21429,6 +21449,10 @@ CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_ ...@@ -21429,6 +21449,10 @@ CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_
CREATE UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_generic ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 7); CREATE UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_generic ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 7);
CREATE INDEX index_packages_package_file_build_infos_on_package_file_id ON packages_package_file_build_infos USING btree (package_file_id);
CREATE INDEX index_packages_package_file_build_infos_on_pipeline_id ON packages_package_file_build_infos USING btree (pipeline_id);
CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store); CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store);
CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name); CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name);
...@@ -23589,6 +23613,9 @@ ALTER TABLE ONLY snippet_user_mentions ...@@ -23589,6 +23613,9 @@ ALTER TABLE ONLY snippet_user_mentions
ALTER TABLE ONLY clusters_applications_helm ALTER TABLE ONLY clusters_applications_helm
ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
ALTER TABLE ONLY packages_package_file_build_infos
ADD CONSTRAINT fk_rails_3e3f630188 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
ALTER TABLE ONLY epic_user_mentions ALTER TABLE ONLY epic_user_mentions
ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
...@@ -23973,6 +24000,9 @@ ALTER TABLE ONLY merge_request_diff_details ...@@ -23973,6 +24000,9 @@ ALTER TABLE ONLY merge_request_diff_details
ALTER TABLE ONLY clusters_applications_crossplane ALTER TABLE ONLY clusters_applications_crossplane
ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
ALTER TABLE ONLY packages_package_file_build_infos
ADD CONSTRAINT fk_rails_871ca3ae21 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_runner_namespaces ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_8767676b7a FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE CASCADE; ADD CONSTRAINT fk_rails_8767676b7a FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE CASCADE;
......
...@@ -93,9 +93,10 @@ GET /groups/:id/packages ...@@ -93,9 +93,10 @@ GET /groups/:id/packages
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true"
``` ```
CAUTION: **Deprecation:** > **Deprecation:**
> The `build_info` attribute in the response is deprecated in favour of `pipeline`. >
> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040). > The `pipeline` attribute in the response is deprecated in favor of `pipelines`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44348) in GitLab 13.6. Both are available until 13.7.
> The `build_info` attribute in the response is deprecated in favor of `pipeline`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) in GitLab 12.10.
Example response: Example response:
...@@ -111,7 +112,8 @@ Example response: ...@@ -111,7 +112,8 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1" "delete_api_path": "/namespace1/project1/-/packages/1"
}, },
"created_at": "2019-11-27T03:37:38.711Z", "created_at": "2019-11-27T03:37:38.711Z",
"pipeline": { "pipelines": [
{
"id": 123, "id": 123,
"status": "pending", "status": "pending",
"ref": "new-pipeline", "ref": "new-pipeline",
...@@ -124,6 +126,7 @@ Example response: ...@@ -124,6 +126,7 @@ Example response:
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
} }
} }
]
}, },
{ {
"id": 2, "id": 2,
...@@ -135,7 +138,8 @@ Example response: ...@@ -135,7 +138,8 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1" "delete_api_path": "/namespace1/project1/-/packages/1"
}, },
"created_at": "2019-11-27T03:37:38.711Z", "created_at": "2019-11-27T03:37:38.711Z",
"pipeline": { "pipelines": [
{
"id": 123, "id": 123,
"status": "pending", "status": "pending",
"ref": "new-pipeline", "ref": "new-pipeline",
...@@ -148,6 +152,7 @@ Example response: ...@@ -148,6 +152,7 @@ Example response:
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
} }
} }
]
} }
] ]
``` ```
...@@ -178,9 +183,10 @@ GET /projects/:id/packages/:package_id ...@@ -178,9 +183,10 @@ GET /projects/:id/packages/:package_id
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id" curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id"
``` ```
CAUTION: **Deprecation:** > **Deprecation:**
> The `build_info` attribute in the response is deprecated in favour of `pipeline`. >
> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040). > The `pipeline` attribute in the response is deprecated in favor of `pipelines`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44348) in GitLab 13.6. Both are available until 13.7.
> The `build_info` attribute in the response is deprecated in favor of `pipeline`, which was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040) in GitLab 12.10.
Example response: Example response:
...@@ -195,7 +201,8 @@ Example response: ...@@ -195,7 +201,8 @@ Example response:
"delete_api_path": "/namespace1/project1/-/packages/1" "delete_api_path": "/namespace1/project1/-/packages/1"
}, },
"created_at": "2019-11-27T03:37:38.711Z", "created_at": "2019-11-27T03:37:38.711Z",
"pipeline": { "pipelines": [
{
"id": 123, "id": 123,
"status": "pending", "status": "pending",
"ref": "new-pipeline", "ref": "new-pipeline",
...@@ -207,13 +214,15 @@ Example response: ...@@ -207,13 +214,15 @@ Example response:
"name": "Administrator", "name": "Administrator",
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
} }
}, }
],
"versions": [ "versions": [
{ {
"id":2, "id":2,
"version":"2.0-SNAPSHOT", "version":"2.0-SNAPSHOT",
"created_at":"2020-04-28T04:42:11.573Z", "created_at":"2020-04-28T04:42:11.573Z",
"pipeline": { "pipelines": [
{
"id": 234, "id": 234,
"status": "pending", "status": "pending",
"ref": "new-pipeline", "ref": "new-pipeline",
...@@ -226,6 +235,7 @@ Example response: ...@@ -226,6 +235,7 @@ Example response:
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
} }
} }
]
} }
] ]
} }
...@@ -266,7 +276,22 @@ Example response: ...@@ -266,7 +276,22 @@ Example response:
"file_name": "my-app-1.5-20181107.152550-1.jar", "file_name": "my-app-1.5-20181107.152550-1.jar",
"size": 2421, "size": 2421,
"file_md5": "58e6a45a629910c6ff99145a688971ac", "file_md5": "58e6a45a629910c6ff99145a688971ac",
"file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe" "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe",
"pipelines": [
{
"id": 123,
"status": "pending",
"ref": "new-pipeline",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"web_url": "https://example.com/foo/bar/pipelines/47",
"created_at": "2016-08-11T11:28:34.085Z",
"updated_at": "2016-08-11T11:32:35.169Z",
"user": {
"name": "Administrator",
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
}
}
]
}, },
{ {
"id": 26, "id": 26,
......
...@@ -38,7 +38,8 @@ module API ...@@ -38,7 +38,8 @@ module API
expose :project_path, if: ->(obj, opts) { opts[:group] && Ability.allowed?(opts[:user], :read_project, obj.project) } expose :project_path, if: ->(obj, opts) { opts[:group] && Ability.allowed?(opts[:user], :read_project, obj.project) }
expose :tags expose :tags
expose :pipeline, if: ->(package) { package.build_info }, using: Package::Pipeline expose :pipeline, if: ->(package) { package.original_build_info }, using: Package::Pipeline
expose :pipelines, if: ->(package) { package.pipelines.present? }, using: Package::Pipeline
expose :versions, using: ::API::Entities::PackageVersion, unless: ->(_, opts) { opts[:collection] } expose :versions, using: ::API::Entities::PackageVersion, unless: ->(_, opts) { opts[:collection] }
......
...@@ -6,6 +6,7 @@ module API ...@@ -6,6 +6,7 @@ module API
expose :id, :package_id, :created_at expose :id, :package_id, :created_at
expose :file_name, :size expose :file_name, :size
expose :file_md5, :file_sha1 expose :file_md5, :file_sha1
expose :pipelines, if: ->(package_file) { package_file.pipelines.present? }, using: Package::Pipeline
end end
end end
end end
...@@ -8,7 +8,7 @@ module API ...@@ -8,7 +8,7 @@ module API
expose :created_at expose :created_at
expose :tags expose :tags
expose :pipeline, if: ->(package) { package.build_info }, using: Package::Pipeline expose :pipeline, if: ->(package) { package.original_build_info }, using: Package::Pipeline
end end
end end
end end
...@@ -246,7 +246,7 @@ module API ...@@ -246,7 +246,7 @@ module API
file_md5: params['file.md5'] file_md5: params['file.md5']
} }
::Packages::CreatePackageFileService.new(package, file_params).execute ::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job)).execute
end end
end end
end end
......
...@@ -147,10 +147,6 @@ FactoryBot.define do ...@@ -147,10 +147,6 @@ FactoryBot.define do
composer_json { { name: 'foo' } } composer_json { { name: 'foo' } }
end end
factory :package_build_info, class: 'Packages::BuildInfo' do
package
end
factory :maven_metadatum, class: 'Packages::Maven::Metadatum' 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' }
......
# frozen_string_literal: true
FactoryBot.define do
factory :package_build_info, class: 'Packages::BuildInfo' do
package
trait :with_pipeline do
association :pipeline, factory: [:ci_pipeline, :with_job]
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :package_file_build_info, class: 'Packages::PackageFileBuildInfo' do
package_file
trait :with_pipeline do
association :pipeline, factory: [:ci_pipeline, :with_job]
end
end
end
...@@ -7,7 +7,10 @@ ...@@ -7,7 +7,10 @@
"id": { "type": "integer" }, "id": { "type": "integer" },
"package_id": { "type": "integer" }, "package_id": { "type": "integer" },
"file_name": { "type": "string" }, "file_name": { "type": "string" },
"file_sha1": { "type": "string" } "file_sha1": { "type": "string" },
"pipelines": {
"items": { "$ref": "../pipeline.json" }
}
} }
} }
} }
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
"name": { "type": "string" }, "name": { "type": "string" },
"version": { "type": "string" }, "version": { "type": "string" },
"package_type": { "type": "string" }, "package_type": { "type": "string" },
"pipeline": { "$ref": "../pipeline.json" } "pipeline": { "$ref": "../pipeline.json" },
"pipelines": {
"items": { "$ref": "../pipeline.json" }
}
} }
} }
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::BuildInfo, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:package) }
it { is_expected.to belong_to(:pipeline) }
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Packages::PackageFileBuildInfo, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:package_file) }
it { is_expected.to belong_to(:pipeline) }
end
end
...@@ -5,6 +5,8 @@ RSpec.describe Packages::PackageFile, type: :model do ...@@ -5,6 +5,8 @@ RSpec.describe Packages::PackageFile, type: :model do
describe 'relationships' do describe 'relationships' do
it { is_expected.to belong_to(:package) } it { is_expected.to belong_to(:package) }
it { is_expected.to have_one(:conan_file_metadatum) } it { is_expected.to have_one(:conan_file_metadatum) }
it { is_expected.to have_many(:package_file_build_infos).inverse_of(:package_file) }
it { is_expected.to have_many(:pipelines).through(:package_file_build_infos) }
end end
describe 'validations' do describe 'validations' do
......
...@@ -10,6 +10,8 @@ RSpec.describe Packages::Package, type: :model do ...@@ -10,6 +10,8 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to have_many(:package_files).dependent(:destroy) } it { is_expected.to have_many(:package_files).dependent(:destroy) }
it { is_expected.to have_many(:dependency_links).inverse_of(:package) } it { is_expected.to have_many(:dependency_links).inverse_of(:package) }
it { is_expected.to have_many(:tags).inverse_of(:package) } it { is_expected.to have_many(:tags).inverse_of(:package) }
it { is_expected.to have_many(:build_infos).inverse_of(:package) }
it { is_expected.to have_many(:pipelines).through(:build_infos) }
it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) } it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) } it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) } it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) }
...@@ -580,7 +582,7 @@ RSpec.describe Packages::Package, type: :model do ...@@ -580,7 +582,7 @@ RSpec.describe Packages::Package, type: :model do
end end
describe '#pipeline' do describe '#pipeline' do
let_it_be(:package) { create(:maven_package) } let_it_be_with_refind(:package) { create(:maven_package) }
context 'package without pipeline' do context 'package without pipeline' do
it 'returns nil if there is no pipeline' do it 'returns nil if there is no pipeline' do
...@@ -592,7 +594,7 @@ RSpec.describe Packages::Package, type: :model do ...@@ -592,7 +594,7 @@ RSpec.describe Packages::Package, type: :model do
let_it_be(:pipeline) { create(:ci_pipeline) } let_it_be(:pipeline) { create(:ci_pipeline) }
before do before do
package.create_build_info!(pipeline: pipeline) package.build_infos.create!(pipeline: pipeline)
end end
it 'returns the pipeline' do it 'returns the pipeline' do
...@@ -637,4 +639,23 @@ RSpec.describe Packages::Package, type: :model do ...@@ -637,4 +639,23 @@ RSpec.describe Packages::Package, type: :model do
end end
end end
end end
describe '#original_build_info' do
let_it_be_with_refind(:package) { create(:npm_package) }
context 'without build_infos' do
it 'returns nil' do
expect(package.original_build_info).to be_nil
end
end
context 'with build_infos' do
let_it_be(:first_build_info) { create(:package_build_info, :with_pipeline, package: package) }
let_it_be(:second_build_info) { create(:package_build_info, :with_pipeline, package: package) }
it 'returns the first build info' do
expect(package.original_build_info).to eq(first_build_info)
end
end
end
end end
...@@ -22,7 +22,7 @@ RSpec.describe ::Packages::Detail::PackagePresenter do ...@@ -22,7 +22,7 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
end end
let(:pipeline_info) do let(:pipeline_info) do
pipeline = package.build_info.pipeline pipeline = package.original_build_info.pipeline
{ {
created_at: pipeline.created_at, created_at: pipeline.created_at,
id: pipeline.id, id: pipeline.id,
...@@ -56,16 +56,44 @@ RSpec.describe ::Packages::Detail::PackagePresenter do ...@@ -56,16 +56,44 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
} }
end end
context 'detail_view' do describe '#detail_view' do
context 'with build_info' do context 'with build_info' do
let_it_be(:package) { create(:npm_package, :with_build, project: project) } let_it_be(:package) { create(:npm_package, :with_build, project: project) }
let(:expected_package_details) { super().merge(pipeline: pipeline_info) }
let(:expected_package_details) do
super().merge(
pipeline: pipeline_info,
pipelines: [pipeline_info]
)
end
it 'returns details with pipeline' do it 'returns details with pipeline' do
expect(presenter.detail_view).to match expected_package_details expect(presenter.detail_view).to match expected_package_details
end end
end end
context 'with multiple build_infos' do
let_it_be(:package) { create(:npm_package, :with_build, project: project) }
let_it_be(:build_info2) { create(:package_build_info, :with_pipeline, package: package) }
it 'returns details with two pipelines' do
expect(presenter.detail_view[:pipelines].size).to eq(2)
end
end
context 'with package_file_build_infos' do
let_it_be(:package) { create(:npm_package, :with_build, project: project) }
let_it_be(:package_file_build_info) do
create(:package_file_build_info, package_file: package.package_files.first,
pipeline: package.pipelines.first)
end
it 'returns details with package_file pipeline' do
expect(presenter.detail_view[:package_files].first[:pipelines].size).to eq(1)
end
end
context 'without build info' do context 'without build info' do
let_it_be(:package) { create(:npm_package, project: project) } let_it_be(:package) { create(:npm_package, project: project) }
......
...@@ -195,7 +195,7 @@ RSpec.describe API::GenericPackages do ...@@ -195,7 +195,7 @@ RSpec.describe API::GenericPackages do
package = project.packages.generic.last package = project.packages.generic.last
expect(package.name).to eq('mypackage') expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1') expect(package.version).to eq('0.0.1')
expect(package.build_info).to be_nil expect(package.original_build_info).to be_nil
package_file = package.package_files.last package_file = package.package_files.last
expect(package_file.file_name).to eq('myfile.tar.gz') expect(package_file.file_name).to eq('myfile.tar.gz')
...@@ -215,7 +215,7 @@ RSpec.describe API::GenericPackages do ...@@ -215,7 +215,7 @@ RSpec.describe API::GenericPackages do
package = project.packages.generic.last package = project.packages.generic.last
expect(package.name).to eq('mypackage') expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1') expect(package.version).to eq('0.0.1')
expect(package.build_info.pipeline).to eq(ci_build.pipeline) expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
package_file = package.package_files.last package_file = package.package_files.last
expect(package_file.file_name).to eq('myfile.tar.gz') expect(package_file.file_name).to eq('myfile.tar.gz')
......
...@@ -601,7 +601,7 @@ RSpec.describe API::MavenPackages do ...@@ -601,7 +601,7 @@ RSpec.describe API::MavenPackages do
upload_file(params: params.merge(job_token: job.token)) upload_file(params: params.merge(job_token: job.token))
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages.last.build_info.pipeline).to eq job.pipeline expect(project.reload.packages.last.original_build_info.pipeline).to eq job.pipeline
end end
it 'rejects upload without running job token' do it 'rejects upload without running job token' do
......
...@@ -211,7 +211,7 @@ RSpec.describe API::NpmProjectPackages do ...@@ -211,7 +211,7 @@ RSpec.describe API::NpmProjectPackages do
upload_package_with_token(package_name, params) upload_package_with_token(package_name, params)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages.find(json_response['id']).build_info.pipeline).to eq job.pipeline expect(project.reload.packages.find(json_response['id']).original_build_info.pipeline).to eq job.pipeline
end end
end end
end end
......
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::CreatePackageFileService do RSpec.describe Packages::CreatePackageFileService do
let(:package) { create(:maven_package) } let_it_be(:package) { create(:maven_package) }
let_it_be(:user) { create(:user) }
subject { described_class.new(package, params) }
describe '#execute' do describe '#execute' do
context 'with valid params' do context 'with valid params' do
...@@ -14,7 +17,7 @@ RSpec.describe Packages::CreatePackageFileService do ...@@ -14,7 +17,7 @@ RSpec.describe Packages::CreatePackageFileService do
end end
it 'creates a new package file' do it 'creates a new package file' do
package_file = described_class.new(package, params).execute package_file = subject.execute
expect(package_file).to be_valid expect(package_file).to be_valid
expect(package_file.file_name).to eq('foo.jar') expect(package_file.file_name).to eq('foo.jar')
...@@ -29,9 +32,17 @@ RSpec.describe Packages::CreatePackageFileService do ...@@ -29,9 +32,17 @@ RSpec.describe Packages::CreatePackageFileService do
end end
it 'raises an error' do it 'raises an error' do
service = described_class.new(package, params) expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid)
end
end
context 'with a build' do
let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
let(:build) { double('build', pipeline: pipeline) }
let(:params) { { file: Tempfile.new, file_name: 'foo.jar', build: build } }
expect { service.execute }.to raise_error(ActiveRecord::RecordInvalid) it 'creates a build_info' do
expect { subject.execute }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end end
end end
end end
......
...@@ -5,6 +5,8 @@ require 'spec_helper' ...@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Packages::Generic::CreatePackageFileService do 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(:build) { double('build', pipeline: pipeline) }
describe '#execute' do describe '#execute' do
let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' } let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' }
...@@ -16,7 +18,8 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -16,7 +18,8 @@ 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: 'myfile.tar.gz.1',
build: build
} }
end end
...@@ -41,6 +44,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -41,6 +44,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
service = described_class.new(project, user, params) service = described_class.new(project, user, params)
expect { service.execute }.to change { package.package_files.count }.by(1) expect { service.execute }.to change { package.package_files.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
......
...@@ -27,7 +27,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do ...@@ -27,7 +27,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(package.creator).to eq(user) expect(package.creator).to eq(user)
expect(package.name).to eq('mypackage') expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1') expect(package.version).to eq('0.0.1')
expect(package.build_info).to be_nil expect(package.original_build_info).to be_nil
end end
end end
...@@ -42,7 +42,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do ...@@ -42,7 +42,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(package.creator).to eq(user) expect(package.creator).to eq(user)
expect(package.name).to eq('mypackage') expect(package.name).to eq('mypackage')
expect(package.version).to eq('0.0.1') expect(package.version).to eq('0.0.1')
expect(package.build_info.pipeline).to eq(ci_build.pipeline) expect(package.original_build_info.pipeline).to eq(ci_build.pipeline)
end end
end end
end end
...@@ -60,7 +60,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do ...@@ -60,7 +60,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(found_package).to eq(package) expect(found_package).to eq(package)
end.not_to change { project.packages.generic.count } end.not_to change { project.packages.generic.count }
expect(package.reload.build_info).to be_nil expect(package.reload.original_build_info).to be_nil
end end
end end
...@@ -68,7 +68,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do ...@@ -68,7 +68,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
let(:pipeline) { create(:ci_pipeline, project: project) } let(:pipeline) { create(:ci_pipeline, project: project) }
before do before do
package.create_build_info!(pipeline: pipeline) package.build_infos.create!(pipeline: pipeline)
end end
it 'finds the package and does not change package build info even if build is provided' do it 'finds the package and does not change package build info even if build is provided' do
...@@ -80,7 +80,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do ...@@ -80,7 +80,7 @@ RSpec.describe Packages::Generic::FindOrCreatePackageService do
expect(found_package).to eq(package) expect(found_package).to eq(package)
end.not_to change { project.packages.generic.count } end.not_to change { project.packages.generic.count }
expect(package.reload.build_info.pipeline).to eq(pipeline) expect(package.reload.original_build_info.pipeline).to eq(pipeline)
end end
end end
end end
......
...@@ -33,8 +33,6 @@ RSpec.describe Packages::Maven::CreatePackageService do ...@@ -33,8 +33,6 @@ RSpec.describe Packages::Maven::CreatePackageService do
expect(package.maven_metadatum.app_version).to eq(version) expect(package.maven_metadatum.app_version).to eq(version)
end end
it_behaves_like 'assigns build to package'
it_behaves_like 'assigns the package creator' it_behaves_like 'assigns the package creator'
end end
......
...@@ -10,11 +10,12 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do ...@@ -10,11 +10,12 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
let(:version) { '1.0.0' } let(:version) { '1.0.0' }
let(:file_name) { 'test.jar' } let(:file_name) { 'test.jar' }
let(:param_path) { "#{path}/#{version}" } let(:param_path) { "#{path}/#{version}" }
let(:params) { { path: param_path, file_name: file_name } }
describe '#execute' do describe '#execute' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
subject { described_class.new(project, user, { path: param_path, file_name: file_name }).execute } subject { described_class.new(project, user, params).execute }
RSpec.shared_examples 'reuse existing package' do RSpec.shared_examples 'reuse existing package' do
it { expect { subject}.not_to change { Packages::Package.count } } it { expect { subject}.not_to change { Packages::Package.count } }
...@@ -23,7 +24,7 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do ...@@ -23,7 +24,7 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
end end
RSpec.shared_examples 'create package' do RSpec.shared_examples 'create package' do
it { expect { subject}.to change { Packages::Package.count }.by(1) } it { expect { subject }.to change { Packages::Package.count }.by(1) }
it 'sets the proper name and version' do it 'sets the proper name and version' do
pkg = subject pkg = subject
...@@ -31,6 +32,8 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do ...@@ -31,6 +32,8 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
expect(pkg.name).to eq(path) expect(pkg.name).to eq(path)
expect(pkg.version).to eq(version) expect(pkg.version).to eq(version)
end end
it_behaves_like 'assigns build to package'
end end
context 'path with version' do context 'path with version' do
...@@ -77,5 +80,15 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do ...@@ -77,5 +80,15 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
end end
end end
end end
context 'with a build' do
let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
let(:build) { double('build', pipeline: pipeline) }
let(:params) { { path: param_path, file_name: file_name, build: build } }
it 'creates a build_info' do
expect { subject }.to change { Packages::BuildInfo.count }.by(1)
end
end
end end
end end
...@@ -48,7 +48,16 @@ RSpec.describe Packages::Npm::CreatePackageService do ...@@ -48,7 +48,16 @@ RSpec.describe Packages::Npm::CreatePackageService do
context 'scoped package' do context 'scoped package' do
it_behaves_like 'valid package' it_behaves_like 'valid package'
context 'with build info' do
let(:job) { create(:ci_build, user: user) }
let(:params) { super().merge(build: job) }
it_behaves_like 'assigns build to package' it_behaves_like 'assigns build to package'
it 'creates a package file build info' do
expect { subject }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end
end
end end
context 'invalid package name' do context 'invalid package name' do
......
...@@ -8,8 +8,8 @@ RSpec.shared_examples 'assigns build to package' do ...@@ -8,8 +8,8 @@ RSpec.shared_examples 'assigns build to package' do
it 'assigns the pipeline to the package' do it 'assigns the pipeline to the package' do
package = subject package = subject
expect(package.build_info).to be_present expect(package.original_build_info).to be_present
expect(package.build_info.pipeline).to eq job.pipeline expect(package.original_build_info.pipeline).to eq job.pipeline
end end
end end
end end
......
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