Commit 1201f46a authored by Furkan Ayhan's avatar Furkan Ayhan Committed by Alper Akgun

Add project scope to ci clint graphql endpoint

We need project and user info in order to execute yaml processor
effectively.
parent d9958bf6
#import "~/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql"
query getCiConfigData($content: String!) {
ciConfig(content: $content) {
query getCiConfigData($projectPath: ID!, $content: String!) {
ciConfig(projectPath: $projectPath, content: $content) {
errors
status
stages {
......
......@@ -106,6 +106,7 @@ export default {
},
variables() {
return {
projectPath: this.projectPath,
content: this.contentModel,
};
},
......
......@@ -3,14 +3,27 @@
module Resolvers
module Ci
class ConfigResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
include ResolvesProject
type Types::Ci::Config::ConfigType, null: true
authorize :read_pipeline
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'The project of the CI config'
argument :content, GraphQL::STRING_TYPE,
required: true,
description: 'Contents of .gitlab-ci.yml'
def resolve(content:)
result = ::Gitlab::Ci::YamlProcessor.new(content).execute
def resolve(project_path:, content:)
project = authorized_find!(project_path: project_path)
result = ::Gitlab::Ci::YamlProcessor.new(content, project: project,
user: current_user,
sha: project.repository.commit.sha).execute
response = if result.errors.empty?
{
......@@ -55,6 +68,10 @@ module Resolvers
.group_by { |group| group[:stage] }
.map { |name, groups| { name: name, groups: groups } }
end
def find_object(project_path:)
resolve_project(full_path: project_path)
end
end
end
end
---
title: Add project scope to ci clint graphql endpoint
merge_request: 50418
author:
type: fixed
......@@ -19371,6 +19371,11 @@ type Query {
Contents of .gitlab-ci.yml
"""
content: String!
"""
The project of the CI config
"""
projectPath: ID!
): CiConfig
"""
......
......@@ -56487,6 +56487,20 @@
"name": "ciConfig",
"description": "Get linted and processed contents of a CI config. Should not be requested more than once per request.",
"args": [
{
"name": "projectPath",
"description": "The project of the CI config",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "content",
"description": "Contents of .gitlab-ci.yml",
......@@ -149,7 +149,7 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
beforeEach(() => {
mockBlobContentData = jest.fn();
mockCiConfigData = jest.fn().mockResolvedValue(mockCiConfigQueryResponse);
mockCiConfigData = jest.fn();
});
afterEach(() => {
......@@ -413,9 +413,13 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
});
});
describe('displays fetch content errors', () => {
it('no error is shown when data is set', async () => {
describe('when queries are called', () => {
beforeEach(() => {
mockBlobContentData.mockResolvedValue(mockCiYml);
mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
});
it('no error is shown when data is set', async () => {
createComponentWithApollo();
await waitForPromises();
......@@ -424,6 +428,17 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
expect(findEditorLite().attributes('value')).toBe(mockCiYml);
});
it('ci config query is called with correct variables', async () => {
createComponentWithApollo();
await waitForPromises();
expect(mockCiConfigData).toHaveBeenCalledWith({
content: mockCiYml,
projectPath: mockProjectPath,
});
});
it('shows a 404 error message', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
......
......@@ -13,6 +13,15 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
allow(::Gitlab::Ci::YamlProcessor).to receive(:new).and_return(yaml_processor_double)
end
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
subject(:response) do
resolve(described_class,
args: { project_path: project.full_path, content: content },
ctx: { current_user: user })
end
context 'with a valid .gitlab-ci.yml' do
let(:fake_result) do
::Gitlab::Ci::YamlProcessor::Result.new(
......@@ -27,8 +36,6 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
end
it 'lints the ci config file' do
response = resolve(described_class, args: { content: content }, ctx: {})
expect(response[:status]).to eq(:valid)
expect(response[:errors]).to be_empty
end
......@@ -46,8 +53,6 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
end
it 'responds with errors about invalid syntax' do
response = resolve(described_class, args: { content: content }, ctx: {})
expect(response[:status]).to eq(:invalid)
expect(response[:errors]).to eq(['Invalid configuration format'])
end
......
......@@ -7,7 +7,8 @@ RSpec.describe 'Query.ciConfig' do
subject(:post_graphql_query) { post_graphql(query, current_user: user) }
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
let_it_be(:content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_includes.yml'))
......@@ -16,7 +17,7 @@ RSpec.describe 'Query.ciConfig' do
let(:query) do
%(
query {
ciConfig(content: "#{content}") {
ciConfig(projectPath: "#{project.full_path}", content: "#{content}") {
status
errors
stages {
......@@ -47,13 +48,15 @@ RSpec.describe 'Query.ciConfig' do
)
end
it_behaves_like 'a working graphql query' do
before do
post_graphql_query
end
it_behaves_like 'a working graphql query'
end
it 'returns the correct structure' do
post_graphql_query
expect(graphql_data['ciConfig']).to eq(
"status" => "VALID",
"errors" => [],
......@@ -114,4 +117,75 @@ RSpec.describe 'Query.ciConfig' do
}
)
end
context 'when the config file includes other files' do
let_it_be(:content) do
YAML.dump(
include: 'other_file.yml',
rspec: {
script: 'rspec'
}
)
end
before do
allow_next_instance_of(Repository) do |repository|
allow(repository).to receive(:blob_data_at).with(an_instance_of(String), 'other_file.yml') do
YAML.dump(
build: {
script: 'build'
}
)
end
end
post_graphql_query
end
it_behaves_like 'a working graphql query'
it 'returns the correct structure with included files' do
expect(graphql_data['ciConfig']).to eq(
"status" => "VALID",
"errors" => [],
"stages" =>
{
"nodes" =>
[
{
"name" => "test",
"groups" =>
{
"nodes" =>
[
{
"name" => "build",
"size" => 1,
"jobs" =>
{
"nodes" =>
[
{ "name" => "build", "groupName" => "build", "stage" => "test", "needs" => { "nodes" => [] } }
]
}
},
{
"name" => "rspec",
"size" => 1,
"jobs" =>
{
"nodes" =>
[
{ "name" => "rspec", "groupName" => "rspec", "stage" => "test", "needs" => { "nodes" => [] } }
]
}
}
]
}
}
]
}
)
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