Commit 5c888c42 authored by Jarka Kadlecova's avatar Jarka Kadlecova

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce

parents 806baa41 8500ec82
...@@ -73,34 +73,22 @@ ...@@ -73,34 +73,22 @@
<template> <template>
<div class="prometheus-state"> <div class="prometheus-state">
<div class="row"> <div class="state-svg svg-content">
<div class="col-md-4 col-md-offset-4 state-svg svg-content"> <img :src="currentState.svgUrl"/>
<img :src="currentState.svgUrl"/>
</div>
</div> </div>
<div class="row"> <h4 class="state-title">
<div class="col-md-6 col-md-offset-3"> {{currentState.title}}
<h4 class="text-center state-title"> </h4>
{{currentState.title}} <p class="state-description">
</h4> {{currentState.description}}
</div> <a v-if="showButtonDescription" :href="settingsPath">
</div> Prometheus server
<div class="row"> </a>
<div class="col-md-6 col-md-offset-3"> </p>
<div class="description-text text-center state-description"> <div class="state-button">
{{currentState.description}} <a class="btn btn-success" :href="buttonPath">
<a v-if="showButtonDescription" :href="settingsPath"> {{currentState.buttonText}}
Prometheus server </a>
</a>
</div>
</div>
</div>
<div class="row state-button-section">
<div class="col-md-4 col-md-offset-4 text-center state-button">
<a class="btn btn-success" :href="buttonPath">
{{currentState.buttonText}}
</a>
</div>
</div> </div>
</div> </div>
</template> </template>
...@@ -3,8 +3,5 @@ import Dashboard from './components/dashboard.vue'; ...@@ -3,8 +3,5 @@ import Dashboard from './components/dashboard.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({ document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#prometheus-graphs', el: '#prometheus-graphs',
components: { render: createElement => createElement(Dashboard),
Dashboard,
},
render: createElement => createElement('dashboard'),
})); }));
...@@ -74,8 +74,8 @@ export default { ...@@ -74,8 +74,8 @@ export default {
<thead v-if="!isMini"> <thead v-if="!isMini">
<tr> <tr>
<th class="name">Name</th> <th class="name">Name</th>
<th class="hidden-sm hidden-xs last-commit">Last Commit</th> <th class="hidden-sm hidden-xs last-commit">Last commit</th>
<th class="hidden-xs last-update text-right">Last Update</th> <th class="hidden-xs last-update text-right">Last update</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
......
...@@ -38,24 +38,40 @@ export default { ...@@ -38,24 +38,40 @@ export default {
return this.useCommitMessageWithDescription ? withoutDesc : withDesc; return this.useCommitMessageWithDescription ? withoutDesc : withDesc;
}, },
mergeButtonClass() { status() {
const defaultClass = 'btn btn-sm btn-success accept-merge-request';
const failedClass = `${defaultClass} btn-danger`;
const inActionClass = `${defaultClass} btn-info`;
const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr; const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr;
if (hasCI && !ciStatus) { if (hasCI && !ciStatus) {
return failedClass; return 'failed';
} else if (!pipeline) { } else if (!pipeline) {
return defaultClass; return 'success';
} else if (isPipelineActive) { } else if (isPipelineActive) {
return inActionClass; return 'pending';
} else if (isPipelineFailed) { } else if (isPipelineFailed) {
return 'failed';
}
return 'success';
},
mergeButtonClass() {
const defaultClass = 'btn btn-sm btn-success accept-merge-request';
const failedClass = `${defaultClass} btn-danger`;
const inActionClass = `${defaultClass} btn-info`;
if (this.status === 'failed') {
return failedClass; return failedClass;
} else if (this.status === 'pending') {
return inActionClass;
} }
return defaultClass; return defaultClass;
}, },
iconClass() {
if (this.status === 'failed' || !this.commitMessage.length || !this.isMergeAllowed() || this.mr.preventMerge) {
return 'failed';
}
return 'success';
},
mergeButtonText() { mergeButtonText() {
if (this.isMergingImmediately) { if (this.isMergingImmediately) {
return 'Merge in progress'; return 'Merge in progress';
...@@ -209,7 +225,7 @@ export default { ...@@ -209,7 +225,7 @@ export default {
}, },
template: ` template: `
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon status="success" /> <status-icon :status="iconClass" />
<div class="media-body"> <div class="media-body">
<div class="mr-widget-body-controls media space-children"> <div class="mr-widget-body-controls media space-children">
<span class="btn-group append-bottom-5"> <span class="btn-group append-bottom-5">
......
...@@ -207,10 +207,13 @@ ...@@ -207,10 +207,13 @@
} }
.prometheus-state { .prometheus-state {
margin-top: 10px; max-width: 430px;
margin: 10px auto;
text-align: center;
.state-button-section { .state-svg {
margin-top: 10px; max-width: 80vw;
margin: 0 auto;
} }
} }
......
...@@ -85,12 +85,21 @@ class ApplicationController < ActionController::Base ...@@ -85,12 +85,21 @@ class ApplicationController < ActionController::Base
super super
payload[:remote_ip] = request.remote_ip payload[:remote_ip] = request.remote_ip
if current_user.present? logged_user = auth_user
payload[:user_id] = current_user.id
payload[:username] = current_user.username if logged_user.present?
payload[:user_id] = logged_user.try(:id)
payload[:username] = logged_user.try(:username)
end end
end end
# Controllers such as GitHttpController may use alternative methods
# (e.g. tokens) to authenticate the user, whereas Devise sets current_user
def auth_user
return current_user if current_user.present?
return try(:authenticated_user)
end
# This filter handles both private tokens and personal access tokens # This filter handles both private tokens and personal access tokens
def authenticate_user_from_private_token! def authenticate_user_from_private_token!
token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence
......
...@@ -9,6 +9,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController ...@@ -9,6 +9,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true
alias_method :user, :actor alias_method :user, :actor
alias_method :authenticated_user, :actor
# Git clients will not know what authenticity token to send along # Git clients will not know what authenticity token to send along
skip_before_action :verify_authenticity_token skip_before_action :verify_authenticity_token
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
%th= s_('ProjectFileTree|Name') %th= s_('ProjectFileTree|Name')
%th.hidden-xs %th.hidden-xs
.pull-left= _('Last commit') .pull-left= _('Last commit')
%th.text-right= _('Last Update') %th.text-right= _('Last update')
- if @path.present? - if @path.present?
%tr.tree-item %tr.tree-item
%td.tree-item-file-name %td.tree-item-file-name
......
---
title: fix merge request widget status icon for failed CI
merge_request:
author:
type: fixed
---
title: Fix username and ID not logging in production_json.log for Git activity
merge_request:
author:
type: fixed
...@@ -142,9 +142,9 @@ and [projects APIs](../api/projects.md). ...@@ -142,9 +142,9 @@ and [projects APIs](../api/projects.md).
## Implementation details ## Implementation details
When GitLab receives an artifacts archive, an archive metadata file is also When GitLab receives an artifacts archive, an archive metadata file is also
generated. This metadata file describes all the entries that are located in the generated by [GitLab Workhorse]. This metadata file describes all the entries
artifacts archive itself. The metadata file is in a binary format, with that are located in the artifacts archive itself.
additional GZIP compression. The metadata file is in a binary format, with additional GZIP compression.
GitLab does not extract the artifacts archive in order to save space, memory GitLab does not extract the artifacts archive in order to save space, memory
and disk I/O. It instead inspects the metadata file which contains all the and disk I/O. It instead inspects the metadata file which contains all the
......
...@@ -8,8 +8,8 @@ msgid "" ...@@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-28 13:28-0400\n" "POT-Creation-Date: 2017-10-03 16:06-0400\n"
"PO-Revision-Date: 2017-09-28 13:28-0400\n" "PO-Revision-Date: 2017-10-03 16:06-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n" "Language: \n"
...@@ -420,9 +420,6 @@ msgstr "" ...@@ -420,9 +420,6 @@ msgstr ""
msgid "Create New Directory" msgid "Create New Directory"
msgstr "" msgstr ""
msgid "Create a new branch"
msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}." msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "" msgstr ""
...@@ -729,9 +726,6 @@ msgstr[1] "" ...@@ -729,9 +726,6 @@ msgstr[1] ""
msgid "Last Pipeline" msgid "Last Pipeline"
msgstr "" msgstr ""
msgid "Last Update"
msgstr ""
msgid "Last commit" msgid "Last commit"
msgstr "" msgstr ""
...@@ -741,6 +735,9 @@ msgstr "" ...@@ -741,6 +735,9 @@ msgstr ""
msgid "Last edited by %{name}" msgid "Last edited by %{name}"
msgstr "" msgstr ""
msgid "Last update"
msgstr ""
msgid "Last updated" msgid "Last updated"
msgstr "" msgstr ""
...@@ -1189,9 +1186,6 @@ msgstr "" ...@@ -1189,9 +1186,6 @@ msgstr ""
msgid "Select a timezone" msgid "Select a timezone"
msgstr "" msgstr ""
msgid "Select existing branch"
msgstr ""
msgid "Select target branch" msgid "Select target branch"
msgstr "" msgstr ""
...@@ -1493,9 +1487,6 @@ msgstr "" ...@@ -1493,9 +1487,6 @@ msgstr ""
msgid "Timeago|a week ago" msgid "Timeago|a week ago"
msgstr "" msgstr ""
msgid "Timeago|a while"
msgstr ""
msgid "Timeago|a year ago" msgid "Timeago|a year ago"
msgstr "" msgstr ""
...@@ -1547,6 +1538,9 @@ msgstr "" ...@@ -1547,6 +1538,9 @@ msgstr ""
msgid "Timeago|in 1 year" msgid "Timeago|in 1 year"
msgstr "" msgstr ""
msgid "Timeago|in a while"
msgstr ""
msgid "Timeago|less than a minute ago" msgid "Timeago|less than a minute ago"
msgstr "" msgstr ""
......
...@@ -23,8 +23,8 @@ describe('RepoSidebar', () => { ...@@ -23,8 +23,8 @@ describe('RepoSidebar', () => {
expect(vm.$el.id).toEqual('sidebar'); expect(vm.$el.id).toEqual('sidebar');
expect(vm.$el.classList.contains('sidebar-mini')).toBeFalsy(); expect(vm.$el.classList.contains('sidebar-mini')).toBeFalsy();
expect(thead.querySelector('.name').textContent).toEqual('Name'); expect(thead.querySelector('.name').textContent).toEqual('Name');
expect(thead.querySelector('.last-commit').textContent).toEqual('Last Commit'); expect(thead.querySelector('.last-commit').textContent).toEqual('Last commit');
expect(thead.querySelector('.last-update').textContent).toEqual('Last Update'); expect(thead.querySelector('.last-update').textContent).toEqual('Last update');
expect(tbody.querySelector('.repo-file-options')).toBeFalsy(); expect(tbody.querySelector('.repo-file-options')).toBeFalsy();
expect(tbody.querySelector('.prev-directory')).toBeFalsy(); expect(tbody.querySelector('.prev-directory')).toBeFalsy();
expect(tbody.querySelector('.loading-file')).toBeFalsy(); expect(tbody.querySelector('.loading-file')).toBeFalsy();
......
...@@ -95,35 +95,84 @@ describe('MRWidgetReadyToMerge', () => { ...@@ -95,35 +95,84 @@ describe('MRWidgetReadyToMerge', () => {
}); });
}); });
describe('status', () => {
it('defaults to success', () => {
vm.mr.pipeline = true;
expect(vm.status).toEqual('success');
});
it('returns failed when MR has CI but also has an unknown status', () => {
vm.mr.hasCI = true;
expect(vm.status).toEqual('failed');
});
it('returns default when MR has no pipeline', () => {
expect(vm.status).toEqual('success');
});
it('returns pending when pipeline is active', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
expect(vm.status).toEqual('pending');
});
it('returns failed when pipeline is failed', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineFailed = true;
expect(vm.status).toEqual('failed');
});
});
describe('mergeButtonClass', () => { describe('mergeButtonClass', () => {
const defaultClass = 'btn btn-sm btn-success accept-merge-request'; const defaultClass = 'btn btn-sm btn-success accept-merge-request';
const failedClass = `${defaultClass} btn-danger`; const failedClass = `${defaultClass} btn-danger`;
const inActionClass = `${defaultClass} btn-info`; const inActionClass = `${defaultClass} btn-info`;
it('should return default class', () => { it('defaults to success class', () => {
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns success class for success status', () => {
vm.mr.pipeline = true; vm.mr.pipeline = true;
expect(vm.mergeButtonClass).toEqual(defaultClass); expect(vm.mergeButtonClass).toEqual(defaultClass);
}); });
it('should return failed class when MR has CI but also has an unknown status', () => { it('returns info class for pending status', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
expect(vm.mergeButtonClass).toEqual(inActionClass);
});
it('returns failed class for failed status', () => {
vm.mr.hasCI = true; vm.mr.hasCI = true;
expect(vm.mergeButtonClass).toEqual(failedClass); expect(vm.mergeButtonClass).toEqual(failedClass);
}); });
});
it('should return default class when MR has no pipeline', () => { describe('status icon', () => {
expect(vm.mergeButtonClass).toEqual(defaultClass); it('defaults to tick icon', () => {
expect(vm.iconClass).toEqual('success');
}); });
it('should return in action class when pipeline is active', () => { it('shows tick for success status', () => {
vm.mr.pipeline = true;
expect(vm.iconClass).toEqual('success');
});
it('shows tick for pending status', () => {
vm.mr.pipeline = {}; vm.mr.pipeline = {};
vm.mr.isPipelineActive = true; vm.mr.isPipelineActive = true;
expect(vm.mergeButtonClass).toEqual(inActionClass); expect(vm.iconClass).toEqual('success');
}); });
it('should return failed class when pipeline is failed', () => { it('shows x for failed status', () => {
vm.mr.pipeline = {}; vm.mr.hasCI = true;
vm.mr.isPipelineFailed = true; expect(vm.iconClass).toEqual('failed');
expect(vm.mergeButtonClass).toEqual(failedClass); });
it('shows x for merge not allowed', () => {
vm.mr.hasCI = true;
expect(vm.iconClass).toEqual('failed');
}); });
}); });
...@@ -177,7 +226,7 @@ describe('MRWidgetReadyToMerge', () => { ...@@ -177,7 +226,7 @@ describe('MRWidgetReadyToMerge', () => {
expect(vm.isMergeButtonDisabled).toBeTruthy(); expect(vm.isMergeButtonDisabled).toBeTruthy();
}); });
it('should return true when there vm instance is making request', () => { it('should return true when the vm instance is making request', () => {
vm.isMakingRequest = true; vm.isMakingRequest = true;
expect(vm.isMergeButtonDisabled).toBeTruthy(); expect(vm.isMergeButtonDisabled).toBeTruthy();
}); });
......
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