Commit 7e9b35dc authored by charlie ablett's avatar charlie ablett

Merge branch 'mc/feature/add-ci-templates-graphql' into 'master'

Add CI template field to project GraphQL type

See merge request gitlab-org/gitlab!60276
parents 55c5be8a 1281f553
# frozen_string_literal: true
module Resolvers
module Ci
class TemplateResolver < BaseResolver
type Types::Ci::TemplateType, null: true
argument :name, GraphQL::STRING_TYPE, required: true,
description: 'Name of the CI/CD template to search for.'
alias_method :project, :object
def resolve(name: nil)
::TemplateFinder.new(:gitlab_ci_ymls, project, name: name).execute
end
end
end
end
# frozen_string_literal: true
module Types
module Ci
# rubocop: disable Graphql/AuthorizeTypes
class TemplateType < BaseObject
graphql_name 'CiTemplate'
description 'GitLab CI/CD configuration template.'
field :name, GraphQL::STRING_TYPE, null: false,
description: 'Name of the CI template.'
field :content, GraphQL::STRING_TYPE, null: false,
description: 'Contents of the CI template.'
end
end
end
...@@ -337,6 +337,10 @@ module Types ...@@ -337,6 +337,10 @@ module Types
description: 'Pipeline analytics.', description: 'Pipeline analytics.',
resolver: Resolvers::ProjectPipelineStatisticsResolver resolver: Resolvers::ProjectPipelineStatisticsResolver
field :ci_template, Types::Ci::TemplateType, null: true,
description: 'Find a single CI/CD template by name.',
resolver: Resolvers::Ci::TemplateResolver
def label(title:) def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args| BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder LabelsFinder
......
---
title: Add CI template field to project GraphQL type.
merge_request: 60276
author:
type: added
...@@ -7298,6 +7298,17 @@ Represents the total number of issues and their weights for a particular day. ...@@ -7298,6 +7298,17 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cistagejobs"></a>`jobs` | [`CiJobConnection`](#cijobconnection) | Jobs for the stage. (see [Connections](#connections)) | | <a id="cistagejobs"></a>`jobs` | [`CiJobConnection`](#cijobconnection) | Jobs for the stage. (see [Connections](#connections)) |
| <a id="cistagename"></a>`name` | [`String`](#string) | Name of the stage. | | <a id="cistagename"></a>`name` | [`String`](#string) | Name of the stage. |
### `CiTemplate`
GitLab CI/CD configuration template.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="citemplatecontent"></a>`content` | [`String!`](#string) | Contents of the CI template. |
| <a id="citemplatename"></a>`name` | [`String!`](#string) | Name of the CI template. |
### `ClusterAgent` ### `ClusterAgent`
#### Fields #### Fields
...@@ -10815,6 +10826,18 @@ four standard [pagination arguments](#connection-pagination-arguments): ...@@ -10815,6 +10826,18 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="projectboardsid"></a>`id` | [`BoardID`](#boardid) | Find a board by its ID. | | <a id="projectboardsid"></a>`id` | [`BoardID`](#boardid) | Find a board by its ID. |
##### `Project.ciTemplate`
Find a single CI/CD template by name.
Returns [`CiTemplate`](#citemplate).
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectcitemplatename"></a>`name` | [`String!`](#string) | Name of the CI/CD template to search for. |
##### `Project.clusterAgent` ##### `Project.clusterAgent`
Find a single cluster agent by name. Find a single cluster agent by name.
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Ci::TemplateResolver do
include GraphqlHelpers
describe '#resolve' do
let(:user) { create(:user) }
let(:project) { create(:project) }
subject(:resolve_subject) { resolve(described_class, obj: project, ctx: { current_user: user }, args: { name: template_name }) }
context 'when template exists' do
let(:template_name) { 'Android' }
it 'returns the found template' do
found_template = resolve_subject
expect(found_template).to be_an_instance_of(Gitlab::Template::GitlabCiYmlTemplate)
expect(found_template.name).to eq('Android')
end
end
context 'when template does not exist' do
let(:template_name) { 'invalidname' }
it 'returns nil' do
expect(resolve_subject).to eq(nil)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::Ci::TemplateType do
specify { expect(described_class.graphql_name).to eq('CiTemplate') }
it 'exposes the expected fields' do
expected_fields = %i[
name
content
]
expect(described_class).to have_graphql_fields(*expected_fields)
end
end
...@@ -32,6 +32,7 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -32,6 +32,7 @@ RSpec.describe GitlabSchema.types['Project'] do
issue_status_counts terraform_states alert_management_integrations issue_status_counts terraform_states alert_management_integrations
container_repositories container_repositories_count container_repositories container_repositories_count
pipeline_analytics squash_read_only sast_ci_configuration pipeline_analytics squash_read_only sast_ci_configuration
ci_template
] ]
expect(described_class).to include_graphql_fields(*expected_fields) expect(described_class).to include_graphql_fields(*expected_fields)
...@@ -379,4 +380,11 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -379,4 +380,11 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::Ci::JobType.connection_type) } it { is_expected.to have_graphql_type(Types::Ci::JobType.connection_type) }
it { is_expected.to have_graphql_arguments(:statuses) } it { is_expected.to have_graphql_arguments(:statuses) }
end end
describe 'ci_template field' do
subject { described_class.fields['ciTemplate'] }
it { is_expected.to have_graphql_type(Types::Ci::TemplateType) }
it { is_expected.to have_graphql_arguments(:name) }
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Querying CI template' do
include GraphqlHelpers
let_it_be(:project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
let(:query) do
<<~QUERY
{
project(fullPath: "#{project.full_path}") {
name
ciTemplate(name: "#{template_name}") {
name
content
}
}
}
QUERY
end
before do
post_graphql(query, current_user: user)
end
context 'when the template exists' do
let(:template_name) { 'Android' }
it_behaves_like 'a working graphql query'
it 'returns correct data' do
expect(graphql_data.dig('project', 'ciTemplate', 'name')).to eq(template_name)
expect(graphql_data.dig('project', 'ciTemplate', 'content')).not_to be_blank
end
end
context 'when the template does not exist' do
let(:template_name) { 'doesnotexist' }
it_behaves_like 'a working graphql query'
it 'returns correct data' do
expect(graphql_data.dig('project', 'ciTemplate')).to eq(nil)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment