Skip to content
Snippets Groups Projects
Commit 2b7a5214 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 15a2d004
No related branches found
No related tags found
No related merge requests found
Showing
with 182 additions and 43 deletions
Loading
Loading
@@ -76,8 +76,7 @@ graphql-reference-verify:
- .default-only
- .default-before_script
- .only:changes-graphql
variables:
SETUP_DB: "false"
- .use-pg9
stage: test
needs: ["setup-test-env"]
script:
Loading
Loading
Loading
Loading
@@ -2,6 +2,8 @@ import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
import { joinPaths } from './lib/utils/url_utility';
import flash from '~/flash';
import { __ } from '~/locale';
 
const Api = {
groupsPath: '/api/:version/groups.json',
Loading
Loading
@@ -29,6 +31,7 @@ const Api = {
usersPath: '/api/:version/users.json',
userPath: '/api/:version/users/:id',
userStatusPath: '/api/:version/users/:id/status',
userProjectsPath: '/api/:version/users/:id/projects',
userPostStatusPath: '/api/:version/user/status',
commitPath: '/api/:version/projects/:id/repository/commits',
applySuggestionPath: '/api/:version/suggestions/:id/apply',
Loading
Loading
@@ -239,7 +242,8 @@ const Api = {
.get(url, {
params: Object.assign({}, defaults, options),
})
.then(({ data }) => callback(data));
.then(({ data }) => callback(data))
.catch(() => flash(__('Something went wrong while fetching projects')));
},
 
commitMultiple(id, data) {
Loading
Loading
@@ -348,6 +352,20 @@ const Api = {
});
},
 
userProjects(userId, query, options, callback) {
const url = Api.buildUrl(Api.userProjectsPath).replace(':id', userId);
const defaults = {
search: query,
per_page: 20,
};
return axios
.get(url, {
params: Object.assign({}, defaults, options),
})
.then(({ data }) => callback(data))
.catch(() => flash(__('Something went wrong while fetching projects')));
},
branches(id, query = '', options = {}) {
const url = Api.buildUrl(this.createBranchPath).replace(':id', encodeURIComponent(id));
 
Loading
Loading
Loading
Loading
@@ -13,6 +13,7 @@ import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue';
import setupToggleButtons from '../toggle_buttons';
import initProjectSelectDropdown from '~/project_select';
 
const Environments = () => import('ee_component/clusters/components/environments.vue');
 
Loading
Loading
@@ -110,8 +111,10 @@ export default class Clusters {
this.ingressDomainHelpText &&
this.ingressDomainHelpText.querySelector('.js-ingress-domain-snippet');
 
initProjectSelectDropdown();
Clusters.initDismissableCallout();
initSettingsPanels();
const toggleButtonsContainer = document.querySelector('.js-cluster-enable-toggle-area');
if (toggleButtonsContainer) {
setupToggleButtons(toggleButtonsContainer);
Loading
Loading
Loading
Loading
@@ -174,7 +174,7 @@ export default {
return this.customMetricsAvailable && this.customMetricsPath.length;
},
...mapState('monitoringDashboard', [
'groups',
'dashboard',
'emptyState',
'showEmptyState',
'environments',
Loading
Loading
@@ -238,6 +238,7 @@ export default {
'setGettingStartedEmptyState',
'setEndpoints',
'setDashboardEnabled',
'setPanelGroupMetrics',
]),
chartsWithData(charts) {
if (!this.useDashboardEndpoint) {
Loading
Loading
@@ -274,10 +275,17 @@ export default {
this.$toast.show(__('Link copied'));
},
// TODO: END
removeGraph(metrics, graphIndex) {
// At present graphs will not be removed, they should removed using the vuex store
// See https://gitlab.com/gitlab-org/gitlab/issues/27835
metrics.splice(graphIndex, 1);
updateMetrics(key, metrics) {
this.setPanelGroupMetrics({
metrics,
key,
});
},
removeMetric(key, metrics, graphIndex) {
this.setPanelGroupMetrics({
metrics: metrics.filter((v, i) => i !== graphIndex),
key,
});
},
showInvalidDateError() {
createFlash(s__('Metrics|Link contains an invalid time window.'));
Loading
Loading
@@ -447,7 +455,7 @@ export default {
 
<div v-if="!showEmptyState">
<graph-group
v-for="(groupData, index) in groups"
v-for="(groupData, index) in dashboard.panel_groups"
:key="`${groupData.group}.${groupData.priority}`"
:name="groupData.group"
:show-panels="showPanels"
Loading
Loading
@@ -455,10 +463,11 @@ export default {
>
<template v-if="additionalPanelTypesEnabled">
<vue-draggable
:list="groupData.metrics"
:value="groupData.metrics"
group="metrics-dashboard"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:disabled="!isRearrangingPanels"
@input="updateMetrics(groupData.key, $event)"
>
<div
v-for="(graphData, graphIndex) in groupData.metrics"
Loading
Loading
@@ -470,7 +479,7 @@ export default {
<div
v-if="isRearrangingPanels"
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removeGraph(groupData.metrics, graphIndex)"
@click="removeMetric(groupData.key, groupData.metrics, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
><icon name="close"
Loading
Loading
Loading
Loading
@@ -35,9 +35,9 @@ export default {
};
},
computed: {
...mapState('monitoringDashboard', ['groups', 'metricsWithData']),
...mapState('monitoringDashboard', ['dashboard', 'metricsWithData']),
charts() {
const groupWithMetrics = this.groups.find(group =>
const groupWithMetrics = this.dashboard.panel_groups.find(group =>
group.metrics.find(chart => this.chartHasData(chart)),
) || { metrics: [] };
 
Loading
Loading
Loading
Loading
@@ -166,7 +166,7 @@ export const fetchPrometheusMetrics = ({ state, commit, dispatch }, params) => {
commit(types.REQUEST_METRICS_DATA);
 
const promises = [];
state.groups.forEach(group => {
state.dashboard.panel_groups.forEach(group => {
group.panels.forEach(panel => {
panel.metrics.forEach(metric => {
promises.push(dispatch('fetchPrometheusMetric', { metric, params }));
Loading
Loading
@@ -221,5 +221,15 @@ export const fetchEnvironmentsData = ({ state, dispatch }) => {
});
};
 
/**
* Set a new array of metrics to a panel group
* @param {*} data An object containing
* - `key` with a unique panel key
* - `metrics` with the metrics array
*/
export const setPanelGroupMetrics = ({ commit }, data) => {
commit(types.SET_PANEL_GROUP_METRICS, data);
};
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
Loading
Loading
@@ -16,3 +16,4 @@ export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
export const SET_PANEL_GROUP_METRICS = 'SET_PANEL_GROUP_METRICS';
import Vue from 'vue';
import { slugify } from '~/lib/utils/text_utility';
import * as types from './mutation_types';
import { normalizeMetrics, sortMetrics, normalizeMetric, normalizeQueryResult } from './utils';
import { normalizeMetrics, normalizeMetric, normalizeQueryResult } from './utils';
 
const normalizePanel = panel => panel.metrics.map(normalizeMetric);
 
Loading
Loading
@@ -10,10 +11,12 @@ export default {
state.showEmptyState = true;
},
[types.RECEIVE_METRICS_DATA_SUCCESS](state, groupData) {
state.groups = groupData.map(group => {
state.dashboard.panel_groups = groupData.map((group, i) => {
const key = `${slugify(group.group || 'default')}-${i}`;
let { metrics = [], panels = [] } = group;
 
// each panel has metric information that needs to be normalized
panels = panels.map(panel => ({
...panel,
metrics: normalizePanel(panel),
Loading
Loading
@@ -32,11 +35,12 @@ export default {
return {
...group,
panels,
metrics: normalizeMetrics(sortMetrics(metrics)),
key,
metrics: normalizeMetrics(metrics),
};
});
 
if (!state.groups.length) {
if (!state.dashboard.panel_groups.length) {
state.emptyState = 'noData';
} else {
state.showEmptyState = false;
Loading
Loading
@@ -65,7 +69,7 @@ export default {
 
state.showEmptyState = false;
 
state.groups.forEach(group => {
state.dashboard.panel_groups.forEach(group => {
group.metrics.forEach(metric => {
metric.queries.forEach(query => {
if (query.metric_id === metricId) {
Loading
Loading
@@ -105,4 +109,8 @@ export default {
[types.SET_SHOW_ERROR_BANNER](state, enabled) {
state.showErrorBanner = enabled;
},
[types.SET_PANEL_GROUP_METRICS](state, payload) {
const panelGroup = state.dashboard.panel_groups.find(pg => payload.key === pg.key);
panelGroup.metrics = payload.metrics;
},
};
Loading
Loading
@@ -12,7 +12,9 @@ export default () => ({
emptyState: 'gettingStarted',
showEmptyState: true,
showErrorBanner: true,
groups: [],
dashboard: {
panel_groups: [],
},
deploymentData: [],
environments: [],
metricsWithData: [],
Loading
Loading
Loading
Loading
@@ -82,12 +82,6 @@ export const normalizeMetric = (metric = {}) =>
'id',
);
 
export const sortMetrics = metrics =>
_.chain(metrics)
.sortBy('title')
.sortBy('weight')
.value();
export const normalizeQueryResult = timeSeries => {
let normalizedResult = {};
 
Loading
Loading
Loading
Loading
@@ -9,7 +9,9 @@ const projectSelect = () => {
$('.ajax-project-select').each(function(i, select) {
var placeholder;
const simpleFilter = $(select).data('simpleFilter') || false;
const isInstantiated = $(select).data('select2');
this.groupId = $(select).data('groupId');
this.userId = $(select).data('userId');
this.includeGroups = $(select).data('includeGroups');
this.allProjects = $(select).data('allProjects') || false;
this.orderBy = $(select).data('orderBy') || 'id';
Loading
Loading
@@ -63,6 +65,18 @@ const projectSelect = () => {
},
projectsCallback,
);
} else if (_this.userId) {
return Api.userProjects(
_this.userId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
Loading
Loading
@@ -96,7 +110,7 @@ const projectSelect = () => {
 
dropdownCssClass: 'ajax-project-dropdown',
});
if (simpleFilter) return select;
if (isInstantiated || simpleFilter) return select;
return new ProjectSelectComboButton(select);
});
};
Loading
Loading
Loading
Loading
@@ -46,7 +46,7 @@ class GitlabSchema < GraphQL::Schema
super(query_str, **kwargs)
end
 
def id_from_object(object)
def id_from_object(object, _type = nil, _ctx = nil)
unless object.respond_to?(:to_global_id)
# This is an error in our schema and needs to be solved. So raise a
# more meaningful error message
Loading
Loading
@@ -57,7 +57,7 @@ class GitlabSchema < GraphQL::Schema
object.to_global_id
end
 
def object_from_id(global_id)
def object_from_id(global_id, _ctx = nil)
gid = GlobalID.parse(global_id)
 
unless gid
Loading
Loading
# frozen_string_literal: true
module Mutations
module MergeRequests
class SetMilestone < Base
graphql_name 'MergeRequestSetMilestone'
argument :milestone_id,
GraphQL::ID_TYPE,
required: false,
loads: Types::MilestoneType,
description: <<~DESC
The milestone to assign to the merge request.
DESC
def resolve(project_path:, iid:, milestone: nil)
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.project
::MergeRequests::UpdateService.new(project, current_user, milestone: milestone)
.execute(merge_request)
{
merge_request: merge_request,
errors: merge_request.errors.full_messages
}
end
end
end
end
Loading
Loading
@@ -6,6 +6,8 @@ module Types
 
authorize :read_milestone
 
field :id, GraphQL::ID_TYPE, null: false,
description: 'ID of the milestone'
field :description, GraphQL::STRING_TYPE, null: true,
description: 'Description of the milestone'
field :title, GraphQL::STRING_TYPE, null: false,
Loading
Loading
Loading
Loading
@@ -9,6 +9,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::MergeRequests::SetMilestone
mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true
Loading
Loading
Loading
Loading
@@ -2,13 +2,6 @@
 
class ProjectSnippet < Snippet
belongs_to :project
belongs_to :author, class_name: "User"
 
validates :project, presence: true
# Scopes
scope :fresh, -> { order("created_at DESC") }
participant :author
participant :notes_with_associations
end
Loading
Loading
@@ -44,28 +44,52 @@ module Projects
end
 
expose :url do |service|
service.dig('status', 'url') || "http://#{service.dig('status', 'domain')}"
knative_06_07_url(service) || knative_05_url(service)
end
 
expose :description do |service|
knative_07_description(service) || knative_05_06_description(service)
end
expose :image do |service|
service.dig(
'spec',
'runLatest',
'configuration',
'revisionTemplate',
'build',
'template',
'name')
end
private
def knative_07_description(service)
service.dig(
'spec',
'template',
'metadata',
'annotations',
'Description')
'Description'
)
end
 
expose :image do |service|
def knative_05_url(service)
"http://#{service.dig('status', 'domain')}"
end
def knative_06_07_url(service)
service.dig('status', 'url')
end
def knative_05_06_description(service)
service.dig(
'spec',
'runLatest',
'configuration',
'build',
'template',
'name')
'revisionTemplate',
'metadata',
'annotations',
'Description')
end
end
end
Loading
Loading
- group_id = @cluster.group.id if @cluster.group_type?
- if @cluster.project_type?
- group_id = @cluster.project.group.id if @cluster.project.group
- user_id = @cluster.project.namespace.owner_id unless group_id
- if can?(current_user, :admin_cluster, @cluster)
- unless @cluster.provided_by_user?
.append-bottom-20
Loading
Loading
@@ -7,6 +13,21 @@
- link_gke = link_to(s_('ClusterIntegration|Google Kubernetes Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
= s_('ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
 
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'cluster_management_form' } do |field|
%h5
= s_('ClusterIntegration|Cluster management project (alpha)')
.form-group
.form-text.text-muted
= project_select_tag('cluster[management_project_id]', class: 'hidden-filter-value', toggle_class: 'js-project-search js-project-filter js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit',
placeholder: _('Select project'), idAttribute: 'id', data: { order_by: 'last_activity_at', idattribute: 'id', simple_filter: true, allow_clear: true, include_groups: false, include_projects_in_subgroups: true, group_id: group_id, user_id: user_id }, value: @cluster.management_project_id)
.text-muted
= s_('ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes <code>cluster-admin</code> privileges.').html_safe
= link_to _('More information'), help_page_path('user/clusters/management_project.md'), target: '_blank'
.form-group
= field.submit _('Save changes'), class: 'btn btn-success qa-save-domain'
.sub-section.form-group
%h4.text-danger
= s_('ClusterIntegration|Remove Kubernetes cluster integration')
Loading
Loading
---
title: Can directly add approvers to approval rule
merge_request: 18965
author:
type: changed
---
title: 'GraphQL: Add Merge Request milestone mutation'
merge_request: 19257
author:
type: added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment