Commit 3b744058 authored by David Fernandez's avatar David Fernandez

Merge branch 'helm_graphql' into 'master'

Add Helm metadata to GraphQL

See merge request gitlab-org/gitlab!71963
parents d2c97ebd 2b58d6cc
......@@ -14,6 +14,8 @@ module Types
case object
when ::Packages::Conan::FileMetadatum
::Types::Packages::Conan::FileMetadatumType
when ::Packages::Helm::FileMetadatum
::Types::Packages::Helm::FileMetadatumType
else
# NOTE: This method must be kept in sync with `PackageFileType#file_metadata`,
# which must never produce data that this discriminator cannot handle.
......@@ -21,7 +23,8 @@ module Types
end
end
orphan_types Types::Packages::Conan::FileMetadatumType
orphan_types Types::Packages::Conan::FileMetadatumType,
Types::Packages::Helm::FileMetadatumType
end
end
end
# frozen_string_literal: true
module Types
module Packages
module Helm
# rubocop: disable Graphql/AuthorizeTypes
class DependencyType < BaseObject
graphql_name 'PackageHelmDependencyType'
description 'Represents a Helm dependency'
# Need to be synced with app/validators/json_schemas/helm_metadata.json#dependencies
field :name, GraphQL::Types::String, null: true, description: 'Name of the dependency.'
field :version, GraphQL::Types::String, null: true, description: 'Version of the dependency.'
field :repository, GraphQL::Types::String, null: true, description: 'Repository of the dependency.'
field :condition, GraphQL::Types::String, null: true, description: 'Condition of the dependency.'
field :tags, [GraphQL::Types::String], null: true, description: 'Tags of the dependency.'
field :enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates the dependency is enabled.'
field :import_values, [GraphQL::Types::JSON], null: true, description: 'Import-values of the dependency.', hash_key: "import-values" # rubocop:disable Graphql/JSONType
field :alias, GraphQL::Types::String, null: true, description: 'Alias of the dependency.', resolver_method: :resolve_alias
# field :alias` conflicts with a built-in method
def resolve_alias
object['alias']
end
end
end
end
end
# frozen_string_literal: true
module Types
module Packages
module Helm
class FileMetadatumType < BaseObject
graphql_name 'HelmFileMetadata'
description 'Helm file metadata'
implements Types::Packages::FileMetadataType
authorize :read_package
field :channel, GraphQL::Types::String, null: false, description: 'Channel of the Helm chart.'
field :metadata, Types::Packages::Helm::MetadataType, null: false, description: 'Metadata of the Helm chart.'
end
end
end
end
# frozen_string_literal: true
module Types
module Packages
module Helm
# rubocop: disable Graphql/AuthorizeTypes
class MaintainerType < BaseObject
graphql_name 'PackageHelmMaintainerType'
description 'Represents a Helm maintainer'
# Need to be synced with app/validators/json_schemas/helm_metadata.json#maintainers
field :name, GraphQL::Types::String, null: true, description: 'Name of the maintainer.'
field :email, GraphQL::Types::String, null: true, description: 'Email of the maintainer.'
field :url, GraphQL::Types::String, null: true, description: 'URL of the maintainer.'
end
end
end
end
# frozen_string_literal: true
module Types
module Packages
module Helm
# rubocop: disable Graphql/AuthorizeTypes
class MetadataType < BaseObject
graphql_name 'PackageHelmMetadataType'
description 'Represents the contents of a Helm Chart.yml file'
# Need to be synced with app/validators/json_schemas/helm_metadata.json
field :name, GraphQL::Types::String, null: false, description: 'Name of the chart.'
field :home, GraphQL::Types::String, null: true, description: 'URL of the home page.'
field :sources, [GraphQL::Types::String], null: true, description: 'URLs of the source code for the chart.'
field :version, GraphQL::Types::String, null: false, description: 'Version of the chart.'
field :description, GraphQL::Types::String, null: true, description: 'Description of the chart.'
field :keywords, [GraphQL::Types::String], null: true, description: 'Keywords for the chart.'
field :maintainers, [Types::Packages::Helm::MaintainerType], null: true, description: 'Maintainers of the chart.'
field :icon, GraphQL::Types::String, null: true, description: 'URL to an SVG or PNG image for the chart.'
field :api_version, GraphQL::Types::String, null: false, description: 'API version of the chart.', hash_key: "apiVersion"
field :condition, GraphQL::Types::String, null: true, description: 'Condition for the chart.'
field :tags, GraphQL::Types::String, null: true, description: 'Tags for the chart.'
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the chart.', hash_key: "appVersion"
field :deprecated, GraphQL::Types::Boolean, null: true, description: 'Indicates if the chart is deprecated.'
field :annotations, GraphQL::Types::JSON, null: true, description: 'Annotations for the chart.' # rubocop:disable Graphql/JSONType
field :kube_version, GraphQL::Types::String, null: true, description: 'Kubernetes versions for the chart.', hash_key: "kubeVersion"
field :dependencies, [Types::Packages::Helm::DependencyType], null: true, description: 'Dependencies of the chart.'
field :type, GraphQL::Types::String, null: true, description: 'Type of the chart.', hash_key: "appVersion"
end
end
end
end
......@@ -27,6 +27,8 @@ module Types
case object.package.package_type
when 'conan'
object.conan_file_metadatum
when 'helm'
object.helm_file_metadatum
else
nil
end
......
# frozen_string_literal: true
module Packages
module Helm
class FileMetadatumPolicy < BasePolicy
delegate { @subject.package_file.package }
end
end
end
......@@ -103,7 +103,23 @@
"import-values": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"child": {
"type": "string"
},
"parent": {
"type": "string"
}
},
"additionalProperties": false
}
]
}
},
"alias": {
......
......@@ -10911,6 +10911,19 @@ Represents the Geo sync and verification state of a group wiki repository.
| <a id="groupwikirepositoryregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry. |
| <a id="groupwikirepositoryregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the GroupWikiRepositoryRegistry. |
### `HelmFileMetadata`
Helm file metadata.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="helmfilemetadatachannel"></a>`channel` | [`String!`](#string) | Channel of the Helm chart. |
| <a id="helmfilemetadatacreatedat"></a>`createdAt` | [`Time!`](#time) | Date of creation. |
| <a id="helmfilemetadatametadata"></a>`metadata` | [`PackageHelmMetadataType!`](#packagehelmmetadatatype) | Metadata of the Helm chart. |
| <a id="helmfilemetadataupdatedat"></a>`updatedAt` | [`Time!`](#time) | Date of most recent update. |
### `IncidentManagementOncallRotation`
Describes an incident management on-call rotation.
......@@ -12381,6 +12394,61 @@ Represents the Geo sync and verification state of a package file.
| <a id="packagefileregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PackageFileRegistry. |
| <a id="packagefileregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PackageFileRegistry. |
### `PackageHelmDependencyType`
Represents a Helm dependency.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="packagehelmdependencytypealias"></a>`alias` | [`String`](#string) | Alias of the dependency. |
| <a id="packagehelmdependencytypecondition"></a>`condition` | [`String`](#string) | Condition of the dependency. |
| <a id="packagehelmdependencytypeenabled"></a>`enabled` | [`Boolean`](#boolean) | Indicates the dependency is enabled. |
| <a id="packagehelmdependencytypeimportvalues"></a>`importValues` | [`[JSON!]`](#json) | Import-values of the dependency. |
| <a id="packagehelmdependencytypename"></a>`name` | [`String`](#string) | Name of the dependency. |
| <a id="packagehelmdependencytyperepository"></a>`repository` | [`String`](#string) | Repository of the dependency. |
| <a id="packagehelmdependencytypetags"></a>`tags` | [`[String!]`](#string) | Tags of the dependency. |
| <a id="packagehelmdependencytypeversion"></a>`version` | [`String`](#string) | Version of the dependency. |
### `PackageHelmMaintainerType`
Represents a Helm maintainer.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="packagehelmmaintainertypeemail"></a>`email` | [`String`](#string) | Email of the maintainer. |
| <a id="packagehelmmaintainertypename"></a>`name` | [`String`](#string) | Name of the maintainer. |
| <a id="packagehelmmaintainertypeurl"></a>`url` | [`String`](#string) | URL of the maintainer. |
### `PackageHelmMetadataType`
Represents the contents of a Helm Chart.yml file.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="packagehelmmetadatatypeannotations"></a>`annotations` | [`JSON`](#json) | Annotations for the chart. |
| <a id="packagehelmmetadatatypeapiversion"></a>`apiVersion` | [`String!`](#string) | API version of the chart. |
| <a id="packagehelmmetadatatypeappversion"></a>`appVersion` | [`String`](#string) | App version of the chart. |
| <a id="packagehelmmetadatatypecondition"></a>`condition` | [`String`](#string) | Condition for the chart. |
| <a id="packagehelmmetadatatypedependencies"></a>`dependencies` | [`[PackageHelmDependencyType!]`](#packagehelmdependencytype) | Dependencies of the chart. |
| <a id="packagehelmmetadatatypedeprecated"></a>`deprecated` | [`Boolean`](#boolean) | Indicates if the chart is deprecated. |
| <a id="packagehelmmetadatatypedescription"></a>`description` | [`String`](#string) | Description of the chart. |
| <a id="packagehelmmetadatatypehome"></a>`home` | [`String`](#string) | URL of the home page. |
| <a id="packagehelmmetadatatypeicon"></a>`icon` | [`String`](#string) | URL to an SVG or PNG image for the chart. |
| <a id="packagehelmmetadatatypekeywords"></a>`keywords` | [`[String!]`](#string) | Keywords for the chart. |
| <a id="packagehelmmetadatatypekubeversion"></a>`kubeVersion` | [`String`](#string) | Kubernetes versions for the chart. |
| <a id="packagehelmmetadatatypemaintainers"></a>`maintainers` | [`[PackageHelmMaintainerType!]`](#packagehelmmaintainertype) | Maintainers of the chart. |
| <a id="packagehelmmetadatatypename"></a>`name` | [`String!`](#string) | Name of the chart. |
| <a id="packagehelmmetadatatypesources"></a>`sources` | [`[String!]`](#string) | URLs of the source code for the chart. |
| <a id="packagehelmmetadatatypetags"></a>`tags` | [`String`](#string) | Tags for the chart. |
| <a id="packagehelmmetadatatypetype"></a>`type` | [`String`](#string) | Type of the chart. |
| <a id="packagehelmmetadatatypeversion"></a>`version` | [`String!`](#string) | Version of the chart. |
### `PackageSettings`
Namespace-level Package Registry settings.
......@@ -17759,6 +17827,7 @@ Represents metadata associated with a Package file.
Implementations:
- [`ConanFileMetadata`](#conanfilemetadata)
- [`HelmFileMetadata`](#helmfilemetadata)
##### Fields
......
......@@ -9,7 +9,11 @@ FactoryBot.define do
package_file { association(:helm_package_file, without_loaded_metadatum: true) }
sequence(:channel) { |n| "#{FFaker::Lorem.word}-#{n}" }
metadata do
{ 'name': package_file.package.name, 'version': package_file.package.version, 'apiVersion': 'v2' }.tap do |defaults|
{
'name': package_file.package.name,
'version': package_file.package.version,
'apiVersion': 'v2'
}.tap do |defaults|
defaults['description'] = description if description
end
end
......
......@@ -12,7 +12,6 @@
"tags",
"pipelines",
"versions",
"metadata",
"status",
"canDestroy"
],
......@@ -47,7 +46,8 @@
"GENERIC",
"GOLANG",
"RUBYGEMS",
"DEBIAN"
"DEBIAN",
"HELM"
]
},
"tags": {
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageHelmDependencyType'] do
it { expect(described_class.graphql_name).to eq('PackageHelmDependencyType') }
it 'includes helm dependency fields' do
expected_fields = %w[
name version repository condition tags enabled import_values alias
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['HelmFileMetadata'] do
it { expect(described_class.graphql_name).to eq('HelmFileMetadata') }
it 'includes helm file metadatum fields' do
expected_fields = %w[
created_at updated_at channel metadata
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageHelmMaintainerType'] do
it { expect(described_class.graphql_name).to eq('PackageHelmMaintainerType') }
it 'includes helm maintainer fields' do
expected_fields = %w[
name email url
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageHelmMetadataType'] do
it { expect(described_class.graphql_name).to eq('PackageHelmMetadataType') }
it 'includes helm json fields' do
expected_fields = %w[
name home sources version description keywords maintainers icon apiVersion condition tags appVersion deprecated annotations kubeVersion dependencies type
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'helm package details' do
include GraphqlHelpers
include_context 'package details setup'
let_it_be(:package) { create(:helm_package, project: project) }
let(:package_files_metadata) {query_graphql_fragment('HelmFileMetadata')}
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
#{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
packageFiles {
nodes {
#{package_files}
fileMetadata {
#{package_files_metadata}
}
}
}
FIELDS
end
subject { post_graphql(query, current_user: user) }
before do
subject
end
it_behaves_like 'a package detail'
it_behaves_like 'a package with files'
it 'has the correct file metadata' do
expect(first_file_response_metadata).to include(
'channel' => first_file.helm_file_metadatum.channel
)
expect(first_file_response_metadata['metadata']).to include(
'name' => first_file.helm_file_metadatum.metadata['name'],
'home' => first_file.helm_file_metadatum.metadata['home'],
'sources' => first_file.helm_file_metadatum.metadata['sources'],
'version' => first_file.helm_file_metadatum.metadata['version'],
'description' => first_file.helm_file_metadatum.metadata['description'],
'keywords' => first_file.helm_file_metadatum.metadata['keywords'],
'maintainers' => first_file.helm_file_metadatum.metadata['maintainers'],
'icon' => first_file.helm_file_metadatum.metadata['icon'],
'apiVersion' => first_file.helm_file_metadatum.metadata['apiVersion'],
'condition' => first_file.helm_file_metadatum.metadata['condition'],
'tags' => first_file.helm_file_metadatum.metadata['tags'],
'appVersion' => first_file.helm_file_metadatum.metadata['appVersion'],
'deprecated' => first_file.helm_file_metadatum.metadata['deprecated'],
'annotations' => first_file.helm_file_metadatum.metadata['annotations'],
'kubeVersion' => first_file.helm_file_metadatum.metadata['kubeVersion'],
'dependencies' => first_file.helm_file_metadatum.metadata['dependencies'],
'type' => first_file.helm_file_metadatum.metadata['type']
)
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment