Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
1678784bdfc9
Commit
d50f7c44
authored
Apr 10, 2020
by
GitLab Bot
Browse files
Add latest changes from gitlab-org/gitlab@master
parent
b322483cd738
Changes
48
Hide whitespace changes
Inline
Side-by-side
.haml-lint_todo.yml
View file @
1678784b
...
...
@@ -409,7 +409,6 @@ linters:
-
'
ee/app/views/projects/push_rules/_index.html.haml'
-
'
ee/app/views/projects/services/gitlab_slack_application/_help.html.haml'
-
'
ee/app/views/projects/services/gitlab_slack_application/_slack_integration_form.html.haml'
-
'
ee/app/views/projects/services/prometheus/_metrics.html.haml'
-
'
ee/app/views/projects/settings/slacks/edit.html.haml'
-
'
ee/app/views/shared/_additional_email_text.html.haml'
-
'
ee/app/views/shared/_mirror_update_button.html.haml'
...
...
app/assets/javascripts/jira_import/components/jira_import_app.vue
View file @
1678784b
<
script
>
import
getJiraProjects
from
'
../queries/getJiraProjects.query.graphql
'
;
import
JiraImportForm
from
'
./jira_import_form.vue
'
;
import
JiraImportSetup
from
'
./jira_import_setup.vue
'
;
export
default
{
name
:
'
JiraImportApp
'
,
components
:
{
JiraImportForm
,
JiraImportSetup
,
},
props
:
{
...
...
@@ -41,6 +43,6 @@ export default {
<
template
>
<div>
<jira-import-setup
v-if=
"!isJiraConfigured"
:illustration=
"setupIllustration"
/>
<
div
v-else
></div
>
<
jira-import-form
v-else
/
>
</div>
</
template
>
app/assets/javascripts/jira_import/components/jira_import_form.vue
0 → 100644
View file @
1678784b
<
script
>
import
{
GlAvatar
,
GlNewButton
,
GlFormGroup
,
GlFormSelect
,
GlLabel
}
from
'
@gitlab/ui
'
;
export
default
{
name
:
'
JiraImportForm
'
,
components
:
{
GlAvatar
,
GlNewButton
,
GlFormGroup
,
GlFormSelect
,
GlLabel
,
},
currentUserAvatarUrl
:
gon
.
current_user_avatar_url
,
currentUsername
:
gon
.
current_username
,
};
</
script
>
<
template
>
<div>
<h3
class=
"page-title"
>
{{
__
(
'
New Jira import
'
)
}}
</h3>
<hr
/>
<form>
<gl-form-group
class=
"row align-items-center"
:label=
"__('Import from')"
label-cols-sm=
"2"
label-for=
"jira-project-select"
>
<gl-form-select
id=
"jira-project-select"
class=
"mb-2"
/>
</gl-form-group>
<gl-form-group
class=
"row align-items-center"
:label=
"__('Issue label')"
label-cols-sm=
"2"
label-for=
"jira-project-label"
>
<gl-label
id=
"jira-project-label"
class=
"mb-2"
background-color=
"#428BCA"
title=
"jira-import::KEY-1"
scoped
/>
</gl-form-group>
<hr
/>
<p
class=
"offset-md-1"
>
{{
__
(
"
For each Jira issue successfully imported, we'll create a new GitLab issue with the following data:
"
,
)
}}
</p>
<gl-form-group
class=
"row align-items-center mb-1"
:label=
"__('Title')"
label-cols-sm=
"2"
label-for=
"jira-project-title"
>
<p
id=
"jira-project-title"
class=
"mb-2"
>
{{
__
(
'
jira.issue.summary
'
)
}}
</p>
</gl-form-group>
<gl-form-group
class=
"row align-items-center mb-1"
:label=
"__('Reporter')"
label-cols-sm=
"2"
label-for=
"jira-project-reporter"
>
<gl-avatar
id=
"jira-project-reporter"
class=
"mb-2"
:src=
"$options.currentUserAvatarUrl"
:size=
"24"
:aria-label=
"$options.currentUsername"
/>
</gl-form-group>
<gl-form-group
class=
"row align-items-center mb-1"
:label=
"__('Description')"
label-cols-sm=
"2"
label-for=
"jira-project-description"
>
<p
id=
"jira-project-description"
class=
"mb-2"
>
{{
__
(
'
jira.issue.description.content
'
)
}}
</p>
</gl-form-group>
<div
class=
"footer-block row-content-block d-flex justify-content-between"
>
<gl-new-button
category=
"primary"
variant=
"success"
>
{{
__
(
'
Next
'
)
}}
</gl-new-button>
<gl-new-button>
{{
__
(
'
Cancel
'
)
}}
</gl-new-button>
</div>
</form>
</div>
</
template
>
app/assets/javascripts/pages/projects/services/edit/index.js
View file @
1678784b
import
IntegrationSettingsForm
from
'
~/integrations/integration_settings_form
'
;
import
PrometheusMetrics
from
'
ee_else_ce
/prometheus_metrics/
prometheus
_metrics
'
;
import
PrometheusMetrics
from
'
~
/prometheus_metrics/
custom
_metrics
'
;
import
PrometheusAlerts
from
'
~/prometheus_alerts
'
;
import
initAlertsSettings
from
'
~/alerts_service_settings
'
;
...
...
app/assets/javascripts/prometheus_metrics/constants.js
View file @
1678784b
...
...
@@ -2,4 +2,5 @@ export default {
EMPTY
:
'
empty
'
,
LOADING
:
'
loading
'
,
LIST
:
'
list
'
,
NO_INTEGRATION
:
'
no-integration
'
,
};
app/assets/javascripts/prometheus_metrics/custom_metrics.js
0 → 100644
View file @
1678784b
import
$
from
'
jquery
'
;
import
{
escape
,
sortBy
}
from
'
lodash
'
;
import
PrometheusMetrics
from
'
./prometheus_metrics
'
;
import
PANEL_STATE
from
'
./constants
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
export
default
class
CustomMetrics
extends
PrometheusMetrics
{
constructor
(
wrapperSelector
)
{
super
(
wrapperSelector
);
this
.
customMetrics
=
[];
this
.
environmentsData
=
[];
this
.
$els
=
[];
this
.
$wrapperCustomMetrics
=
$
(
wrapperSelector
);
this
.
$monitoredCustomMetricsPanel
=
this
.
$wrapperCustomMetrics
.
find
(
'
.js-panel-custom-monitored-metrics
'
,
);
this
.
$monitoredCustomMetricsCount
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-custom-monitored-count
'
,
);
this
.
$monitoredCustomMetricsLoading
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-loading-custom-metrics
'
,
);
this
.
$monitoredCustomMetricsEmpty
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-empty-custom-metrics
'
,
);
this
.
$monitoredCustomMetricsList
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-custom-metrics-list
'
,
);
this
.
$monitoredCustomMetricsNoIntegrationText
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-no-active-integration-text
'
,
);
this
.
$newCustomMetricButton
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-new-metric-button
'
);
this
.
$newCustomMetricText
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-new-metric-text
'
);
this
.
$flashCustomMetricsContainer
=
this
.
$wrapperCustomMetrics
.
find
(
'
.flash-container
'
);
this
.
$els
=
[
this
.
$monitoredCustomMetricsLoading
,
this
.
$monitoredCustomMetricsList
,
this
.
$newCustomMetricButton
,
this
.
$newCustomMetricText
,
this
.
$monitoredCustomMetricsNoIntegrationText
,
this
.
$monitoredCustomMetricsEmpty
,
];
this
.
activeCustomMetricsEndpoint
=
this
.
$monitoredCustomMetricsPanel
.
data
(
'
active-custom-metrics
'
,
);
this
.
environmentsDataEndpoint
=
this
.
$monitoredCustomMetricsPanel
.
data
(
'
environments-data-endpoint
'
,
);
this
.
isServiceActive
=
this
.
$monitoredCustomMetricsPanel
.
data
(
'
service-active
'
);
}
init
()
{
if
(
this
.
isServiceActive
)
{
this
.
loadActiveCustomMetrics
();
}
else
{
this
.
setNoIntegrationActiveState
();
}
}
// eslint-disable-next-line class-methods-use-this
setHidden
(
els
)
{
els
.
forEach
(
el
=>
el
.
addClass
(
'
hidden
'
));
}
setVisible
(...
els
)
{
this
.
setHidden
(
this
.
$els
.
filter
(
el
=>
!
els
.
includes
(
el
)));
els
.
forEach
(
el
=>
el
.
removeClass
(
'
hidden
'
));
}
showMonitoringCustomMetricsPanelState
(
stateName
)
{
switch
(
stateName
)
{
case
PANEL_STATE
.
LOADING
:
this
.
setVisible
(
this
.
$monitoredCustomMetricsLoading
);
break
;
case
PANEL_STATE
.
LIST
:
this
.
setVisible
(
this
.
$newCustomMetricButton
,
this
.
$monitoredCustomMetricsList
);
break
;
case
PANEL_STATE
.
NO_INTEGRATION
:
this
.
setVisible
(
this
.
$monitoredCustomMetricsNoIntegrationText
,
this
.
$monitoredCustomMetricsEmpty
,
);
break
;
default
:
this
.
setVisible
(
this
.
$monitoredCustomMetricsEmpty
,
this
.
$newCustomMetricButton
,
this
.
$newCustomMetricText
,
);
break
;
}
}
populateCustomMetrics
()
{
const
capitalizeGroup
=
metric
=>
({
...
metric
,
group
:
capitalizeFirstCharacter
(
metric
.
group
),
});
const
sortedMetrics
=
sortBy
(
this
.
customMetrics
.
map
(
capitalizeGroup
),
[
'
group
'
,
'
title
'
]);
sortedMetrics
.
forEach
(
metric
=>
{
this
.
$monitoredCustomMetricsList
.
append
(
CustomMetrics
.
customMetricTemplate
(
metric
));
});
this
.
$monitoredCustomMetricsCount
.
text
(
this
.
customMetrics
.
length
);
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
LIST
);
if
(
!
this
.
environmentsData
)
{
this
.
showFlashMessage
(
s__
(
'
PrometheusService|These metrics will only be monitored after your first deployment to an environment
'
,
),
);
}
}
showFlashMessage
(
message
)
{
this
.
$flashCustomMetricsContainer
.
removeClass
(
'
hidden
'
);
this
.
$flashCustomMetricsContainer
.
find
(
'
.flash-text
'
).
text
(
message
);
}
setNoIntegrationActiveState
()
{
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
NO_INTEGRATION
);
this
.
showMonitoringMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
}
loadActiveCustomMetrics
()
{
super
.
loadActiveMetrics
();
Promise
.
all
([
axios
.
get
(
this
.
activeCustomMetricsEndpoint
),
axios
.
get
(
this
.
environmentsDataEndpoint
),
])
.
then
(([
customMetrics
,
environmentsData
])
=>
{
this
.
environmentsData
=
environmentsData
.
data
.
environments
;
if
(
!
customMetrics
.
data
||
!
customMetrics
.
data
.
metrics
)
{
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
}
else
{
this
.
customMetrics
=
customMetrics
.
data
.
metrics
;
this
.
populateCustomMetrics
(
customMetrics
.
data
.
metrics
);
}
})
.
catch
(
customMetricError
=>
{
this
.
showFlashMessage
(
customMetricError
);
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
});
}
static
customMetricTemplate
(
metric
)
{
return
`
<li class="custom-metric">
<a href="
${
escape
(
metric
.
edit_path
)}
" class="custom-metric-link-bold">
${
escape
(
metric
.
group
)}
/
${
escape
(
metric
.
title
)}
(
${
escape
(
metric
.
unit
)}
)
</a>
</li>
`
;
}
}
app/helpers/clusters_helper.rb
View file @
1678784b
...
...
@@ -41,6 +41,23 @@ def render_cluster_info_tab_content(tab, expanded)
end
end
def
cluster_type_label
(
cluster_type
)
case
cluster_type
when
'project_type'
s_
(
'ClusterIntegration|Project cluster'
)
when
'group_type'
s_
(
'ClusterIntegration|Group cluster'
)
when
'instance_type'
s_
(
'ClusterIntegration|Instance cluster'
)
else
Gitlab
::
ErrorTracking
.
track_and_raise_for_dev_exception
(
ArgumentError
.
new
(
'Cluster Type Missing'
),
cluster_error:
{
error:
'Cluster Type Missing'
,
cluster_type:
cluster_type
}
)
_
(
'Cluster'
)
end
end
def
has_rbac_enabled?
(
cluster
)
return
cluster
.
platform_kubernetes_rbac?
if
cluster
.
platform_kubernetes
...
...
app/models/performance_monitoring/prometheus_panel.rb
View file @
1678784b
...
...
@@ -4,7 +4,7 @@ module PerformanceMonitoring
class
PrometheusPanel
include
ActiveModel
::
Model
attr_accessor
:type
,
:title
,
:y_label
,
:weight
,
:metrics
attr_accessor
:type
,
:title
,
:y_label
,
:weight
,
:metrics
,
:y_axis
validates
:title
,
presence:
true
validates
:metrics
,
presence:
true
...
...
@@ -20,5 +20,9 @@ def self.from_json(json_content)
panel
.
tap
(
&
:validate!
)
end
def
id
(
group_title
)
Digest
::
SHA2
.
hexdigest
([
group_title
,
type
,
title
].
join
)
end
end
end
app/services/metrics/dashboard/base_service.rb
View file @
1678784b
...
...
@@ -11,6 +11,7 @@ class BaseService < ::BaseService
SEQUENCE
=
[
STAGES
::
CommonMetricsInserter
,
STAGES
::
EndpointInserter
,
STAGES
::
PanelIdsInserter
,
STAGES
::
Sorter
].
freeze
...
...
app/services/metrics/dashboard/gitlab_alert_embed_service.rb
View file @
1678784b
...
...
@@ -10,7 +10,10 @@ module Dashboard
class
GitlabAlertEmbedService
<
::
Metrics
::
Dashboard
::
BaseEmbedService
include
Gitlab
::
Utils
::
StrongMemoize
SEQUENCE
=
[
STAGES
::
EndpointInserter
].
freeze
SEQUENCE
=
[
STAGES
::
EndpointInserter
,
STAGES
::
PanelIdsInserter
].
freeze
class
<<
self
# Determines whether the provided params are sufficient
...
...
app/services/metrics/dashboard/grafana_metric_embed_service.rb
View file @
1678784b
...
...
@@ -10,7 +10,8 @@ class GrafanaMetricEmbedService < ::Metrics::Dashboard::BaseEmbedService
include
ReactiveCaching
SEQUENCE
=
[
::
Gitlab
::
Metrics
::
Dashboard
::
Stages
::
GrafanaFormatter
::
Gitlab
::
Metrics
::
Dashboard
::
Stages
::
GrafanaFormatter
,
::
Gitlab
::
Metrics
::
Dashboard
::
Stages
::
PanelIdsInserter
].
freeze
self
.
reactive_cache_key
=
->
(
service
)
{
service
.
cache_key
}
...
...
app/services/metrics/dashboard/predefined_dashboard_service.rb
View file @
1678784b
...
...
@@ -11,6 +11,7 @@ class PredefinedDashboardService < ::Metrics::Dashboard::BaseService
SEQUENCE
=
[
STAGES
::
EndpointInserter
,
STAGES
::
PanelIdsInserter
,
STAGES
::
Sorter
].
freeze
...
...
app/services/metrics/dashboard/self_monitoring_dashboard_service.rb
View file @
1678784b
...
...
@@ -11,6 +11,7 @@ class SelfMonitoringDashboardService < ::Metrics::Dashboard::PredefinedDashboard
SEQUENCE
=
[
STAGES
::
CustomMetricsInserter
,
STAGES
::
EndpointInserter
,
STAGES
::
PanelIdsInserter
,
STAGES
::
Sorter
].
freeze
...
...
app/services/metrics/dashboard/system_dashboard_service.rb
View file @
1678784b
...
...
@@ -13,6 +13,7 @@ class SystemDashboardService < ::Metrics::Dashboard::PredefinedDashboardService
STAGES
::
CustomMetricsInserter
,
STAGES
::
CustomMetricsDetailsInserter
,
STAGES
::
EndpointInserter
,
STAGES
::
PanelIdsInserter
,
STAGES
::
Sorter
].
freeze
...
...
app/services/tags/create_service.rb
View file @
1678784b
...
...
@@ -4,7 +4,7 @@ module Tags
class
CreateService
<
BaseService
def
execute
(
tag_name
,
target
,
message
)
valid_tag
=
Gitlab
::
GitRefValidator
.
validate
(
tag_name
)
return
error
(
'Tag name invalid'
)
unless
valid_tag
return
error
(
'Tag name invalid'
,
400
)
unless
valid_tag
repository
=
project
.
repository
message
=
message
&
.
strip
...
...
@@ -14,7 +14,7 @@ def execute(tag_name, target, message)
begin
new_tag
=
repository
.
add_tag
(
current_user
,
tag_name
,
target
,
message
)
rescue
Gitlab
::
Git
::
Repository
::
TagExistsError
return
error
(
"Tag
#{
tag_name
}
already exists"
)
return
error
(
"Tag
#{
tag_name
}
already exists"
,
409
)
rescue
Gitlab
::
Git
::
PreReceiveError
=>
ex
return
error
(
ex
.
message
)
end
...
...
@@ -24,7 +24,7 @@ def execute(tag_name, target, message)
success
.
merge
(
tag:
new_tag
)
else
error
(
"Target
#{
target
}
is invalid"
)
error
(
"Target
#{
target
}
is invalid"
,
400
)
end
end
end
...
...
app/views/clusters/clusters/show.html.haml
View file @
1678784b
...
...
@@ -41,7 +41,12 @@
.js-serverless-survey-banner
{
data:
{
user_name:
current_user
.
name
,
user_email:
current_user
.
email
}
}
%h4
=
@cluster
.
name
.d-flex.my-3
%p
.badge.badge-light.p-2.mr-2
=
cluster_type_label
(
@cluster
.
cluster_type
)
%h4
.m-0
=
@cluster
.
name
=
render
'banner'
-
if
cluster_created?
(
@cluster
)
...
...
@@ -56,7 +61,3 @@
.tab-content.py-3
.tab-pane.active
{
role:
'tabpanel'
}
=
render_cluster_info_tab_content
(
params
[
:tab
],
expanded_by_default?
)
app/views/projects/services/prometheus/_custom_metrics.html.haml
0 → 100644
View file @
1678784b
-
project
=
local_assigns
.
fetch
(
:project
)
.col-lg-3
%p
=
s_
(
'PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope "*" OR a manually configured Prometheus to be available.'
)
=
link_to
s_
(
'PrometheusService|More information'
),
help_page_path
(
'user/project/integrations/prometheus'
,
anchor:
'adding-custom-metrics'
),
target:
'_blank'
,
rel:
"noopener noreferrer"
.col-lg-9
.card.custom-monitored-metrics.js-panel-custom-monitored-metrics
{
data:
{
active_custom_metrics:
project_prometheus_metrics_path
(
project
),
environments_data:
environments_list_data
,
service_active:
"#{@service.active}"
}
}
.card-header
%strong
=
s_
(
'PrometheusService|Custom metrics'
)
-# haml-lint:disable NoPlainNodes
%span
.badge.badge-pill.js-custom-monitored-count
0
-# haml-lint:enable NoPlainNodes
=
link_to
s_
(
'PrometheusService|New metric'
),
new_project_prometheus_metric_path
(
project
),
class:
'btn btn-success js-new-metric-button hidden'
.card-body
.flash-container.hidden
.flash-warning
.flash-text
.loading-metrics.js-loading-custom-metrics
%p
.m-3
=
icon
(
'spinner spin'
,
class:
'metrics-load-spinner'
)
=
s_
(
'PrometheusService|Finding custom metrics...'
)
.empty-metrics.hidden.js-empty-custom-metrics
%p
.text-tertiary.m-3.js-no-active-integration-text.hidden
=
s_
(
'PrometheusService|Enable Prometheus to define custom metrics, using either option above'
)
%p
.text-tertiary.m-3.js-new-metric-text.hidden
=
s_
(
'PrometheusService|No custom metrics have been created. Create one using the button above'
)
%ul
.list-unstyled.metrics-list.hidden.js-custom-metrics-list
app/views/projects/services/prometheus/_metrics.html.haml
View file @
1678784b
-
project
=
local_assigns
.
fetch
(
:project
)
=
render
'projects/services/prometheus/custom_metrics'
,
project:
project
.col-lg-3
%p
=
s_
(
'PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.'
)
...
...
changelogs/unreleased/fix-release-api-internal-server-error.yml
0 → 100644
View file @
1678784b
---
title
:
Fix 500 error on create release API when providing an invalid tag_name
merge_request
:
28969
author
:
Sashi Kumar
type
:
fixed
changelogs/unreleased/mwaw-212617-generate-panel-ids-based-on-panel-title-and-group-title-in-th.yml
0 → 100644
View file @
1678784b
---
title
:
Automatically assign id to each panel within dashboard to support panel scoped annotations
merge_request
:
28341
author
:
type
:
added
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment