Commit d7a3ccb4 authored by Fatih Acet's avatar Fatih Acet

Merge branch '49329-mr-show-commit-details' into 'master'

Add signature badge and pipeline status to commit details in MR diff

Closes #49329

See merge request gitlab-org/gitlab-ce!22079
parents 22de07ac becb86ea
...@@ -5,6 +5,7 @@ import Icon from '~/vue_shared/components/icon.vue'; ...@@ -5,6 +5,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CIIcon from '~/vue_shared/components/ci_icon.vue'; import CIIcon from '~/vue_shared/components/ci_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
/** /**
* CommitItem * CommitItem
...@@ -29,6 +30,7 @@ export default { ...@@ -29,6 +30,7 @@ export default {
ClipboardButton, ClipboardButton,
CIIcon, CIIcon,
TimeAgoTooltip, TimeAgoTooltip,
CommitPipelineStatus,
}, },
props: { props: {
commit: { commit: {
...@@ -102,6 +104,14 @@ export default { ...@@ -102,6 +104,14 @@ export default {
></pre> ></pre>
</div> </div>
<div class="commit-actions flex-row d-none d-sm-flex"> <div class="commit-actions flex-row d-none d-sm-flex">
<div
v-if="commit.signatureHtml"
v-html="commit.signatureHtml"
></div>
<commit-pipeline-status
v-if="commit.pipelineStatusPath"
:endpoint="commit.pipelineStatusPath"
/>
<div class="commit-sha-group"> <div class="commit-sha-group">
<div <div
class="label label-monospace" class="label label-monospace"
......
...@@ -25,7 +25,13 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic ...@@ -25,7 +25,13 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
@diffs.write_cache @diffs.write_cache
render json: DiffsSerializer.new(current_user: current_user, project: @merge_request.project).represent(@diffs, additional_attributes) request = {
current_user: current_user,
project: @merge_request.project,
render: ->(partial, locals) { view_to_html_string(partial, locals) }
}
render json: DiffsSerializer.new(request).represent(@diffs, additional_attributes)
end end
def define_diff_vars def define_diff_vars
......
...@@ -319,7 +319,11 @@ class Commit ...@@ -319,7 +319,11 @@ class Commit
def status(ref = nil) def status(ref = nil)
return @statuses[ref] if @statuses.key?(ref) return @statuses[ref] if @statuses.key?(ref)
@statuses[ref] = project.pipelines.latest_status_per_commit(id, ref)[id] @statuses[ref] = status_for_project(ref, project)
end
def status_for_project(ref, pipeline_project)
pipeline_project.pipelines.latest_status_per_commit(id, ref)[id]
end end
def set_status_for_ref(ref, status) def set_status_for_ref(ref, status)
......
...@@ -25,4 +25,25 @@ class CommitEntity < API::Entities::Commit ...@@ -25,4 +25,25 @@ class CommitEntity < API::Entities::Commit
expose :title_html, if: { type: :full } do |commit| expose :title_html, if: { type: :full } do |commit|
markdown_field(commit, :title) markdown_field(commit, :title)
end end
expose :signature_html, if: { type: :full } do |commit|
render('projects/commit/_signature', signature: commit.signature) if commit.has_signature?
end
expose :pipeline_status_path, if: { type: :full } do |commit, options|
pipeline_ref = options[:pipeline_ref]
pipeline_project = options[:pipeline_project] || commit.project
next unless pipeline_ref && pipeline_project
status = commit.status_for_project(pipeline_ref, pipeline_project)
next unless status
pipelines_project_commit_path(pipeline_project, commit.id, ref: pipeline_ref)
end
def render(*args)
return unless request.respond_to?(:render) && request.render.respond_to?(:call)
request.render.call(*args)
end
end end
...@@ -18,7 +18,9 @@ class DiffsEntity < Grape::Entity ...@@ -18,7 +18,9 @@ class DiffsEntity < Grape::Entity
expose :commit do |diffs, options| expose :commit do |diffs, options|
CommitEntity.represent options[:commit], options.merge( CommitEntity.represent options[:commit], options.merge(
type: :full, type: :full,
commit_url_params: { merge_request_iid: merge_request&.iid } commit_url_params: { merge_request_iid: merge_request&.iid },
pipeline_ref: merge_request&.source_branch,
pipeline_project: merge_request&.source_project
) )
end end
......
...@@ -9,6 +9,8 @@ import getDiffWithCommit from '../mock_data/diff_with_commit'; ...@@ -9,6 +9,8 @@ import getDiffWithCommit from '../mock_data/diff_with_commit';
const TEST_AUTHOR_NAME = 'test'; const TEST_AUTHOR_NAME = 'test';
const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com'; const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=36`; const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=36`;
const TEST_SIGNATURE_HTML = '<a>Legit commit</a>';
const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`;
const getTitleElement = vm => vm.$el.querySelector('.commit-row-message.item-title'); const getTitleElement = vm => vm.$el.querySelector('.commit-row-message.item-title');
const getDescElement = vm => vm.$el.querySelector('pre.commit-row-description'); const getDescElement = vm => vm.$el.querySelector('pre.commit-row-description');
...@@ -16,6 +18,7 @@ const getDescExpandElement = vm => vm.$el.querySelector('.commit-content .text-e ...@@ -16,6 +18,7 @@ const getDescExpandElement = vm => vm.$el.querySelector('.commit-content .text-e
const getShaElement = vm => vm.$el.querySelector('.commit-sha-group'); const getShaElement = vm => vm.$el.querySelector('.commit-sha-group');
const getAvatarElement = vm => vm.$el.querySelector('.user-avatar-link'); const getAvatarElement = vm => vm.$el.querySelector('.user-avatar-link');
const getCommitterElement = vm => vm.$el.querySelector('.commiter'); const getCommitterElement = vm => vm.$el.querySelector('.commiter');
const getCommitActionsElement = vm => vm.$el.querySelector('.commit-actions');
describe('diffs/components/commit_widget', () => { describe('diffs/components/commit_widget', () => {
const Component = Vue.extend(CommitItem); const Component = Vue.extend(CommitItem);
...@@ -125,4 +128,36 @@ describe('diffs/components/commit_widget', () => { ...@@ -125,4 +128,36 @@ describe('diffs/components/commit_widget', () => {
expect(nameElement).toHaveText(TEST_AUTHOR_NAME); expect(nameElement).toHaveText(TEST_AUTHOR_NAME);
}); });
}); });
describe('with signature', () => {
beforeEach(done => {
vm.commit.signatureHtml = TEST_SIGNATURE_HTML;
vm.$nextTick()
.then(done)
.catch(done.fail);
});
it('renders signature html', () => {
const actionsElement = getCommitActionsElement(vm);
expect(actionsElement).toContainHtml(TEST_SIGNATURE_HTML);
});
});
describe('with pipeline status', () => {
beforeEach(done => {
vm.commit.pipelineStatusPath = TEST_PIPELINE_STATUS_PATH;
vm.$nextTick()
.then(done)
.catch(done.fail);
});
it('renders pipeline status', () => {
const actionsElement = getCommitActionsElement(vm);
expect(actionsElement).toContainElement('.ci-status-link');
});
});
}); });
require 'spec_helper' require 'spec_helper'
describe CommitEntity do describe CommitEntity do
SIGNATURE_HTML = 'TEST'.freeze
let(:entity) do let(:entity) do
described_class.new(commit, request: request) described_class.new(commit, request: request)
end end
let(:request) { double('request') } let(:request) { double('request') }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:commit) { project.commit } let(:commit) { project.commit }
...@@ -12,7 +13,11 @@ describe CommitEntity do ...@@ -12,7 +13,11 @@ describe CommitEntity do
subject { entity.as_json } subject { entity.as_json }
before do before do
render = double('render')
allow(render).to receive(:call).and_return(SIGNATURE_HTML)
allow(request).to receive(:project).and_return(project) allow(request).to receive(:project).and_return(project)
allow(request).to receive(:render).and_return(render)
end end
context 'when commit author is a user' do context 'when commit author is a user' do
...@@ -61,7 +66,7 @@ describe CommitEntity do ...@@ -61,7 +66,7 @@ describe CommitEntity do
context 'when type is "full"' do context 'when type is "full"' do
let(:entity) do let(:entity) do
described_class.new(commit, request: request, type: :full) described_class.new(commit, request: request, type: :full, pipeline_ref: project.default_branch, pipeline_project: project)
end end
it 'exposes extra properties' do it 'exposes extra properties' do
...@@ -70,6 +75,25 @@ describe CommitEntity do ...@@ -70,6 +75,25 @@ describe CommitEntity do
expect(subject.fetch(:description_html)).not_to be_nil expect(subject.fetch(:description_html)).not_to be_nil
expect(subject.fetch(:title_html)).not_to be_nil expect(subject.fetch(:title_html)).not_to be_nil
end end
context 'when commit has signature' do
let(:commit) { project.commit(TestEnv::BRANCH_SHA['signed-commits']) }
it 'exposes "signature_html"' do
expect(request.render).to receive(:call)
expect(subject.fetch(:signature_html)).to be SIGNATURE_HTML
end
end
context 'when commit has pipeline' do
before do
create(:ci_pipeline, project: project, sha: commit.id)
end
it 'exposes "pipeline_status_path"' do
expect(subject.fetch(:pipeline_status_path)).not_to be_nil
end
end
end end
context 'when commit_url_params is set' do context 'when commit_url_params is set' 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