summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2019-06-28 10:02:57 +0000
committerLin Jen-Shin <godfat@godfat.org>2019-06-28 10:02:57 +0000
commit2321b337f1487031e2cab8e1a4e778f3aaf8e2da (patch)
tree09ac0a7fe65e4da93f873e4b8cf02b57cd359791
parent1012cfb0b780bc9348a8478a66af2a337a69b0f6 (diff)
parentd78f7ceac94abe0e8318c6472fc5f7967325a74f (diff)
downloadgitlab-ce-2321b337f1487031e2cab8e1a4e778f3aaf8e2da.tar.gz
Merge branch 'graphql-tree-last-commit' into 'master'
Added commit type to tree GraphQL type See merge request gitlab-org/gitlab-ce!29412
-rw-r--r--app/graphql/types/commit_type.rb30
-rw-r--r--app/graphql/types/tree/tree_type.rb5
-rw-r--r--app/models/ci/pipeline.rb5
-rw-r--r--app/presenters/commit_presenter.rb8
-rw-r--r--changelogs/unreleased/graphql-tree-last-commit.yml5
-rw-r--r--lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb25
-rw-r--r--spec/graphql/gitlab_schema_spec.rb2
-rw-r--r--spec/graphql/types/commit_type_spec.rb11
-rw-r--r--spec/graphql/types/tree/tree_type_spec.rb2
-rw-r--r--spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb20
-rw-r--r--spec/models/ci/pipeline_spec.rb11
-rw-r--r--spec/requests/api/graphql/project/tree/tree_spec.rb18
12 files changed, 139 insertions, 3 deletions
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
new file mode 100644
index 00000000000..d73dd73affd
--- /dev/null
+++ b/app/graphql/types/commit_type.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Types
+ class CommitType < BaseObject
+ graphql_name 'Commit'
+
+ authorize :download_code
+
+ present_using CommitPresenter
+
+ field :id, type: GraphQL::ID_TYPE, null: false
+ field :sha, type: GraphQL::STRING_TYPE, null: false
+ field :title, type: GraphQL::STRING_TYPE, null: true
+ field :description, type: GraphQL::STRING_TYPE, null: true
+ field :message, type: GraphQL::STRING_TYPE, null: true
+ field :authored_date, type: Types::TimeType, null: true
+ field :web_url, type: GraphQL::STRING_TYPE, null: false
+
+ # models/commit lazy loads the author by email
+ field :author, type: Types::UserType, null: true
+
+ field :latest_pipeline,
+ type: Types::Ci::PipelineType,
+ null: true,
+ description: "Latest pipeline for this commit",
+ resolve: -> (obj, ctx, args) do
+ Gitlab::Graphql::Loaders::PipelineForShaLoader.new(obj.project, obj.sha).find_last
+ end
+ end
+end
diff --git a/app/graphql/types/tree/tree_type.rb b/app/graphql/types/tree/tree_type.rb
index 1ee93ed9542..cbc448a0695 100644
--- a/app/graphql/types/tree/tree_type.rb
+++ b/app/graphql/types/tree/tree_type.rb
@@ -4,6 +4,11 @@ module Types
class TreeType < BaseObject
graphql_name 'Tree'
+ # Complexity 10 as it triggers a Gitaly call on each render
+ field :last_commit, Types::CommitType, null: true, complexity: 10, resolve: -> (tree, args, ctx) do
+ tree.repository.last_commit_for_path(tree.sha, tree.path)
+ end
+
field :trees, Types::Tree::TreeEntryType.connection_type, null: false, resolve: -> (obj, args, ctx) do
Gitlab::Graphql::Representation::TreeEntry.decorate(obj.trees, obj.repository)
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 3727a9861aa..fd5aa216174 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -295,6 +295,11 @@ module Ci
end
end
+ def self.latest_for_shas(shas)
+ max_id_per_sha = for_sha(shas).group(:sha).select("max(id)")
+ where(id: max_id_per_sha)
+ end
+
def self.latest_successful_ids_per_project
success.group(:project_id).select('max(id) as id')
end
diff --git a/app/presenters/commit_presenter.rb b/app/presenters/commit_presenter.rb
index 05adbe1d4f5..fc9853733c1 100644
--- a/app/presenters/commit_presenter.rb
+++ b/app/presenters/commit_presenter.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-class CommitPresenter < Gitlab::View::Presenter::Simple
+class CommitPresenter < Gitlab::View::Presenter::Delegated
+ include GlobalID::Identification
+
presents :commit
def status_for(ref)
@@ -10,4 +12,8 @@ class CommitPresenter < Gitlab::View::Presenter::Simple
def any_pipelines?
can?(current_user, :read_pipeline, commit.project) && commit.pipelines.any?
end
+
+ def web_url
+ Gitlab::UrlBuilder.new(commit).url
+ end
end
diff --git a/changelogs/unreleased/graphql-tree-last-commit.yml b/changelogs/unreleased/graphql-tree-last-commit.yml
new file mode 100644
index 00000000000..5104ca6687e
--- /dev/null
+++ b/changelogs/unreleased/graphql-tree-last-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Added commit type to tree GraphQL response
+merge_request: 29412
+author:
+type: added
diff --git a/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb b/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb
new file mode 100644
index 00000000000..81c5cabf451
--- /dev/null
+++ b/lib/gitlab/graphql/loaders/pipeline_for_sha_loader.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Loaders
+ class PipelineForShaLoader
+ attr_accessor :project, :sha
+
+ def initialize(project, sha)
+ @project, @sha = project, sha
+ end
+
+ def find_last
+ BatchLoader.for(sha).batch(key: project) do |shas, loader, args|
+ pipelines = args[:key].ci_pipelines.latest_for_shas(shas)
+
+ pipelines.each do |pipeline|
+ loader.call(pipeline.sha, pipeline)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 4076c1f824b..d36e428a8ee 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -113,7 +113,7 @@ describe GitlabSchema do
end
it "raises a meaningful error if a global id couldn't be generated" do
- expect { described_class.id_from_object(build(:commit)) }
+ expect { described_class.id_from_object(build(:wiki_directory)) }
.to raise_error(RuntimeError, /include `GlobalID::Identification` into/i)
end
end
diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb
new file mode 100644
index 00000000000..5d8edcf254c
--- /dev/null
+++ b/spec/graphql/types/commit_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['Commit'] do
+ it { expect(described_class.graphql_name).to eq('Commit') }
+
+ it { expect(described_class).to require_graphql_authorizations(:download_code) }
+
+ it { expect(described_class).to have_graphql_fields(:id, :sha, :title, :description, :message, :authored_date, :author, :web_url, :latest_pipeline) }
+end
diff --git a/spec/graphql/types/tree/tree_type_spec.rb b/spec/graphql/types/tree/tree_type_spec.rb
index b9c5570115e..23779d75600 100644
--- a/spec/graphql/types/tree/tree_type_spec.rb
+++ b/spec/graphql/types/tree/tree_type_spec.rb
@@ -5,5 +5,5 @@ require 'spec_helper'
describe Types::Tree::TreeType do
it { expect(described_class.graphql_name).to eq('Tree') }
- it { expect(described_class).to have_graphql_fields(:trees, :submodules, :blobs) }
+ it { expect(described_class).to have_graphql_fields(:trees, :submodules, :blobs, :last_commit) }
end
diff --git a/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb
new file mode 100644
index 00000000000..927476cc655
--- /dev/null
+++ b/spec/lib/gitlab/graphql/loaders/pipeline_for_sha_loader_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Graphql::Loaders::PipelineForShaLoader do
+ include GraphqlHelpers
+
+ describe '#find_last' do
+ it 'batch-resolves latest pipeline' do
+ project = create(:project, :repository)
+ pipeline1 = create(:ci_pipeline, project: project, ref: project.default_branch, sha: project.commit.sha)
+ pipeline2 = create(:ci_pipeline, project: project, ref: project.default_branch, sha: project.commit.sha)
+ pipeline3 = create(:ci_pipeline, project: project, ref: 'improve/awesome', sha: project.commit('improve/awesome').sha)
+
+ result = batch(max_queries: 1) do
+ [pipeline1.sha, pipeline3.sha].map { |sha| described_class.new(project, sha).find_last }
+ end
+
+ expect(result).to contain_exactly(pipeline2, pipeline3)
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 6ebc6337d50..55cea48b641 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1886,6 +1886,17 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.latest_for_shas' do
+ let(:sha) { 'abc' }
+
+ it 'returns latest pipeline for sha' do
+ create(:ci_pipeline, sha: sha)
+ pipeline2 = create(:ci_pipeline, sha: sha)
+
+ expect(described_class.latest_for_shas(sha)).to contain_exactly(pipeline2)
+ end
+ end
+
describe '.latest_successful_ids_per_project' do
let(:projects) { create_list(:project, 2) }
let!(:pipeline1) { create(:ci_pipeline, :success, project: projects[0]) }
diff --git a/spec/requests/api/graphql/project/tree/tree_spec.rb b/spec/requests/api/graphql/project/tree/tree_spec.rb
index b07aa1e12d3..94128cc21ee 100644
--- a/spec/requests/api/graphql/project/tree/tree_spec.rb
+++ b/spec/requests/api/graphql/project/tree/tree_spec.rb
@@ -33,6 +33,12 @@ describe 'getting a tree in a project' do
expect(graphql_data['project']['repository']['tree']['submodules']['edges']).to eq([])
expect(graphql_data['project']['repository']['tree']['blobs']['edges']).to eq([])
end
+
+ it 'returns null commit' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['last_commit']).to be_nil
+ end
end
context 'when ref does not exist' do
@@ -45,6 +51,12 @@ describe 'getting a tree in a project' do
expect(graphql_data['project']['repository']['tree']['submodules']['edges']).to eq([])
expect(graphql_data['project']['repository']['tree']['blobs']['edges']).to eq([])
end
+
+ it 'returns null commit' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['last_commit']).to be_nil
+ end
end
context 'when ref and path exist' do
@@ -61,6 +73,12 @@ describe 'getting a tree in a project' do
expect(graphql_data['project']['repository']['tree']['blobs']['edges'].size).to be > 0
expect(graphql_data['project']['repository']['tree']['submodules']['edges'].size).to be > 0
end
+
+ it 'returns tree latest commit' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['tree']['lastCommit']).to be_present
+ end
end
context 'when current user is nil' do