Commit 211f728a authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'feature/gb/expose-commit-and-mr-pipelines-api' into 'master'

Expose pipelines API for commits and merge requests

See merge request !8837
parents adc0e41f 8e8ec9d7
...@@ -30,6 +30,17 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -30,6 +30,17 @@ class Projects::CommitController < Projects::ApplicationController
end end
def pipelines def pipelines
@pipelines = @commit.pipelines.order(id: :desc)
respond_to do |format|
format.html
format.json do
render json: PipelineSerializer
.new(project: @project, user: @current_user)
.with_pagination(request, response)
.represent(@pipelines)
end
end
end end
def branches def branches
......
...@@ -214,7 +214,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -214,7 +214,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render 'show' render 'show'
end end
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_pipelines') } }
format.json do
render json: {
html: view_to_html_string('projects/merge_requests/show/_pipelines'),
pipelines: PipelineSerializer
.new(project: @project, user: @current_user)
.with_pagination(request, response)
.represent(@pipelines)
}
end
end end
end end
......
...@@ -6,6 +6,7 @@ class BaseSerializer ...@@ -6,6 +6,7 @@ class BaseSerializer
def represent(resource, opts = {}) def represent(resource, opts = {})
self.class.entity_class self.class.entity_class
.represent(resource, opts.merge(request: @request)) .represent(resource, opts.merge(request: @request))
.as_json
end end
def self.entity(entity_class) def self.entity(entity_class)
......
class PipelineSerializer < BaseSerializer class PipelineSerializer < BaseSerializer
entity PipelineEntity
class InvalidResourceError < StandardError; end class InvalidResourceError < StandardError; end
include API::Helpers::Pagination include API::Helpers::Pagination
Struct.new('Pagination', :request, :response) Struct.new('Pagination', :request, :response)
entity PipelineEntity
def represent(resource, opts = {}) def represent(resource, opts = {})
if paginated? if paginated?
raise InvalidResourceError unless resource.respond_to?(:page) raise InvalidResourceError unless resource.respond_to?(:page)
......
- page_title "Pipelines", "#{@commit.title} (#{@commit.short_id})", "Commits" - page_title 'Pipelines', "#{@commit.title} (#{@commit.short_id})", 'Commits'
= render "commit_box" = render 'commit_box'
= render 'ci_menu'
= render "ci_menu" = render 'pipelines_list', pipelines: @pipelines
= render "pipelines_list", pipelines: @commit.pipelines.order(id: :desc)
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
end end
def as_json def as_json
AnalyticsStageSerializer.new.represent(self).as_json AnalyticsStageSerializer.new.represent(self)
end end
def title def title
......
...@@ -18,7 +18,7 @@ module Gitlab ...@@ -18,7 +18,7 @@ module Gitlab
private private
def serialize(event) def serialize(event)
AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json AnalyticsMergeRequestSerializer.new(project: @project).represent(event)
end end
end end
end end
......
...@@ -16,7 +16,7 @@ module Gitlab ...@@ -16,7 +16,7 @@ module Gitlab
private private
def serialize(event) def serialize(event)
AnalyticsIssueSerializer.new(project: @project).represent(event).as_json AnalyticsIssueSerializer.new(project: @project).represent(event)
end end
end end
end end
......
...@@ -37,7 +37,7 @@ module Gitlab ...@@ -37,7 +37,7 @@ module Gitlab
def serialize_commit(event, st_commit, query) def serialize_commit(event, st_commit, query)
commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project) commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit).as_json AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit)
end end
end end
end end
......
...@@ -15,7 +15,7 @@ module Gitlab ...@@ -15,7 +15,7 @@ module Gitlab
end end
def serialize(event) def serialize(event)
AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json AnalyticsMergeRequestSerializer.new(project: @project).represent(event)
end end
end end
end end
......
...@@ -16,7 +16,7 @@ module Gitlab ...@@ -16,7 +16,7 @@ module Gitlab
private private
def serialize(summary_object) def serialize(summary_object)
AnalyticsSummarySerializer.new.represent(summary_object).as_json AnalyticsSummarySerializer.new.represent(summary_object)
end end
end end
end end
......
...@@ -23,7 +23,7 @@ module Gitlab ...@@ -23,7 +23,7 @@ module Gitlab
private private
def serialize(event) def serialize(event)
AnalyticsBuildSerializer.new.represent(event['build']).as_json AnalyticsBuildSerializer.new.represent(event['build'])
end end
end end
end end
......
...@@ -4,7 +4,6 @@ describe Projects::CommitController do ...@@ -4,7 +4,6 @@ describe Projects::CommitController do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:commit) { project.commit("master") } let(:commit) { project.commit("master") }
let(:pipeline) { create(:ci_pipeline, project: project, commit: commit) }
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' } let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
let(:master_pickable_commit) { project.commit(master_pickable_sha) } let(:master_pickable_commit) { project.commit(master_pickable_sha) }
...@@ -322,11 +321,26 @@ describe Projects::CommitController do ...@@ -322,11 +321,26 @@ describe Projects::CommitController do
end end
context 'when the commit exists' do context 'when the commit exists' do
context 'when the commit has one or more pipelines' do context 'when the commit has pipelines' do
it 'shows pipelines' do before do
get_pipelines(id: commit.id) create(:ci_pipeline, project: project, sha: commit.id)
end
context 'when rendering a HTML format' do
it 'shows pipelines' do
get_pipelines(id: commit.id)
expect(response).to be_ok
end
end
expect(response).to be_ok context 'when rendering a JSON format' do
it 'responds with serialized pipelines' do
get_pipelines(id: commit.id, format: :json)
expect(response).to be_ok
expect(JSON.parse(response.body)).not_to be_empty
end
end end
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe Projects::MergeRequestsController do describe Projects::MergeRequestsController do
include ApiHelpers
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
...@@ -455,7 +457,7 @@ describe Projects::MergeRequestsController do ...@@ -455,7 +457,7 @@ describe Projects::MergeRequestsController do
it 'renders the diffs template to a string' do it 'renders the diffs template to a string' do
expect(response).to render_template('projects/merge_requests/show/_diffs') expect(response).to render_template('projects/merge_requests/show/_diffs')
expect(JSON.parse(response.body)).to have_key('html') expect(json_response).to have_key('html')
end end
end end
...@@ -494,7 +496,7 @@ describe Projects::MergeRequestsController do ...@@ -494,7 +496,7 @@ describe Projects::MergeRequestsController do
it 'renders the diffs template to a string' do it 'renders the diffs template to a string' do
expect(response).to render_template('projects/merge_requests/show/_diffs') expect(response).to render_template('projects/merge_requests/show/_diffs')
expect(JSON.parse(response.body)).to have_key('html') expect(json_response).to have_key('html')
end end
end end
end end
...@@ -662,18 +664,45 @@ describe Projects::MergeRequestsController do ...@@ -662,18 +664,45 @@ describe Projects::MergeRequestsController do
go format: 'json' go format: 'json'
expect(response).to render_template('projects/merge_requests/show/_commits') expect(response).to render_template('projects/merge_requests/show/_commits')
expect(JSON.parse(response.body)).to have_key('html') expect(json_response).to have_key('html')
end end
end end
end end
describe 'GET pipelines' do describe 'GET pipelines' do
it_behaves_like "loads labels", :pipelines before do
create(:ci_pipeline, project: merge_request.source_project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha)
end
context 'when using HTML format' do
it_behaves_like "loads labels", :pipelines
end
context 'when using JSON format' do
before do
get :pipelines,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: merge_request.iid,
format: :json
end
it 'responds with a rendered HTML partial' do
expect(response)
.to render_template('projects/merge_requests/show/_pipelines')
expect(json_response).to have_key 'html'
end
it 'responds with serialized pipelines' do
expect(json_response).to have_key 'pipelines'
expect(json_response['pipelines']).not_to be_empty
end
end
end end
describe 'GET conflicts' do describe 'GET conflicts' do
let(:json_response) { JSON.parse(response.body) }
context 'when the conflicts cannot be resolved in the UI' do context 'when the conflicts cannot be resolved in the UI' do
before do before do
allow_any_instance_of(Gitlab::Conflict::Parser). allow_any_instance_of(Gitlab::Conflict::Parser).
...@@ -770,8 +799,6 @@ describe Projects::MergeRequestsController do ...@@ -770,8 +799,6 @@ describe Projects::MergeRequestsController do
end end
describe 'GET conflict_for_path' do describe 'GET conflict_for_path' do
let(:json_response) { JSON.parse(response.body) }
def conflict_for_path(path) def conflict_for_path(path)
get :conflict_for_path, get :conflict_for_path,
namespace_id: merge_request_with_conflicts.project.namespace.to_param, namespace_id: merge_request_with_conflicts.project.namespace.to_param,
...@@ -826,7 +853,6 @@ describe Projects::MergeRequestsController do ...@@ -826,7 +853,6 @@ describe Projects::MergeRequestsController do
end end
context 'POST resolve_conflicts' do context 'POST resolve_conflicts' do
let(:json_response) { JSON.parse(response.body) }
let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha } let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha }
def resolve_conflicts(files) def resolve_conflicts(files)
...@@ -1024,7 +1050,6 @@ describe Projects::MergeRequestsController do ...@@ -1024,7 +1050,6 @@ describe Projects::MergeRequestsController do
let!(:forked) { create(:project) } let!(:forked) { create(:project) }
let!(:environment) { create(:environment, project: forked) } let!(:environment) { create(:environment, project: forked) }
let!(:deployment) { create(:deployment, environment: environment, sha: forked.commit.id, ref: 'master') } let!(:deployment) { create(:deployment, environment: environment, sha: forked.commit.id, ref: 'master') }
let(:json_response) { JSON.parse(response.body) }
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:merge_request) do let(:merge_request) do
......
require 'spec_helper' require 'spec_helper'
describe AnalyticsBuildSerializer do describe AnalyticsBuildSerializer do
let(:serializer) do
described_class
.new.represent(resource)
end
let(:json) { serializer.as_json }
let(:resource) { create(:ci_build) } let(:resource) { create(:ci_build) }
subject { described_class.new.represent(resource) }
context 'when there is a single object provided' do context 'when there is a single object provided' do
it 'contains important elements of analyticsBuild' do it 'contains important elements of analyticsBuild' do
expect(json) expect(subject)
.to include(:name, :branch, :short_sha, :date, :total_time, :url, :author) .to include(:name, :branch, :short_sha, :date, :total_time, :url, :author)
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe AnalyticsIssueSerializer do describe AnalyticsIssueSerializer do
let(:serializer) do subject do
described_class described_class
.new(project: project, entity: :merge_request) .new(project: project, entity: :merge_request)
.represent(resource) .represent(resource)
end end
let(:user) { create(:user) } let(:user) { create(:user) }
let(:json) { serializer.as_json }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:resource) do let(:resource) do
{ {
...@@ -23,7 +22,7 @@ describe AnalyticsIssueSerializer do ...@@ -23,7 +22,7 @@ describe AnalyticsIssueSerializer do
context 'when there is a single object provided' do context 'when there is a single object provided' do
it 'contains important elements of the issue' do it 'contains important elements of the issue' do
expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author) expect(subject).to include(:title, :iid, :created_at, :total_time, :url, :author)
end end
end end
end end
require 'spec_helper' require 'spec_helper'
describe AnalyticsMergeRequestSerializer do describe AnalyticsMergeRequestSerializer do
let(:serializer) do subject do
described_class described_class
.new(project: project, entity: :merge_request) .new(project: project, entity: :merge_request)
.represent(resource) .represent(resource)
end end
let(:user) { create(:user) } let(:user) { create(:user) }
let(:json) { serializer.as_json }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:resource) do let(:resource) do
{ {
...@@ -24,7 +23,7 @@ describe AnalyticsMergeRequestSerializer do ...@@ -24,7 +23,7 @@ describe AnalyticsMergeRequestSerializer do
context 'when there is a single object provided' do context 'when there is a single object provided' do
it 'contains important elements of the merge request' do it 'contains important elements of the merge request' do
expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author, :state) expect(subject).to include(:title, :iid, :created_at, :total_time, :url, :author, :state)
end end
end end
end end
require 'spec_helper' require 'spec_helper'
describe AnalyticsStageSerializer do describe AnalyticsStageSerializer do
let(:serializer) do subject do
described_class described_class.new.represent(resource)
.new.represent(resource)
end end
let(:json) { serializer.as_json } let(:resource) do
let(:resource) { Gitlab::CycleAnalytics::CodeStage.new(project: double, options: {}) } Gitlab::CycleAnalytics::CodeStage.new(project: double, options: {})
end
before do before do
allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(1.12) allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(1.12)
...@@ -15,10 +15,10 @@ describe AnalyticsStageSerializer do ...@@ -15,10 +15,10 @@ describe AnalyticsStageSerializer do
end end
it 'it generates payload for single object' do it 'it generates payload for single object' do
expect(json).to be_kind_of Hash expect(subject).to be_kind_of Hash
end end
it 'contains important elements of AnalyticsStage' do it 'contains important elements of AnalyticsStage' do
expect(json).to include(:title, :description, :value) expect(subject).to include(:title, :description, :value)
end end
end end
require 'spec_helper' require 'spec_helper'
describe AnalyticsSummarySerializer do describe AnalyticsSummarySerializer do
let(:serializer) do subject do
described_class described_class.new.represent(resource)
.new.represent(resource)
end end
let(:json) { serializer.as_json }
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:resource) do let(:resource) do
Gitlab::CycleAnalytics::Summary::Issue.new(project: double, Gitlab::CycleAnalytics::Summary::Issue
from: 1.day.ago, .new(project: double, from: 1.day.ago, current_user: user)
current_user: user)
end end
before do before do
allow_any_instance_of(Gitlab::CycleAnalytics::Summary::Issue).to receive(:value).and_return(1.12) allow_any_instance_of(Gitlab::CycleAnalytics::Summary::Issue)
.to receive(:value).and_return(1.12)
end end
it 'it generates payload for single object' do it 'it generates payload for single object' do
expect(json).to be_kind_of Hash expect(subject).to be_kind_of Hash
end end
it 'contains important elements of AnalyticsStage' do it 'contains important elements of AnalyticsStage' do
expect(json).to include(:title, :value) expect(subject).to include(:title, :value)
end end
end end
require 'spec_helper' require 'spec_helper'
describe EnvironmentSerializer do describe EnvironmentSerializer do
let(:serializer) do let(:user) { create(:user) }
let(:project) { create(:project) }
let(:json) do
described_class described_class
.new(user: user, project: project) .new(user: user, project: project)
.represent(resource) .represent(resource)
end end
let(:json) { serializer.as_json }
let(:user) { create(:user) }
let(:project) { create(:project) }
context 'when there is a single object provided' do context 'when there is a single object provided' do
before do before do
create(:ci_build, :manual, name: 'manual1', create(:ci_build, :manual, name: 'manual1',
......
...@@ -7,11 +7,7 @@ describe PipelineSerializer do ...@@ -7,11 +7,7 @@ describe PipelineSerializer do
described_class.new(user: user) described_class.new(user: user)
end end
let(:entity) do subject { serializer.represent(resource) }
serializer.represent(resource)
end
subject { entity.as_json }
describe '#represent' do describe '#represent' do
context 'when used without pagination' do context 'when used without pagination' do
......
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