Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-04-09 21:09:22 +00:00
parent b19efd7274
commit 017841e3c0
49 changed files with 1028 additions and 171 deletions

View file

@ -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

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
module Packages
module Conan
class FileMetadatumPolicy < BasePolicy
delegate { @subject.package_file.package }
end
end
end

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
module Packages
module Conan
class MetadatumPolicy < BasePolicy
delegate { @subject.package }
end
end
end

View file

@ -0,0 +1,6 @@
# frozen_string_literal: true
module Packages
class PackageFilePolicy < BasePolicy
delegate { @subject.package }
end
end

View file

@ -0,0 +1,5 @@
---
title: Return email confirmation time from email entity
merge_request: 58957
author:
type: changed

View file

@ -0,0 +1,5 @@
---
title: Add Conan GraphQL type to package
merge_request: 57719
author:
type: added

View file

@ -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

View file

@ -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:

View file

@ -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"
```

View file

@ -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.

View file

@ -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"
}
```

View file

@ -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.

View file

@ -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).

View file

@ -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

View file

@ -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.

View file

@ -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) |

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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).

View file

@ -3,7 +3,7 @@
module API
module Entities
class Email < Grape::Entity
expose :id, :email
expose :id, :email, :confirmed_at
end
end
end

View file

@ -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",

View file

@ -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"
}
}
}

View file

@ -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" }
}
}
}
}

View file

@ -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');
});
});
});
});

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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
it 'includes the fields of the correct package' do
expect(package_details).to include(
'id' => package_global_id,
'metadata' => {
describe 'Packages Metadata' do
before do
subject
end
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

View file

@ -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

View file

@ -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"