Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop_manual_todo.yml2
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue12
-rw-r--r--app/graphql/resolvers/package_details_resolver.rb10
-rw-r--r--app/graphql/types/ci/stage_type.rb28
-rw-r--r--app/graphql/types/packages/conan/file_metadatum_type.rb22
-rw-r--r--app/graphql/types/packages/conan/metadatum_file_type_enum.rb16
-rw-r--r--app/graphql/types/packages/conan/metadatum_type.rb22
-rw-r--r--app/graphql/types/packages/file_metadata_type.rb27
-rw-r--r--app/graphql/types/packages/metadata_type.rb4
-rw-r--r--app/graphql/types/packages/package_details_type.rb20
-rw-r--r--app/graphql/types/packages/package_file_type.rb36
-rw-r--r--app/graphql/types/packages/package_type.rb47
-rw-r--r--app/graphql/types/packages/package_without_versions_type.rb44
-rw-r--r--app/policies/packages/conan/file_metadatum_policy.rb8
-rw-r--r--app/policies/packages/conan/metadatum_policy.rb8
-rw-r--r--app/policies/packages/package_file_policy.rb6
-rw-r--r--changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml5
-rw-r--r--changelogs/unreleased/285467-package-registry-graphql-api.yml5
-rw-r--r--config/feature_flags/development/ci_no_empty_groups.yml8
-rw-r--r--doc/api/graphql/reference/index.md166
-rw-r--r--doc/api/packages/rubygems.md149
-rw-r--r--doc/api/repositories.md12
-rw-r--r--doc/api/users.md12
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md4
-rw-r--r--doc/operations/incident_management/index.md3
-rw-r--r--doc/operations/incident_management/oncall_schedules.md9
-rw-r--r--doc/user/packages/composer_repository/index.md7
-rw-r--r--doc/user/packages/index.md2
-rw-r--r--doc/user/packages/maven_repository/index.md8
-rw-r--r--doc/user/packages/npm_registry/index.md17
-rw-r--r--doc/user/packages/nuget_repository/index.md10
-rw-r--r--doc/user/packages/pypi_repository/index.md7
-rw-r--r--doc/user/packages/rubygems_registry/index.md137
-rw-r--r--lib/api/entities/email.rb2
-rw-r--r--package.json2
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json37
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json36
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js23
-rw-r--r--spec/graphql/types/packages/conan/file_metadatum_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb13
-rw-r--r--spec/graphql/types/packages/conan/metadatum_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/package_details_type_spec.rb (renamed from spec/graphql/types/packages/package_without_versions_type_spec.rb)4
-rw-r--r--spec/graphql/types/packages/package_file_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/package_type_spec.rb2
-rw-r--r--spec/graphql/types/query_type_spec.rb2
-rw-r--r--spec/helpers/projects/ci/pipeline_editor_helper_spec.rb31
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb121
-rw-r--r--spec/requests/api/users_spec.rb6
-rw-r--r--yarn.lock8
49 files changed, 1028 insertions, 171 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 8091d4f2e52..75d6d38b91e 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -517,8 +517,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- ee/spec/policies/merge_request_policy_spec.rb
- ee/spec/policies/project_policy_spec.rb
- ee/spec/policies/vulnerabilities/issue_link_policy_spec.rb
- - ee/spec/presenters/approval_rule_presenter_spec.rb
- - ee/spec/presenters/ci/pipeline_presenter_spec.rb
- ee/spec/requests/api/analytics/code_review_analytics_spec.rb
- ee/spec/requests/api/audit_events_spec.rb
- ee/spec/requests/api/commits_spec.rb
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
index 21708c6c9db..1060b37067e 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
@@ -91,7 +91,7 @@ export default {
},
computed: {
- availablePanels() {
+ decoratedPanels() {
const PANEL_TITLES = experiment(NEW_REPO_EXPERIMENT, {
use: () => ({
blank: s__('ProjectsNew|Create blank project'),
@@ -103,20 +103,22 @@ export default {
}),
});
- const updatedPanels = PANELS.map(({ key, title, ...el }) => ({
+ return PANELS.map(({ key, title, ...el }) => ({
...el,
title: PANEL_TITLES[key] !== undefined ? PANEL_TITLES[key] : title,
}));
+ },
+ availablePanels() {
if (this.isCiCdAvailable) {
- return updatedPanels;
+ return this.decoratedPanels;
}
- return updatedPanels.filter((p) => p.name !== CI_CD_PANEL);
+ return this.decoratedPanels.filter((p) => p.name !== CI_CD_PANEL);
},
activePanel() {
- return PANELS.find((p) => p.name === this.activeTab);
+ return this.decoratedPanels.find((p) => p.name === this.activeTab);
},
breadcrumbs() {
diff --git a/app/graphql/resolvers/package_details_resolver.rb b/app/graphql/resolvers/package_details_resolver.rb
index e688e34599a..89d79747732 100644
--- a/app/graphql/resolvers/package_details_resolver.rb
+++ b/app/graphql/resolvers/package_details_resolver.rb
@@ -2,12 +2,20 @@
module Resolvers
class PackageDetailsResolver < BaseResolver
- type ::Types::Packages::PackageType, null: true
+ type ::Types::Packages::PackageDetailsType, null: true
argument :id, ::Types::GlobalIDType[::Packages::Package],
required: true,
description: 'The global ID of the package.'
+ def ready?(**args)
+ context[self.class] ||= { executions: 0 }
+ context[self.class][:executions] += 1
+ raise GraphQL::ExecutionError, "Package details can be requested only for one package at a time" if context[self.class][:executions] > 1
+
+ super
+ end
+
def resolve(id:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index 04a7698e323..56b4f248697 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -36,6 +36,34 @@ module Types
jobs_for_pipeline(pl, indexed.keys, include_needs).each do |stage_id, statuses|
key = indexed[stage_id]
groups = ::Ci::Group.fabricate(project, key.stage, statuses)
+
+ if Feature.enabled?(:ci_no_empty_groups, project)
+ groups.each do |group|
+ rejected = group.jobs.reject { |job| Ability.allowed?(current_user, :read_commit_status, job) }
+ group.jobs.select! { |job| Ability.allowed?(current_user, :read_commit_status, job) }
+ next unless group.jobs.empty?
+
+ exc = StandardError.new('Empty Ci::Group')
+ traces = rejected.map do |job|
+ trace = []
+ policy = Ability.policy_for(current_user, job)
+ policy.debug(:read_commit_status, trace)
+ trace
+ end
+ extra = {
+ current_user_id: current_user&.id,
+ project_id: project.id,
+ pipeline_id: pl.id,
+ stage_id: stage_id,
+ group_name: group.name,
+ rejected_job_ids: rejected.map(&:id),
+ rejected_traces: traces
+ }
+ Gitlab::ErrorTracking.track_exception(exc, extra)
+ end
+ groups.reject! { |group| group.jobs.empty? }
+ end
+
loader.call(key, groups)
end
end
diff --git a/app/graphql/types/packages/conan/file_metadatum_type.rb b/app/graphql/types/packages/conan/file_metadatum_type.rb
new file mode 100644
index 00000000000..97d5abe6ba4
--- /dev/null
+++ b/app/graphql/types/packages/conan/file_metadatum_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class FileMetadatumType < BaseObject
+ graphql_name 'ConanFileMetadata'
+ description 'Conan file metadata'
+
+ implements Types::Packages::FileMetadataType
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Conan::FileMetadatum], null: false, description: 'ID of the metadatum.'
+ field :recipe_revision, GraphQL::STRING_TYPE, null: false, description: 'Revision of the Conan recipe.'
+ field :package_revision, GraphQL::STRING_TYPE, null: true, description: 'Revision of the package.'
+ field :conan_package_reference, GraphQL::STRING_TYPE, null: true, description: 'Reference of the Conan package.'
+ field :conan_file_type, ::Types::Packages::Conan::MetadatumFileTypeEnum, null: false, description: 'Type of the Conan file.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/conan/metadatum_file_type_enum.rb b/app/graphql/types/packages/conan/metadatum_file_type_enum.rb
new file mode 100644
index 00000000000..d8ec3a44d4d
--- /dev/null
+++ b/app/graphql/types/packages/conan/metadatum_file_type_enum.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class MetadatumFileTypeEnum < BaseEnum
+ graphql_name 'ConanMetadatumFileTypeEnum'
+ description 'Conan file types'
+
+ ::Packages::Conan::FileMetadatum.conan_file_types.keys.each do |file|
+ value file.upcase, value: file, description: "A #{file.humanize(capitalize: false)} type."
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/conan/metadatum_type.rb b/app/graphql/types/packages/conan/metadatum_type.rb
new file mode 100644
index 00000000000..00b84235d27
--- /dev/null
+++ b/app/graphql/types/packages/conan/metadatum_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class MetadatumType < BaseObject
+ graphql_name 'ConanMetadata'
+ description 'Conan metadata'
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Conan::Metadatum], null: false, description: 'ID of the metadatum.'
+ field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
+ field :package_username, GraphQL::STRING_TYPE, null: false, description: 'Username of the Conan package.'
+ field :package_channel, GraphQL::STRING_TYPE, null: false, description: 'Channel of the Conan package.'
+ field :recipe, GraphQL::STRING_TYPE, null: false, description: 'Recipe of the Conan package.'
+ field :recipe_path, GraphQL::STRING_TYPE, null: false, description: 'Recipe path of the Conan package.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/file_metadata_type.rb b/app/graphql/types/packages/file_metadata_type.rb
new file mode 100644
index 00000000000..46ccb424218
--- /dev/null
+++ b/app/graphql/types/packages/file_metadata_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module FileMetadataType
+ include ::Types::BaseInterface
+ graphql_name 'PackageFileMetadata'
+ description 'Represents metadata associated with a Package file'
+
+ field :created_at, ::Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, ::Types::TimeType, null: false, description: 'Date of most recent update.'
+
+ def self.resolve_type(object, context)
+ case object
+ when ::Packages::Conan::FileMetadatum
+ ::Types::Packages::Conan::FileMetadatumType
+ else
+ # NOTE: This method must be kept in sync with `PackageFileType#file_metadata`,
+ # which must never produce data that this discriminator cannot handle.
+ raise 'Unsupported file metadata type'
+ end
+ end
+
+ orphan_types Types::Packages::Conan::FileMetadatumType
+ end
+ end
+end
diff --git a/app/graphql/types/packages/metadata_type.rb b/app/graphql/types/packages/metadata_type.rb
index 26c43b51a69..4ab6707df88 100644
--- a/app/graphql/types/packages/metadata_type.rb
+++ b/app/graphql/types/packages/metadata_type.rb
@@ -6,12 +6,14 @@ module Types
graphql_name 'PackageMetadata'
description 'Represents metadata associated with a Package'
- possible_types ::Types::Packages::Composer::MetadatumType
+ possible_types ::Types::Packages::Composer::MetadatumType, ::Types::Packages::Conan::MetadatumType
def self.resolve_type(object, context)
case object
when ::Packages::Composer::Metadatum
::Types::Packages::Composer::MetadatumType
+ when ::Packages::Conan::Metadatum
+ ::Types::Packages::Conan::MetadatumType
else
# NOTE: This method must be kept in sync with `PackageWithoutVersionsType#metadata`,
# which must never produce data that this discriminator cannot handle.
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
new file mode 100644
index 00000000000..510b7e2ba41
--- /dev/null
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageDetailsType < PackageType
+ graphql_name 'PackageDetailsType'
+ description 'Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes'
+ authorize :read_package
+
+ field :versions, ::Types::Packages::PackageType.connection_type, null: true,
+ description: 'The other versions of the package.'
+
+ field :package_files, Types::Packages::PackageFileType.connection_type, null: true, description: 'Package files.'
+
+ def versions
+ object.versions
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_file_type.rb b/app/graphql/types/packages/package_file_type.rb
new file mode 100644
index 00000000000..e9e38559626
--- /dev/null
+++ b/app/graphql/types/packages/package_file_type.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageFileType < BaseObject
+ graphql_name 'PackageFile'
+ description 'Represents a package file'
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::PackageFile], null: false, description: 'ID of the file.'
+ field :created_at, Types::TimeType, null: false, description: 'The created date.'
+ field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
+ field :size, GraphQL::STRING_TYPE, null: false, description: 'Size of the package file.'
+ field :file_name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package file.'
+ field :download_path, GraphQL::STRING_TYPE, null: false, description: 'Download path of the package file.'
+ field :file_md5, GraphQL::STRING_TYPE, null: true, description: 'Md5 of the package file.'
+ field :file_sha1, GraphQL::STRING_TYPE, null: true, description: 'Sha1 of the package file.'
+ field :file_sha256, GraphQL::STRING_TYPE, null: true, description: 'Sha256 of the package file.'
+ field :file_metadata, Types::Packages::FileMetadataType, null: true,
+ description: 'File metadata.'
+
+ # NOTE: This method must be kept in sync with the union
+ # type: `Types::Packages::FileMetadataType`.
+ #
+ # `Types::Packages::FileMetadataType.resolve_type(metadata, ctx)` must never raise.
+ def file_metadata
+ case object.package.package_type
+ when 'conan'
+ object.conan_file_metadatum
+ else
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index 331898a1e84..a263ca1577a 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -2,13 +2,52 @@
module Types
module Packages
- class PackageType < PackageWithoutVersionsType
+ class PackageType < ::Types::BaseObject
graphql_name 'Package'
- description 'Represents a package in the Package Registry'
+ description 'Represents a package in the Package Registry. Note that this type is in beta and susceptible to changes'
+
authorize :read_package
- field :versions, ::Types::Packages::PackageWithoutVersionsType.connection_type, null: true,
- description: 'The other versions of the package.'
+ field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
+ description: 'ID of the package.'
+
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
+ field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
+ field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
+ field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
+ field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
+ field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
+ field :pipelines, Types::Ci::PipelineType.connection_type, null: true,
+ description: 'Pipelines that built the package.'
+ field :metadata, Types::Packages::MetadataType, null: true,
+ description: 'Package metadata.'
+ field :versions, ::Types::Packages::PackageType.connection_type, null: true,
+ description: 'The other versions of the package.',
+ deprecated: { reason: 'This field is now only returned in the PackageDetailsType', milestone: '13.11' }
+
+ def project
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
+ end
+
+ def versions
+ []
+ end
+
+ # NOTE: This method must be kept in sync with the union
+ # type: `Types::Packages::MetadataType`.
+ #
+ # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise.
+ def metadata
+ case object.package_type
+ when 'composer'
+ object.composer_metadatum
+ when 'conan'
+ object.conan_metadatum
+ else
+ nil
+ end
+ end
end
end
end
diff --git a/app/graphql/types/packages/package_without_versions_type.rb b/app/graphql/types/packages/package_without_versions_type.rb
deleted file mode 100644
index 9c6bb37e6cc..00000000000
--- a/app/graphql/types/packages/package_without_versions_type.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module Packages
- class PackageWithoutVersionsType < ::Types::BaseObject
- graphql_name 'PackageWithoutVersions'
- description 'Represents a version of a package in the Package Registry'
-
- authorize :read_package
-
- field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
- description: 'ID of the package.'
-
- field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
- field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
- field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
- field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
- field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
- field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
- field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
- field :pipelines, Types::Ci::PipelineType.connection_type, null: true,
- description: 'Pipelines that built the package.'
- field :metadata, Types::Packages::MetadataType, null: true,
- description: 'Package metadata.'
-
- def project
- Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
- end
-
- # NOTE: This method must be kept in sync with the union
- # type: `Types::Packages::MetadataType`.
- #
- # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise.
- def metadata
- case object.package_type
- when 'composer'
- object.composer_metadatum
- else
- nil
- end
- end
- end
- end
-end
diff --git a/app/policies/packages/conan/file_metadatum_policy.rb b/app/policies/packages/conan/file_metadatum_policy.rb
new file mode 100644
index 00000000000..ac1ffb3ea93
--- /dev/null
+++ b/app/policies/packages/conan/file_metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Conan
+ class FileMetadatumPolicy < BasePolicy
+ delegate { @subject.package_file.package }
+ end
+ end
+end
diff --git a/app/policies/packages/conan/metadatum_policy.rb b/app/policies/packages/conan/metadatum_policy.rb
new file mode 100644
index 00000000000..8622da015c6
--- /dev/null
+++ b/app/policies/packages/conan/metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Conan
+ class MetadatumPolicy < BasePolicy
+ delegate { @subject.package }
+ end
+ end
+end
diff --git a/app/policies/packages/package_file_policy.rb b/app/policies/packages/package_file_policy.rb
new file mode 100644
index 00000000000..e98f74204e8
--- /dev/null
+++ b/app/policies/packages/package_file_policy.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module Packages
+ class PackageFilePolicy < BasePolicy
+ delegate { @subject.package }
+ end
+end
diff --git a/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml b/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml
new file mode 100644
index 00000000000..7ead03d8c40
--- /dev/null
+++ b/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml
@@ -0,0 +1,5 @@
+---
+title: Return email confirmation time from email entity
+merge_request: 58957
+author:
+type: changed
diff --git a/changelogs/unreleased/285467-package-registry-graphql-api.yml b/changelogs/unreleased/285467-package-registry-graphql-api.yml
new file mode 100644
index 00000000000..17c4c2b3344
--- /dev/null
+++ b/changelogs/unreleased/285467-package-registry-graphql-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add Conan GraphQL type to package
+merge_request: 57719
+author:
+type: added
diff --git a/config/feature_flags/development/ci_no_empty_groups.yml b/config/feature_flags/development/ci_no_empty_groups.yml
new file mode 100644
index 00000000000..ef7d6459a5a
--- /dev/null
+++ b/config/feature_flags/development/ci_no_empty_groups.yml
@@ -0,0 +1,8 @@
+---
+name: ci_no_empty_groups
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58789
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327139
+milestone: '13.11'
+type: development
+group: group::verify
+default_enabled: false
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 67267223fd9..36774757ed3 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -215,7 +215,7 @@ Returns [`Namespace`](#namespace).
Find a package.
-Returns [`Package`](#package).
+Returns [`PackageDetailsType`](#packagedetailstype).
#### Arguments
@@ -1548,6 +1548,34 @@ Composer metadata.
| `composerJson` | [`PackageComposerJsonType!`](#packagecomposerjsontype) | Data of the Composer JSON file. |
| `targetSha` | [`String!`](#string) | Target SHA of the package. |
+### `ConanFileMetadata`
+
+Conan file metadata.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `conanFileType` | [`ConanMetadatumFileTypeEnum!`](#conanmetadatumfiletypeenum) | Type of the Conan file. |
+| `conanPackageReference` | [`String`](#string) | Reference of the Conan package. |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesConanFileMetadatumID!`](#packagesconanfilemetadatumid) | ID of the metadatum. |
+| `packageRevision` | [`String`](#string) | Revision of the package. |
+| `recipeRevision` | [`String!`](#string) | Revision of the Conan recipe. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
+### `ConanMetadata`
+
+Conan metadata.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesConanMetadatumID!`](#packagesconanmetadatumid) | ID of the metadatum. |
+| `packageChannel` | [`String!`](#string) | Channel of the Conan package. |
+| `packageUsername` | [`String!`](#string) | Username of the Conan package. |
+| `recipe` | [`String!`](#string) | Recipe of the Conan package. |
+| `recipePath` | [`String!`](#string) | Recipe path of the Conan package. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
### `ConfigureSastPayload`
Autogenerated return type of ConfigureSast.
@@ -4501,7 +4529,7 @@ Autogenerated return type of OncallScheduleUpdate.
### `Package`
-Represents a package in the Package Registry.
+Represents a package in the Package Registry. Note that this type is in beta and susceptible to changes.
| Field | Type | Description |
| ----- | ---- | ----------- |
@@ -4515,7 +4543,7 @@ Represents a package in the Package Registry.
| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
| `version` | [`String`](#string) | Version string. |
-| `versions` | [`PackageWithoutVersionsConnection`](#packagewithoutversionsconnection) | The other versions of the package. |
+| `versions` **{warning-solid}** | [`PackageConnection`](#packageconnection) | **Deprecated** in 13.11. This field is now only returned in the PackageDetailsType. |
### `PackageComposerJsonType`
@@ -4538,6 +4566,25 @@ The connection type for Package.
| `nodes` | [`[Package]`](#package) | A list of nodes. |
| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+### `PackageDetailsType`
+
+Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
+| `metadata` | [`PackageMetadata`](#packagemetadata) | Package metadata. |
+| `name` | [`String!`](#string) | Name of the package. |
+| `packageFiles` | [`PackageFileConnection`](#packagefileconnection) | Package files. |
+| `packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
+| `pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. |
+| `project` | [`Project!`](#project) | Project where the package is stored. |
+| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+| `version` | [`String`](#string) | Version string. |
+| `versions` | [`PackageConnection`](#packageconnection) | The other versions of the package. |
+
### `PackageEdge`
An edge in a connection.
@@ -4547,6 +4594,42 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`Package`](#package) | The item at the end of the edge. |
+### `PackageFile`
+
+Represents a package file.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | The created date. |
+| `downloadPath` | [`String!`](#string) | Download path of the package file. |
+| `fileMd5` | [`String`](#string) | Md5 of the package file. |
+| `fileMetadata` | [`PackageFileMetadata`](#packagefilemetadata) | File metadata. |
+| `fileName` | [`String!`](#string) | Name of the package file. |
+| `fileSha1` | [`String`](#string) | Sha1 of the package file. |
+| `fileSha256` | [`String`](#string) | Sha256 of the package file. |
+| `id` | [`PackagesPackageFileID!`](#packagespackagefileid) | ID of the file. |
+| `size` | [`String!`](#string) | Size of the package file. |
+| `updatedAt` | [`Time!`](#time) | The updated date. |
+
+### `PackageFileConnection`
+
+The connection type for PackageFile.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[PackageFileEdge]`](#packagefileedge) | A list of edges. |
+| `nodes` | [`[PackageFile]`](#packagefile) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `PackageFileEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`PackageFile`](#packagefile) | The item at the end of the edge. |
+
### `PackageFileRegistry`
Represents the Geo sync and verification state of a package file.
@@ -4620,42 +4703,6 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`PackageTag`](#packagetag) | The item at the end of the edge. |
-### `PackageWithoutVersions`
-
-Represents a version of a package in the Package Registry.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `createdAt` | [`Time!`](#time) | Date of creation. |
-| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
-| `metadata` | [`PackageMetadata`](#packagemetadata) | Package metadata. |
-| `name` | [`String!`](#string) | Name of the package. |
-| `packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
-| `pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. |
-| `project` | [`Project!`](#project) | Project where the package is stored. |
-| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
-| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
-| `version` | [`String`](#string) | Version string. |
-
-### `PackageWithoutVersionsConnection`
-
-The connection type for PackageWithoutVersions.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `edges` | [`[PackageWithoutVersionsEdge]`](#packagewithoutversionsedge) | A list of edges. |
-| `nodes` | [`[PackageWithoutVersions]`](#packagewithoutversions) | A list of nodes. |
-| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-
-### `PackageWithoutVersionsEdge`
-
-An edge in a connection.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| `node` | [`PackageWithoutVersions`](#packagewithoutversions) | The item at the end of the edge. |
-
### `PageInfo`
Information about pagination in a connection.
@@ -7536,6 +7583,15 @@ Mode of a commit action.
| `BASE64` | Base64 encoding. |
| `TEXT` | Text encoding. |
+### `ConanMetadatumFileTypeEnum`
+
+Conan file types.
+
+| Value | Description |
+| ----- | ----------- |
+| `PACKAGE_FILE` | A package file type. |
+| `RECIPE_FILE` | A recipe file type. |
+
### `ContainerExpirationPolicyCadenceEnum`
| Value | Description |
@@ -8794,6 +8850,24 @@ A `NoteableID` is a global ID. It is encoded as a string.
An example `NoteableID` is: `"gid://gitlab/Noteable/1"`.
+### `PackagesConanFileMetadatumID`
+
+A `PackagesConanFileMetadatumID` is a global ID. It is encoded as a string.
+
+An example `PackagesConanFileMetadatumID` is: `"gid://gitlab/Packages::Conan::FileMetadatum/1"`.
+
+### `PackagesConanMetadatumID`
+
+A `PackagesConanMetadatumID` is a global ID. It is encoded as a string.
+
+An example `PackagesConanMetadatumID` is: `"gid://gitlab/Packages::Conan::Metadatum/1"`.
+
+### `PackagesPackageFileID`
+
+A `PackagesPackageFileID` is a global ID. It is encoded as a string.
+
+An example `PackagesPackageFileID` is: `"gid://gitlab/Packages::PackageFile/1"`.
+
### `PackagesPackageID`
A `PackagesPackageID` is a global ID. It is encoded as a string.
@@ -8902,6 +8976,7 @@ Represents metadata associated with a Package.
One of:
- [`ComposerMetadata`](#composermetadata)
+- [`ConanMetadata`](#conanmetadata)
#### `VulnerabilityDetail`
@@ -9054,6 +9129,19 @@ Implementations:
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
| `notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. |
+#### `PackageFileMetadata`
+
+Represents metadata associated with a Package file.
+
+Implementations:
+
+- [`ConanFileMetadata`](#conanfilemetadata)
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
#### `ResolvableInterface`
Implementations:
diff --git a/doc/api/packages/rubygems.md b/doc/api/packages/rubygems.md
new file mode 100644
index 00000000000..426548d5ed2
--- /dev/null
+++ b/doc/api/packages/rubygems.md
@@ -0,0 +1,149 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Ruby gems API
+
+This is the API documentation for [Ruby gems](../../user/packages/rubygems_registry/index.md).
+
+WARNING:
+This API is used by the [Ruby gems and Bundler package manager clients](https://maven.apache.org/)
+and is generally not meant for manual consumption. This API is under development and is not ready
+for production use due to limited functionality.
+
+For instructions on how to upload and install gems from the GitLab
+package registry, see the [Ruby gems registry documentation](../../user/packages/rubygems_registry/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [Ruby gems registry documentation](../../user/packages/rubygems_registry/index.md)
+for details on which headers and token types are supported.
+
+## Enable the Ruby gems API
+
+The Ruby gems API for GitLab is behind a feature flag that is disabled by default. GitLab
+administrators with access to the GitLab Rails console can enable this API for your instance.
+
+To enable it:
+
+```ruby
+Feature.enable(:rubygem_packages)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:rubygem_packages)
+```
+
+To enable or disable it for specific projects:
+
+```ruby
+Feature.enable(:rubygem_packages, Project.find(1))
+Feature.disable(:rubygem_packages, Project.find(2))
+```
+
+## Download a gem file
+
+> Introduced in GitLab 13.10.
+
+Download a gem:
+
+```plaintext
+GET projects/:id/packages/rubygems/gems/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `file_name` | string | yes | The name of the `.gem` file. |
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/gems/my_gem-1.0.0.gem"
+```
+
+Write the output to file:
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/gems/my_gem-1.0.0.gem" >> my_gem-1.0.0.gem
+```
+
+This writes the downloaded file to `my_gem-1.0.0.gem` in the current directory.
+
+## Fetch a list of dependencies
+
+> Introduced in GitLab 13.10.
+
+Fetch a list of dependencies for a list of gems:
+
+```plaintext
+GET projects/:id/packages/rubygems/api/v1/dependencies
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `gems` | string | no | Comma-separated list of gems to fetch dependencies for. |
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/dependencies?gems=my_gem,foo"
+```
+
+This endpoint returns a marshalled array of hashes for all versions of the requested gems. Since the
+response is marshalled, you can store it in a file. If Ruby is installed, you can use the following
+Ruby command to read the response. For this to work, you must
+[set your credentials in `~/.gem/credentials`](../../user/packages/rubygems_registry/index.md#authenticate-with-a-personal-access-token-or-deploy-token):
+
+```shell
+$ ruby -ropen-uri -rpp -e \
+ 'pp Marshal.load(open("https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/dependencies?gems=my_gem,rails,foo"))'
+
+[{:name=>"my_gem", :number=>"0.0.1", :platform=>"ruby", :dependencies=>[]},
+ {:name=>"my_gem",
+ :number=>"0.0.3",
+ :platform=>"ruby",
+ :dependencies=>
+ [["dependency_1", "~> 1.2.3"],
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_3", ">= 1.0.0"],
+ ["dependency_4", ">= 0"]]},
+ {:name=>"my_gem",
+ :number=>"0.0.2",
+ :platform=>"ruby",
+ :dependencies=>
+ [["dependency_1", "~> 1.2.3"],
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_3", ">= 1.0.0"],
+ ["dependency_4", ">= 0"]]},
+ {:name=>"foo",
+ :number=>"0.0.2",
+ :platform=>"ruby",
+ :dependencies=>
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_4", ">= 0"]]}]
+```
+
+This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
+
+## Upload a gem
+
+> Introduced in GitLab 13.11.
+
+Upload a gem:
+
+```plaintext
+POST projects/:id/packages/rubygems/api/v1/gems
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+
+```shell
+curl --request POST \
+ --upload-file path/to/my_gem_file.gem \
+ --header "Authorization:<personal_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/gems"
+```
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index ba0a200731b..857cd3883c8 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -397,6 +397,18 @@ these as the changelog entries. You can enrich entries with additional data,
such as a link to the merge request or details about the commit author. You can
[customize the format of a changelog](#customize-the-changelog-output) section with a template.
+Trailers can be manually added while editing a commit message. To include a commit
+using the default trailer of `Changelog` and categorize it as a feature, the
+trailer could be added to a commit message like so:
+
+```plaintext
+<Commit message subject>
+
+<Commit message description>
+
+Changelog: feature
+```
+
### Reverted commits
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55537) in GitLab 13.10.
diff --git a/doc/api/users.md b/doc/api/users.md
index 4c35ee0e531..86f1548dac4 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1213,11 +1213,13 @@ GET /user/emails
[
{
"id": 1,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
},
{
"id": 3,
- "email": "email2@example.com"
+ "email": "email2@example.com",
+ "confirmed_at" : null
}
]
```
@@ -1257,7 +1259,8 @@ Parameters:
```json
{
"id": 1,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
}
```
@@ -1276,7 +1279,8 @@ Parameters:
```json
{
"id": 4,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
}
```
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index a01ad54b697..51328a13f27 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -49,7 +49,7 @@ graph TD
Running? -->|No| Excluded[Control / No Tracking]
Cached? -->|No| Excluded?
Cached? -->|Yes| Cached[Cached Value]
- Excluded? -->|Yes / Cached| Excluded
+ Excluded? -->|Yes| Excluded
Excluded? -->|No| Segmented?
Segmented? -->|Yes / Cached| VariantA
Segmented? -->|No| Included?[Experiment Group?]
@@ -92,7 +92,7 @@ end
```
When this code executes, the experiment is run, a variant is assigned, and (if within a
-controller or view) a `window.gon.experiment.pillColor` object will be available in the
+controller or view) a `window.gon.experiment.pill_color` object will be available in the
client layer, with details like:
- The assigned variant.
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index eb931b3eec5..ff5f41e59e9 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -13,6 +13,7 @@ generated by their application. By surfacing alerts and incidents where the code
being developed, efficiency and awareness can be increased. Check out the following sections for more information:
- [Integrate your monitoring tools](integrations.md).
-- Receive [notifications](paging.md) for triggered alerts.
+- Manage [on-call schedules](oncall_schedules.md) and receive [notifications](paging.md) for
+ triggered alerts.
- Triage [Alerts](alerts.md) and [Incidents](incidents.md).
- Inform stakeholders with [Status Page](status_page.md).
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
index 5a5564e3ce9..87745639c69 100644
--- a/doc/operations/incident_management/oncall_schedules.md
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -37,7 +37,7 @@ create [rotations](#rotations) for your schedule.
![Schedule Empty Grid](img/oncall_schedule_empty_grid_v13_10.png)
-### Update a schedule
+### Edit a schedule
Follow these steps to update a schedule:
@@ -46,6 +46,9 @@ Follow these steps to update a schedule:
1. In the **Edit schedule** form, edit the information you wish to update.
1. Click the **Edit schedule** button to save your changes.
+If you change the schedule's time zone, GitLab automatically updates the rotation's restricted time
+interval (if one is set) to the corresponding times in the new time zone.
+
### Delete a schedule
Follow these steps to delete a schedule:
@@ -70,8 +73,8 @@ Follow these steps to create a rotation:
- **Starts on:** The date and time the rotation begins.
- **Enable end date:** With the toggle set to on, you can select the date and time your rotation
ends.
- - **Restrict to time intervals:** With the toggle set to on, you can restrict your rotation to
- the time period you select.
+ - **Restrict to time intervals:** With the toggle set to on, you can restrict your rotation to the
+ time period you select.
### Edit a rotation
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 6a976fca382..bc1e59e4ac2 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -295,3 +295,10 @@ Never commit the `auth.json` file to your repository. To install packages from a
consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages.md#satis) tool with your personal access token
stored in a [GitLab CI/CD variable](../../../ci/variables/README.md) or in
[HashiCorp Vault](../../../ci/secrets/index.md).
+
+## Supported CLI commands
+
+The GitLab Composer repository supports the following Composer CLI commands:
+
+- `composer install`: Install Composer dependencies.
+- `composer update`: Install the latest version of Composer dependencies.
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index b35015d0b67..591bdca9353 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -24,6 +24,7 @@ The Package Registry supports the following formats:
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/nuget_repository/index.html">NuGet</a></td><td>12.8+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/pypi_repository/index.html">PyPI</a></td><td>12.10+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/generic_packages/index.html">Generic packages</a></td><td>13.5+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/rubygems_registry/index.html">RubyGems</a></td><td>13.10+</td></tr>
</table>
</div>
</div>
@@ -49,7 +50,6 @@ guides you through the process.
| P2 | [#36895](https://gitlab.com/gitlab-org/gitlab/-/issues/36895) |
| Puppet | [#36897](https://gitlab.com/gitlab-org/gitlab/-/issues/36897) |
| RPM | [#5932](https://gitlab.com/gitlab-org/gitlab/-/issues/5932) |
-| RubyGems | [#803](https://gitlab.com/gitlab-org/gitlab/-/issues/803) |
| SBT | [#36898](https://gitlab.com/gitlab-org/gitlab/-/issues/36898) |
| Terraform | [Draft: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 7104f4a02ed..d4dc9f0ae78 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -871,3 +871,11 @@ package:
- 'mvn help:system'
- 'mvn package'
```
+
+## Supported CLI commands
+
+The GitLab Maven repository supports the following Maven CLI commands:
+
+- `mvn deploy`: Publish your package to the Package Registry.
+- `mvn install`: Install packages specified in your Maven project.
+- `mvn dependency:get`: Install a specific package.
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index a997f2fbb08..b6312002184 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -515,4 +515,19 @@ This is usually a permissions issue with either:
- The remote bucket if [object storage](../../../administration/packages/#using-object-storage)
is used.
-In the latter case, ensure the bucket exists and the GitLab has write access to it.
+In the latter case, ensure the bucket exists and GitLab has write access to it.
+
+## Supported CLI commands
+
+The GitLab npm repository supports the following commands for the npm CLI (`npm`) and yarn CLI
+(`yarn`):
+
+- `npm install`: Install npm packages.
+- `npm publish`: Publish an npm package to the registry.
+- `npm dist-tag add`: Add a dist-tag to an npm package.
+- `npm dist-tag ls`: List dist-tags for a package.
+- `npm dist-tag rm`: Delete a dist-tag.
+- `npm ci`: Install npm packages directly from your `package-lock.json` file.
+- `npm view`: Show package metadata.
+- `yarn add`: Install an npm package.
+- `yarn update`: Update your dependencies.
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 128b1daf9cb..7e59b19076a 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -393,3 +393,13 @@ dotnet add package <package_id> \
- `<package_id>` is the package ID.
- `<package_version>` is the package version. Optional.
+
+## Supported CLI commands
+
+The GitLab NuGet repository supports the following commands for the NuGet CLI (`nuget`) and the .NET
+CLI (`dotnet`):
+
+- `nuget push`: Upload a package to the registry.
+- `dotnet nuget push`: Upload a package to the registry.
+- `nuget install`: Install a package from the registry.
+- `dotnet add`: Install a package from the registry.
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index a08b7b65145..17b51e313fa 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -359,3 +359,10 @@ characters are removed.
A `pip install` request for `my.package` looks for packages that match any of
the three characters, such as `my-package`, `my_package`, and `my....package`.
+
+## Supported CLI commands
+
+The GitLab PyPI repository supports the following CLI commands:
+
+- `twine upload`: Upload a package to the registry.
+- `pip install`: Install a PyPI package from the registry.
diff --git a/doc/user/packages/rubygems_registry/index.md b/doc/user/packages/rubygems_registry/index.md
new file mode 100644
index 00000000000..2a94d2a3ccf
--- /dev/null
+++ b/doc/user/packages/rubygems_registry/index.md
@@ -0,0 +1,137 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Ruby gems in the Package Registry
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/803) in [GitLab Free](https://about.gitlab.com/pricing/) 13.10.
+
+WARNING:
+The Ruby gems registry for GitLab is under development and isn't ready for production use due to
+limited functionality.
+
+You can publish Ruby gems in your project's Package Registry, then install the packages when you
+need to use them as a dependency. Although you can push gems to the registry, you cannot install
+them from the registry. However, you can download `gem` files directly from the Package Registry's
+UI, or by using the [API](../../../api/packages/rubygems.md#download-a-gem-file).
+
+For documentation of the specific API endpoints that the Ruby gems and Bundler package manager
+clients use, see the [Ruby gems API documentation](../../../api/packages/rubygems.md).
+
+## Enable the Ruby gems registry
+
+The Ruby gems registry for GitLab is behind a feature flag that is disabled by default. GitLab
+administrators with access to the GitLab Rails console can enable this registry for your instance.
+
+To enable it:
+
+```ruby
+Feature.enable(:rubygem_packages)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:rubygem_packages)
+```
+
+To enable or disable it for specific projects:
+
+```ruby
+Feature.enable(:rubygem_packages, Project.find(1))
+Feature.disable(:rubygem_packages, Project.find(2))
+```
+
+## Create a Ruby Gem
+
+If you need help creating a Ruby gem, see the [RubyGems documentation](https://guides.rubygems.org/make-your-own-gem/).
+
+## Authenticate to the Package Registry
+
+Before you can push to the Package Registry, you must authenticate.
+
+To do this, you can use:
+
+- A [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the scope set to `api`.
+- A [deploy token](../../project/deploy_tokens/index.md) with the scope set to
+ `read_package_registry`, `write_package_registry`, or both.
+- A [CI job token](#authenticate-with-a-ci-job-token).
+
+### Authenticate with a personal access token or deploy token
+
+To authenticate with a personal access token, create or edit the `~/.gem/credentials` file and add:
+
+```ini
+---
+https://gitlab.example.com/api/v4/projects/<project_id>/packages/rubygems: '<your token>'
+```
+
+- `<your token>` must be the token value of either your personal access token or deploy token.
+- Your project ID is on your project's home page.
+
+### Authenticate with a CI job token
+
+To work with RubyGems commands within [GitLab CI/CD](../../../ci/README.md),
+you can use `CI_JOB_TOKEN` instead of a personal access token or deploy token.
+
+For example:
+
+```yaml
+image: ruby:latest
+
+run:
+ script:
+```
+
+You can also use `CI_JOB_TOKEN` in a `~/.gem/credentials` file that you check in to
+GitLab:
+
+```ini
+---
+https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/rubygems: '${env.CI_JOB_TOKEN}'
+```
+
+## Push a Ruby gem
+
+Prerequisites:
+
+- You must [authenticate to the Package Registry](#authenticate-to-the-package-registry).
+- The maximum allowed gem size is 3 GB.
+
+To push your gem, run a command like this one:
+
+```shell
+gem push my_gem-0.0.1.gem --host <host>
+```
+
+Note that `<host>` is the URL you used when setting up authentication. For example:
+
+```shell
+gem push my_gem-0.0.1.gem --host https://gitlab.example.com/api/v4/projects/1/packages/rubygems
+```
+
+This message indicates that the gem uploaded successfully:
+
+```plaintext
+Pushing gem to https://gitlab.example.com/api/v4/projects/1/packages/rubygems...
+{"message":"201 Created"}
+```
+
+To view the published gem, go to your project's **Packages & Registries** page. Gems pushed to
+GitLab aren't displayed in your project's Packages UI immediately. It can take up to 10 minutes to
+process a gem.
+
+### Pushing gems with the same name or version
+
+You can push a gem if a package of the same name and version already exists.
+Both are visible and accessible in the UI. However, only the most recently
+pushed gem is used for installs.
+
+## Install a Ruby gem
+
+The Ruby gems registry for GitLab is under development, and isn't ready for production use. You
+cannot install Gems from the registry. However, you can download `.gem` files directly from the UI
+or by using the [API](../../../api/packages/rubygems.md#download-a-gem-file).
diff --git a/lib/api/entities/email.rb b/lib/api/entities/email.rb
index 5ba425def3d..46ebc458bcd 100644
--- a/lib/api/entities/email.rb
+++ b/lib/api/entities/email.rb
@@ -3,7 +3,7 @@
module API
module Entities
class Email < Grape::Entity
- expose :id, :email
+ expose :id, :email, :confirmed_at
end
end
end
diff --git a/package.json b/package.json
index 794e8cb6baa..868ac33d8e3 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.188.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "29.2.1",
+ "@gitlab/ui": "29.3.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json b/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json
new file mode 100644
index 00000000000..31bb861ced5
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json
@@ -0,0 +1,37 @@
+{
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "id",
+ "createdAt",
+ "updatedAt",
+ "packageUsername",
+ "packageChannel",
+ "recipe",
+ "recipePath",
+ "packageName"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "updated_at": {
+ "type": "string"
+ },
+ "package_username": {
+ "type": "string"
+ },
+ "package_channel": {
+ "type": "string"
+ },
+ "recipe": {
+ "type": "string"
+ },
+ "recipe_path": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index cf624f9c644..87b173eefc7 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -2,8 +2,17 @@
"type": "object",
"additionalProperties": false,
"required": [
- "id", "name", "createdAt", "updatedAt", "version", "packageType",
- "project", "tags", "pipelines", "versions", "metadata"
+ "id",
+ "name",
+ "createdAt",
+ "updatedAt",
+ "version",
+ "packageType",
+ "project",
+ "tags",
+ "pipelines",
+ "versions",
+ "metadata"
],
"properties": {
"id": {
@@ -23,7 +32,18 @@
},
"packageType": {
"type": ["string"],
- "enum": ["MAVEN", "NPM", "CONAN", "NUGET", "PYPI", "COMPOSER", "GENERIC", "GOLANG", "RUBYGEMS", "DEBIAN"]
+ "enum": [
+ "MAVEN",
+ "NPM",
+ "CONAN",
+ "NUGET",
+ "PYPI",
+ "COMPOSER",
+ "GENERIC",
+ "GOLANG",
+ "RUBYGEMS",
+ "DEBIAN"
+ ]
},
"tags": {
"type": "object",
@@ -59,8 +79,18 @@
"metadata": {
"anyOf": [
{ "$ref": "./package_composer_metadata.json" },
+ { "$ref": "./package_conan_metadata.json" },
{ "type": "null" }
]
+ },
+ "packageFiles": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pageInfo": { "type": "object" },
+ "edges": { "type": "array" },
+ "nodes": { "type": "array" }
+ }
}
}
}
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
index df1e38ec528..204e7a7c394 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
@@ -23,6 +23,7 @@ describe('Experimental new project creation app', () => {
findWelcomePage()
.props()
.panels.find((p) => p.name === panelName);
+ const findPanelHeader = () => wrapper.find('h4');
describe('new_repo experiment', () => {
describe('when in the candidate variant', () => {
@@ -33,6 +34,17 @@ describe('Experimental new project creation app', () => {
expect(findPanel('blank_project').title).toBe('Create blank project/repository');
});
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project/repository"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project/repository');
+ });
+ });
});
describe('when in the control variant', () => {
@@ -43,6 +55,17 @@ describe('Experimental new project creation app', () => {
expect(findPanel('blank_project').title).toBe('Create blank project');
});
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project');
+ });
+ });
});
});
diff --git a/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb b/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb
new file mode 100644
index 00000000000..18b17286654
--- /dev/null
+++ b/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanFileMetadata'] do
+ it 'includes conan file metadatum fields' do
+ expected_fields = %w[
+ id created_at updated_at recipe_revision package_revision conan_package_reference conan_file_type
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb b/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb
new file mode 100644
index 00000000000..379cb5168a8
--- /dev/null
+++ b/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanMetadatumFileTypeEnum'] do
+ it 'uses all possible options from model' do
+ expected_keys = ::Packages::Conan::FileMetadatum.conan_file_types
+ .keys
+ .map(&:upcase)
+
+ expect(described_class.values.keys).to contain_exactly(*expected_keys)
+ end
+end
diff --git a/spec/graphql/types/packages/conan/metadatum_type_spec.rb b/spec/graphql/types/packages/conan/metadatum_type_spec.rb
new file mode 100644
index 00000000000..f8f24ffc95a
--- /dev/null
+++ b/spec/graphql/types/packages/conan/metadatum_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanMetadata'] do
+ it 'includes conan metadatum fields' do
+ expected_fields = %w[
+ id created_at updated_at package_username package_channel recipe recipe_path
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/package_without_versions_type_spec.rb b/spec/graphql/types/packages/package_details_type_spec.rb
index faa79e588d5..06093813315 100644
--- a/spec/graphql/types/packages/package_without_versions_type_spec.rb
+++ b/spec/graphql/types/packages/package_details_type_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['PackageWithoutVersions'] do
+RSpec.describe GitlabSchema.types['PackageDetailsType'] do
it 'includes all the package fields' do
expected_fields = %w[
- id name version created_at updated_at package_type tags project pipelines
+ id name version created_at updated_at package_type tags project pipelines versions package_files
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/packages/package_file_type_spec.rb b/spec/graphql/types/packages/package_file_type_spec.rb
new file mode 100644
index 00000000000..8e20aea5220
--- /dev/null
+++ b/spec/graphql/types/packages/package_file_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageFile'] do
+ it 'includes package file fields' do
+ expected_fields = %w[
+ id file_name created_at updated_at size file_name download_path file_md5 file_sha1 file_sha256 file_metadata
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/package_type_spec.rb b/spec/graphql/types/packages/package_type_spec.rb
index 43289a019b3..544d6ddc3af 100644
--- a/spec/graphql/types/packages/package_type_spec.rb
+++ b/spec/graphql/types/packages/package_type_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['Package'] do
id name version package_type
created_at updated_at
project
- tags pipelines versions
+ tags pipelines metadata versions
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index cb8e875dbf4..d3dcdd260b0 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -98,6 +98,6 @@ RSpec.describe GitlabSchema.types['Query'] do
describe 'package field' do
subject { described_class.fields['package'] }
- it { is_expected.to have_graphql_type(Types::Packages::PackageType) }
+ it { is_expected.to have_graphql_type(Types::Packages::PackageDetailsType) }
end
end
diff --git a/spec/helpers/projects/ci/pipeline_editor_helper_spec.rb b/spec/helpers/projects/ci/pipeline_editor_helper_spec.rb
deleted file mode 100644
index 882b6548d64..00000000000
--- a/spec/helpers/projects/ci/pipeline_editor_helper_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Ci::PipelineEditorHelper do
- let_it_be(:project) { create(:project, :public, :repository) }
-
- describe '#js_pipeline_editor_data' do
- before do
- allow(helper).to receive(:namespace_project_new_merge_request_path).and_return('/mock/project/-/merge_requests/new')
- end
-
- subject { helper.js_pipeline_editor_data(project) }
-
- it {
- is_expected.to match({
- "ci-config-path": project.ci_config_path_or_default,
- "commit-sha" => project.commit.sha,
- "default-branch" => project.default_branch,
- "empty-state-illustration-path" => match_asset_path("/assets/illustrations/empty-state/empty-dag-md.svg"),
- "initial-branch-name": nil,
- "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
- "new-merge-request-path" => '/mock/project/-/merge_requests/new',
- "project-path" => project.path,
- "project-full-path" => project.full_path,
- "project-namespace" => project.namespace.full_path,
- "yml-help-page-path" => help_page_path('ci/yaml/README')
- })
- }
- end
-end
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 654215041cb..a0131c7733e 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -2,33 +2,47 @@
require 'spec_helper'
RSpec.describe 'package details' do
- using RSpec::Parameterized::TableSyntax
include GraphqlHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:package) { create(:composer_package, project: project) }
+ let_it_be(:composer_package) { create(:composer_package, project: project) }
let_it_be(:composer_json) { { name: 'name', type: 'type', license: 'license', version: 1 } }
let_it_be(:composer_metadatum) do
# we are forced to manually create the metadatum, without using the factory to force the sha to be a string
# and avoid an error where gitaly can't find the repository
- create(:composer_metadatum, package: package, target_sha: 'foo_sha', composer_json: composer_json)
+ create(:composer_metadatum, package: composer_package, target_sha: 'foo_sha', composer_json: composer_json)
end
let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline] }
+ let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
+ let(:metadata) { query_graphql_fragment('ComposerMetadata') }
+ let(:package_files) {all_graphql_fields_for('PackageFile')}
+ let(:package_files_metadata) {query_graphql_fragment('ConanFileMetadata')}
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
- #{all_graphql_fields_for('Package', max_depth: depth, excluded: excluded)}
+ #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
metadata {
- #{query_graphql_fragment('ComposerMetadata')}
+ #{metadata}
+ }
+ packageFiles {
+ nodes {
+ #{package_files}
+ fileMetadata {
+ #{package_files_metadata}
+ }
+ }
}
FIELDS
end
let(:user) { project.owner }
- let(:package_global_id) { global_id_of(package) }
+ let(:package_global_id) { global_id_of(composer_package) }
let(:package_details) { graphql_data_at(:package) }
+ let(:metadata_response) { graphql_data_at(:package, :metadata) }
+ let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
+ let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
+ let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)}
subject { post_graphql(query, current_user: user) }
@@ -40,15 +54,68 @@ RSpec.describe 'package details' do
it 'matches the JSON schema' do
expect(package_details).to match_schema('graphql/packages/package_details')
end
+ end
+
+ describe 'Packages Metadata' do
+ before do
+ subject
+ end
- it 'includes the fields of the correct package' do
- expect(package_details).to include(
- 'id' => package_global_id,
- 'metadata' => {
+ describe 'Composer' do
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
'targetSha' => 'foo_sha',
'composerJson' => composer_json.transform_keys(&:to_s).transform_values(&:to_s)
- }
- )
+ )
+ end
+
+ it 'does not have files' do
+ expect(package_files_response).to be_empty
+ end
+ end
+
+ describe 'Conan' do
+ let_it_be(:conan_package) { create(:conan_package, project: project) }
+
+ let(:package_global_id) { global_id_of(conan_package) }
+ let(:metadata) { query_graphql_fragment('ConanMetadata') }
+ let(:first_file) { conan_package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
+
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
+ 'id' => global_id_of(conan_package.conan_metadatum),
+ 'recipe' => conan_package.conan_metadatum.recipe,
+ 'packageChannel' => conan_package.conan_metadatum.package_channel,
+ 'packageUsername' => conan_package.conan_metadatum.package_username,
+ 'recipePath' => conan_package.conan_metadatum.recipe_path
+ )
+ end
+
+ it 'has the right amount of files' do
+ expect(package_files_response.length).to be(conan_package.package_files.length)
+ end
+
+ it 'has the basic package files data' do
+ expect(first_file_response).to include(
+ 'id' => global_id_of(first_file),
+ 'fileName' => first_file.file_name,
+ 'size' => first_file.size.to_s,
+ 'downloadPath' => first_file.download_path,
+ 'fileSha1' => first_file.file_sha1,
+ 'fileMd5' => first_file.file_md5,
+ 'fileSha256' => first_file.file_sha256
+ )
+ end
+
+ it 'has the correct file metadata' do
+ expect(first_file_response_metadata).to include(
+ 'id' => global_id_of(first_file.conan_file_metadatum),
+ 'packageRevision' => first_file.conan_file_metadatum.package_revision,
+ 'conanPackageReference' => first_file.conan_file_metadatum.conan_package_reference,
+ 'recipeRevision' => first_file.conan_file_metadatum.recipe_revision,
+ 'conanFileType' => first_file.conan_file_metadatum.conan_file_type.upcase
+ )
+ end
end
end
@@ -56,7 +123,7 @@ RSpec.describe 'package details' do
let(:depth) { 3 }
let(:excluded) { %w[metadata project tags pipelines] } # to limit the query complexity
- let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: package.name) }
+ let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: composer_package.name) }
it 'includes the sibling versions' do
subject
@@ -73,8 +140,32 @@ RSpec.describe 'package details' do
subject
expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present
- expect(graphql_data_at(:package, :versions, :nodes, :versions)).not_to be_present
+ expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to be_empty
end
end
end
+
+ context 'with a batched query' do
+ let_it_be(:conan_package) { create(:conan_package, project: project) }
+
+ let(:batch_query) do
+ <<~QUERY
+ {
+ a: package(id: "#{global_id_of(composer_package)}") { name }
+ b: package(id: "#{global_id_of(conan_package)}") { name }
+ }
+ QUERY
+ end
+
+ let(:a_packages_names) { graphql_data_at(:a, :packages, :nodes, :name) }
+
+ it 'returns an error for the second package and data for the first' do
+ post_graphql(batch_query, current_user: user)
+
+ expect(graphql_data_at(:a, :name)).to eq(composer_package.name)
+
+ expect_graphql_errors_to_include [/Package details can be requested only for one package at a time/]
+ expect(graphql_data_at(:b)).to be(nil)
+ end
+ end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index c3ada36b611..01a24be9f20 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1795,8 +1795,7 @@ RSpec.describe API::Users do
post api("/users/#{user.id}/emails", admin), params: email_attrs
end.to change { user.emails.count }.by(1)
- email = Email.find_by(user_id: user.id, email: email_attrs[:email])
- expect(email).not_to be_confirmed
+ expect(json_response['confirmed_at']).to be_nil
end
it "returns a 400 for invalid ID" do
@@ -1813,8 +1812,7 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:created)
- email = Email.find_by(user_id: user.id, email: email_attrs[:email])
- expect(email).to be_confirmed
+ expect(json_response['confirmed_at']).not_to be_nil
end
end
diff --git a/yarn.lock b/yarn.lock
index a30bd8dd13e..7d72d00c912 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -907,10 +907,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@29.2.1":
- version "29.2.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.2.1.tgz#e6377131f3a22eebe07903198ec874ca5d26884c"
- integrity sha512-vLzCMQsppGLpzWRaNxXpx86y6JjSOEnQXQxtLudnSJktWl0uHfglED2xe7vJQJo+qmzQf6T5m3gbVupj/pG4+A==
+"@gitlab/ui@29.3.0":
+ version "29.3.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.3.0.tgz#e549b73341246bb9cd1005b2f4c10a599c680cb1"
+ integrity sha512-TWc3O3w7L+aCLC7Vp2JbYTFgCwseLExxjhwDfJuc2Iwkr+1k8k1ygctbid9XRX2Jcy3JPbL+o+m0K/ZXMJTWdg==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"