Commit 13b5f925 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents f6d8206f f97a73fa
......@@ -182,7 +182,7 @@ export default class CreateMergeRequestDropdown {
}
enable() {
if (!canCreateConfidentialMergeRequest()) return;
if (isConfidentialIssue() && !canCreateConfidentialMergeRequest()) return;
this.createMergeRequestButton.classList.remove('disabled');
this.createMergeRequestButton.removeAttribute('disabled');
......
<script>
import { GlDropdown, GlDropdownDivider, GlDropdownHeader, GlDropdownItem } from '@gitlab/ui';
import { __ } from '../../locale';
import Icon from '../../vue_shared/components/icon.vue';
import getRefMixin from '../mixins/get_ref';
import getProjectShortPath from '../queries/getProjectShortPath.query.graphql';
import getProjectPath from '../queries/getProjectPath.query.graphql';
import getPermissions from '../queries/getPermissions.query.graphql';
const ROW_TYPES = {
header: 'header',
divider: 'divider',
};
export default {
components: {
GlDropdown,
GlDropdownDivider,
GlDropdownHeader,
GlDropdownItem,
Icon,
},
apollo: {
projectShortPath: {
query: getProjectShortPath,
},
projectPath: {
query: getProjectPath,
},
userPermissions: {
query: getPermissions,
variables() {
return {
projectPath: this.projectPath,
};
},
update: data => data.project.userPermissions,
},
},
mixins: [getRefMixin],
props: {
......@@ -15,10 +44,52 @@ export default {
required: false,
default: '/',
},
canCollaborate: {
type: Boolean,
required: false,
default: false,
},
canEditTree: {
type: Boolean,
required: false,
default: false,
},
newBranchPath: {
type: String,
required: false,
default: null,
},
newTagPath: {
type: String,
required: false,
default: null,
},
newBlobPath: {
type: String,
required: false,
default: null,
},
forkNewBlobPath: {
type: String,
required: false,
default: null,
},
forkNewDirectoryPath: {
type: String,
required: false,
default: null,
},
forkUploadBlobPath: {
type: String,
required: false,
default: null,
},
},
data() {
return {
projectShortPath: '',
projectPath: '',
userPermissions: {},
};
},
computed: {
......@@ -39,11 +110,112 @@ export default {
[{ name: this.projectShortPath, path: '/', to: `/tree/${this.ref}/` }],
);
},
canCreateMrFromFork() {
return this.userPermissions.forkProject && this.userPermissions.createMergeRequestIn;
},
dropdownItems() {
const items = [];
if (this.canEditTree) {
items.push(
{
type: ROW_TYPES.header,
text: __('This directory'),
},
{
attrs: {
href: this.newBlobPath,
class: 'qa-new-file-option',
},
text: __('New file'),
},
{
attrs: {
href: '#modal-upload-blob',
'data-target': '#modal-upload-blob',
'data-toggle': 'modal',
},
text: __('Upload file'),
},
{
attrs: {
href: '#modal-create-new-dir',
'data-target': '#modal-create-new-dir',
'data-toggle': 'modal',
},
text: __('New directory'),
},
);
} else if (this.canCreateMrFromFork) {
items.push(
{
attrs: {
href: this.forkNewBlobPath,
'data-method': 'post',
},
text: __('New file'),
},
{
attrs: {
href: this.forkUploadBlobPath,
'data-method': 'post',
},
text: __('Upload file'),
},
{
attrs: {
href: this.forkNewDirectoryPath,
'data-method': 'post',
},
text: __('New directory'),
},
);
}
if (this.userPermissions.pushCode) {
items.push(
{
type: ROW_TYPES.divider,
},
{
type: ROW_TYPES.header,
text: __('This repository'),
},
{
attrs: {
href: this.newBranchPath,
},
text: __('New branch'),
},
{
attrs: {
href: this.newTagPath,
},
text: __('New tag'),
},
);
}
return items;
},
renderAddToTreeDropdown() {
return this.canCollaborate || this.canCreateMrFromFork;
},
},
methods: {
isLast(i) {
return i === this.pathLinks.length - 1;
},
getComponent(type) {
switch (type) {
case ROW_TYPES.divider:
return 'gl-dropdown-divider';
case ROW_TYPES.header:
return 'gl-dropdown-header';
default:
return 'gl-dropdown-item';
}
},
},
};
</script>
......@@ -56,6 +228,20 @@ export default {
{{ link.name }}
</router-link>
</li>
<li v-if="renderAddToTreeDropdown" class="breadcrumb-item">
<gl-dropdown toggle-class="add-to-tree qa-add-to-tree ml-1">
<template slot="button-content">
<span class="sr-only">{{ __('Add to tree') }}</span>
<icon name="plus" :size="16" class="float-left" />
<icon name="arrow-down" :size="16" class="float-left" />
</template>
<template v-for="(item, i) in dropdownItems">
<component :is="getComponent(item.type)" :key="i" v-bind="item.attrs">
{{ item.text }}
</component>
</template>
</gl-dropdown>
</li>
</ol>
</nav>
</template>
......@@ -5,6 +5,7 @@ import Breadcrumbs from './components/breadcrumbs.vue';
import LastCommit from './components/last_commit.vue';
import apolloProvider from './graphql';
import { setTitle } from './utils/title';
import { parseBoolean } from '../lib/utils/common_utils';
export default function setupVueRepositoryList() {
const el = document.getElementById('js-tree-list');
......@@ -36,19 +37,42 @@ export default function setupVueRepositoryList() {
.forEach(elem => elem.classList.toggle('hidden', !isRoot));
});
// eslint-disable-next-line no-new
new Vue({
el: document.getElementById('js-repo-breadcrumb'),
router,
apolloProvider,
render(h) {
return h(Breadcrumbs, {
props: {
currentPath: this.$route.params.pathMatch,
},
});
},
});
const breadcrumbEl = document.getElementById('js-repo-breadcrumb');
if (breadcrumbEl) {
const {
canCollaborate,
canEditTree,
newBranchPath,
newTagPath,
newBlobPath,
forkNewBlobPath,
forkNewDirectoryPath,
forkUploadBlobPath,
} = breadcrumbEl.dataset;
// eslint-disable-next-line no-new
new Vue({
el: breadcrumbEl,
router,
apolloProvider,
render(h) {
return h(Breadcrumbs, {
props: {
currentPath: this.$route.params.pathMatch,
canCollaborate: parseBoolean(canCollaborate),
canEditTree: parseBoolean(canEditTree),
newBranchPath,
newTagPath,
newBlobPath,
forkNewBlobPath,
forkNewDirectoryPath,
forkUploadBlobPath,
},
});
},
});
}
// eslint-disable-next-line no-new
new Vue({
......
query getPermissions($projectPath: ID!) {
project(fullPath: $projectPath) {
userPermissions {
pushCode
forkProject
createMergeRequestIn
}
}
}
......@@ -154,6 +154,38 @@ module TreeHelper
"logs-path" => logs_path
}
end
def breadcrumb_data_attributes
attrs = {
can_collaborate: can_collaborate_with_project?(@project).to_s,
new_blob_path: project_new_blob_path(@project, @id),
new_branch_path: new_project_branch_path(@project),
new_tag_path: new_project_tag_path(@project),
can_edit_tree: can_edit_tree?.to_s
}
if can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
continue_param = {
to: project_new_blob_path(@project, @id),
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now
}
attrs.merge!(
fork_new_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param),
fork_new_directory_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
to: request.fullpath,
notice: _("%{edit_in_new_fork_notice} Try to create a new directory again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
})),
fork_upload_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
to: request.fullpath,
notice: _("%{edit_in_new_fork_notice} Try to upload a file again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
}))
)
end
attrs
end
end
TreeHelper.prepend(::EE::TreeHelper)
......@@ -20,6 +20,9 @@
- if vue_file_list_enabled?
#js-tree-list{ data: { project_path: @project.full_path, project_short_path: @project.path, ref: ref, full_name: @project.name_with_namespace } }
- if can_edit_tree?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'
- if @tree.readme
= render "projects/tree/readme", readme: @tree.readme
- else
......
......@@ -11,7 +11,7 @@
- addtotree_toggle_attributes = { title: _("You can only add files when you are on a branch"), data: { container: 'body' }, class: 'disabled has-tooltip' }
- if vue_file_list_enabled?
#js-repo-breadcrumb
#js-repo-breadcrumb{ data: breadcrumb_data_attributes }
- else
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
......
---
title: Update example Prometheus scrape config
merge_request: 30739
author:
type: other
......@@ -134,17 +134,57 @@ To use an external Prometheus server:
```yaml
scrape_configs:
- job_name: 'gitlab_exporters'
- job_name: nginx
static_configs:
- targets: ['1.1.1.1:9168', '1.1.1.1:9236', '1.1.1.1:9236', '1.1.1.1:9100', '1.1.1.1:9121', '1.1.1.1:9187']
- job_name: 'gitlab_metrics'
metrics_path: /-/metrics
- targets:
- 1.1.1.1:8060
- job_name: redis
static_configs:
- targets:
- 1.1.1.1:9121
- job_name: postgres
static_configs:
- targets:
- 1.1.1.1:9187
- job_name: node
static_configs:
- targets:
- 1.1.1.1:9100
- job_name: gitlab-workhorse
static_configs:
- targets:
- 1.1.1.1:9229
- job_name: gitlab-rails
metrics_path: "/-/metrics"
static_configs:
- targets:
- 1.1.1.1:8080
- job_name: gitlab-sidekiq
static_configs:
- targets:
- 1.1.1.1:8082
- job_name: gitlab_monitor_database
metrics_path: "/database"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitlab_monitor_sidekiq
metrics_path: "/sidekiq"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitlab_monitor_process
metrics_path: "/process"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitaly
static_configs:
- targets: ['1.1.1.1:443']
- targets:
- 1.1.1.1:9236
```
1. Restart the Prometheus server.
1. Reload the Prometheus server.
## Viewing performance metrics
......
......@@ -257,7 +257,7 @@ sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4]
To check the status of migrations, you can use the following rake task:
```bash
sudo gitlab-rake db:migrations:status
sudo gitlab-rake db:migrate:status
```
This will output a table with a `Status` of `up` or `down` for
......
......@@ -194,9 +194,15 @@ msgstr[1] ""
msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
msgstr ""
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
msgstr ""
msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
msgstr ""
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
msgstr ""
msgid "%{filePath} deleted"
msgstr ""
......@@ -866,6 +872,9 @@ msgstr ""
msgid "Add to review"
msgstr ""
msgid "Add to tree"
msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
......
import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter';
import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
import confidentialState from '~/confidential_merge_request/state';
import { TEST_HOST } from './helpers/test_constants';
describe('CreateMergeRequestDropdown', () => {
......@@ -66,4 +67,37 @@ describe('CreateMergeRequestDropdown', () => {
);
});
});
describe('enable', () => {
beforeEach(() => {
dropdown.createMergeRequestButton.classList.add('disabled');
});
afterEach(() => {
confidentialState.selectedProject = {};
});
it('enables button when not confidential issue', () => {
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).not.toContain('disabled');
});
it('enables when can create confidential issue', () => {
document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true');
confidentialState.selectedProject = { name: 'test' };
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).not.toContain('disabled');
});
it('does not enable when can not create confidential issue', () => {
document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true');
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).toContain('disabled');
});
});
});
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { GlDropdown } from '@gitlab/ui';
import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
let vm;
function factory(currentPath) {
function factory(currentPath, extraProps = {}) {
vm = shallowMount(Breadcrumbs, {
propsData: {
currentPath,
...extraProps,
},
stubs: {
RouterLink: RouterLinkStub,
......@@ -41,4 +43,20 @@ describe('Repository breadcrumbs component', () => {
.attributes('aria-current'),
).toEqual('page');
});
it('does not render add to tree dropdown when permissions are false', () => {
factory('/', { canCollaborate: false });
vm.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } });
expect(vm.find(GlDropdown).exists()).toBe(false);
});
it('renders add to tree dropdown when permissions are true', () => {
factory('/', { canCollaborate: true });
vm.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } });
expect(vm.find(GlDropdown).exists()).toBe(true);
});
});
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