Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-11 18:09:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-11 18:09:37 +0300
commit6217d19741a8ea4351813b13c6fb39cc6a746602 (patch)
tree148b37b12e23835691de2a6dad4a425e678bc33d /app
parente3190840bc2e05ed04a49869978a54b7b518edf1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/lib/utils/downloader.js20
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue9
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/variables_section.vue48
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js15
-rw-r--r--app/assets/javascripts/monitoring/stores/getters.js12
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js22
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js2
-rw-r--r--app/assets/stylesheets/pages/prometheus.scss8
-rw-r--r--app/controllers/jwt_controller.rb5
-rw-r--r--app/finders/alert_management/alerts_finder.rb7
-rw-r--r--app/graphql/resolvers/alert_management_alert_resolver.rb5
-rw-r--r--app/models/alert_management/alert.rb1
-rw-r--r--app/models/concerns/state_eventable.rb9
-rw-r--r--app/models/issue.rb1
-rw-r--r--app/models/merge_request.rb1
-rw-r--r--app/models/resource_state_event.rb15
-rw-r--r--app/services/issuable/clone/attributes_rewriter.rb30
-rw-r--r--app/services/projects/import_service.rb8
-rw-r--r--app/views/groups/_flash_messages.html.haml2
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/incident_management/process_alert_worker.rb2
-rw-r--r--app/workers/merge_request_mergeability_check_worker.rb3
25 files changed, 207 insertions, 30 deletions
diff --git a/app/assets/javascripts/lib/utils/downloader.js b/app/assets/javascripts/lib/utils/downloader.js
new file mode 100644
index 00000000000..2297f5f90ce
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/downloader.js
@@ -0,0 +1,20 @@
+/**
+ * Helper function to trigger a download.
+ *
+ * - If the `fileName` is `_blank` it will open the file in a new tab.
+ * - If `fileData` is provided, it will inline the content and use data URLs to
+ * download the file. In this case the `url` property will be ignored. Please
+ * note that `fileData` needs to be Base64 encoded.
+ */
+export default ({ fileName, url, fileData }) => {
+ let href = url;
+
+ if (fileData) {
+ href = `data:text/plain;base64,${fileData}`;
+ }
+
+ const anchor = document.createElement('a');
+ anchor.download = fileName;
+ anchor.href = href;
+ anchor.click();
+};
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index e2e950f7790..2b5a10907f5 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -30,6 +30,7 @@ import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
import GroupEmptyState from './group_empty_state.vue';
import DashboardsDropdown from './dashboards_dropdown.vue';
+import VariablesSection from './variables_section.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import {
@@ -64,6 +65,8 @@ export default {
EmptyState,
GroupEmptyState,
DashboardsDropdown,
+
+ VariablesSection,
},
directives: {
GlModal: GlModalDirective,
@@ -222,6 +225,7 @@ export default {
'allDashboards',
'environmentsLoading',
'expandedPanel',
+ 'promVariables',
]),
...mapGetters('monitoringDashboard', ['getMetricStates', 'filteredEnvironments']),
firstDashboard() {
@@ -243,6 +247,9 @@ export default {
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
+ shouldShowVariablesSection() {
+ return Object.keys(this.promVariables).length > 0;
+ },
},
watch: {
dashboard(newDashboard) {
@@ -584,7 +591,7 @@ export default {
</div>
</div>
</div>
-
+ <variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
<div v-if="!showEmptyState">
<dashboard-panel
v-show="expandedPanel.panel"
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 64e79f86dce..48825fda5c8 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -313,7 +313,12 @@ export default {
<template slot="button-content">
<gl-icon name="ellipsis_v" class="text-secondary" />
</template>
- <gl-dropdown-item v-if="expandBtnAvailable" ref="expandBtn" @click="onExpand">
+ <gl-dropdown-item
+ v-if="expandBtnAvailable"
+ ref="expandBtn"
+ :href="clipboardText"
+ @click.prevent="onExpand"
+ >
{{ s__('Metrics|Expand panel') }}
</gl-dropdown-item>
<gl-dropdown-item
diff --git a/app/assets/javascripts/monitoring/components/variables_section.vue b/app/assets/javascripts/monitoring/components/variables_section.vue
new file mode 100644
index 00000000000..a67bc62e196
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/variables_section.vue
@@ -0,0 +1,48 @@
+<script>
+import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlFormInput,
+ },
+ computed: {
+ ...mapState('monitoringDashboard', ['promVariables']),
+ },
+ methods: {
+ ...mapActions('monitoringDashboard', ['fetchDashboardData', 'setVariableData']),
+ refreshDashboard(event) {
+ const { name, value } = event.target;
+
+ if (this.promVariables[name] !== value) {
+ const changedVariable = { [name]: value };
+
+ this.setVariableData(changedVariable);
+
+ updateHistory({
+ url: mergeUrlParams(this.promVariables, window.location.href),
+ title: document.title,
+ });
+
+ this.fetchDashboardData();
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div ref="variablesSection" class="d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 variables-section">
+ <div v-for="(val, key) in promVariables" :key="key" class="mb-1 pr-2 d-flex d-sm-block">
+ <gl-form-group :label="key" class="mb-0 flex-grow-1">
+ <gl-form-input
+ :value="val"
+ :name="key"
+ @keyup.native.enter="refreshDashboard"
+ @blur.native="refreshDashboard"
+ />
+ </gl-form-group>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 9d18629bf34..0134378868b 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -222,14 +222,17 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
*
* @param {metric} metric
*/
-export const fetchPrometheusMetric = ({ commit, state }, { metric, defaultQueryParams }) => {
+export const fetchPrometheusMetric = (
+ { commit, state, getters },
+ { metric, defaultQueryParams },
+) => {
const queryParams = { ...defaultQueryParams };
if (metric.step) {
queryParams.step = metric.step;
}
- if (state.promVariables.length > 0) {
- queryParams.variables = state.promVariables;
+ if (Object.keys(state.promVariables).length > 0) {
+ queryParams.variables = getters.getCustomVariablesArray;
}
commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId });
@@ -390,5 +393,11 @@ export const duplicateSystemDashboard = ({ state }, payload) => {
});
};
+// Variables manipulation
+
+export const setVariableData = ({ commit }, updatedVariable) => {
+ commit(types.UPDATE_VARIABLE_DATA, updatedVariable);
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/monitoring/stores/getters.js b/app/assets/javascripts/monitoring/stores/getters.js
index a6d80c5063e..1cadc287204 100644
--- a/app/assets/javascripts/monitoring/stores/getters.js
+++ b/app/assets/javascripts/monitoring/stores/getters.js
@@ -96,5 +96,17 @@ export const filteredEnvironments = state =>
env.name.toLowerCase().includes((state.environmentsSearchTerm || '').trim().toLowerCase()),
);
+/**
+ * Maps an variables object to an array
+ * @param {Object} variables - Custom variables provided by the user
+ * @returns {Array} The custom variables array to be send to the API
+ * in the format of [variable1, variable1_value]
+ */
+
+export const getCustomVariablesArray = state =>
+ Object.entries(state.promVariables)
+ .flat()
+ .map(encodeURIComponent);
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
index ebe89e93ede..2fd0efa4ab7 100644
--- a/app/assets/javascripts/monitoring/stores/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -3,6 +3,7 @@ export const REQUEST_METRICS_DASHBOARD = 'REQUEST_METRICS_DASHBOARD';
export const RECEIVE_METRICS_DASHBOARD_SUCCESS = 'RECEIVE_METRICS_DASHBOARD_SUCCESS';
export const RECEIVE_METRICS_DASHBOARD_FAILURE = 'RECEIVE_METRICS_DASHBOARD_FAILURE';
export const SET_PROM_QUERY_VARIABLES = 'SET_PROM_QUERY_VARIABLES';
+export const UPDATE_VARIABLE_DATA = 'UPDATE_VARIABLE_DATA';
// Annotations
export const RECEIVE_ANNOTATIONS_SUCCESS = 'RECEIVE_ANNOTATIONS_SUCCESS';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index c4c15993aa0..8de1430302a 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -1,4 +1,4 @@
-import pick from 'lodash/pick';
+import { pick } from 'lodash';
import * as types from './mutation_types';
import { mapToDashboardViewModel, normalizeQueryResult } from './utils';
import { BACKOFF_TIMEOUT } from '../../lib/utils/common_utils';
@@ -51,18 +51,6 @@ const emptyStateFromError = error => {
return metricStates.UNKNOWN_ERROR;
};
-/**
- * Maps an variables object to an array
- * @returns {Array} The custom variables array to be send to the API
- * in the format of [variable1, variable1_value]
- * @param {Object} variables - Custom variables provided by the user
- */
-
-const transformVariablesObjectArray = variables =>
- Object.entries(variables)
- .flat()
- .map(encodeURIComponent);
-
export default {
/**
* Dashboard panels structure and global state
@@ -182,6 +170,12 @@ export default {
state.expandedPanel.panel = panel;
},
[types.SET_PROM_QUERY_VARIABLES](state, variables) {
- state.promVariables = transformVariablesObjectArray(variables);
+ state.promVariables = variables;
+ },
+ [types.UPDATE_VARIABLE_DATA](state, newVariable) {
+ Object.assign(state.promVariables, {
+ ...state.promVariables,
+ ...newVariable,
+ });
},
};
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index 3a63d6279f4..f1b2baf0f74 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -33,7 +33,7 @@ export default () => ({
panel: null,
},
allDashboards: [],
- promVariables: [],
+ promVariables: {},
// Other project data
annotations: [],
diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss
index f61245bed24..d86bf92eac4 100644
--- a/app/assets/stylesheets/pages/prometheus.scss
+++ b/app/assets/stylesheets/pages/prometheus.scss
@@ -13,6 +13,14 @@
.form-group {
margin-bottom: map-get($spacing-scale, 3);
}
+
+ .variables-section {
+ input {
+ @include media-breakpoint-up(sm) {
+ width: 160px;
+ }
+ }
+ }
}
.draggable {
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index da39d64c93d..dcd80f4032e 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -75,4 +75,9 @@ class JwtController < ApplicationController
Array(Rack::Utils.parse_query(request.query_string)['scope'])
end
+
+ def auth_user
+ actor = @authentication_result&.actor
+ actor.is_a?(User) ? actor : nil
+ end
end
diff --git a/app/finders/alert_management/alerts_finder.rb b/app/finders/alert_management/alerts_finder.rb
index a48dadc7fdb..eeb6b5f8491 100644
--- a/app/finders/alert_management/alerts_finder.rb
+++ b/app/finders/alert_management/alerts_finder.rb
@@ -12,6 +12,7 @@ module AlertManagement
return AlertManagement::Alert.none unless authorized?
collection = project.alert_management_alerts
+ collection = by_status(collection)
collection = by_iid(collection)
sort(collection)
end
@@ -26,6 +27,12 @@ module AlertManagement
collection.for_iid(params[:iid])
end
+ def by_status(collection)
+ values = AlertManagement::Alert::STATUSES.values & Array(params[:status])
+
+ values.present? ? collection.for_status(values) : collection
+ end
+
def sort(collection)
params[:sort] ? collection.sort_by_attribute(params[:sort]) : collection
end
diff --git a/app/graphql/resolvers/alert_management_alert_resolver.rb b/app/graphql/resolvers/alert_management_alert_resolver.rb
index 6c8f64cc62b..d2f82ece281 100644
--- a/app/graphql/resolvers/alert_management_alert_resolver.rb
+++ b/app/graphql/resolvers/alert_management_alert_resolver.rb
@@ -6,6 +6,11 @@ module Resolvers
required: false,
description: 'IID of the alert. For example, "1"'
+ argument :statuses, [Types::AlertManagement::StatusEnum],
+ as: :status,
+ required: false,
+ description: 'Alerts with the specified statues. For example, [TRIGGERED]'
+
argument :sort, Types::AlertManagement::AlertSortEnum,
description: 'Sort alerts by this criteria',
required: false
diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb
index 6bbdc1645ca..e1a6b507906 100644
--- a/app/models/alert_management/alert.rb
+++ b/app/models/alert_management/alert.rb
@@ -93,6 +93,7 @@ module AlertManagement
end
scope :for_iid, -> (iid) { where(iid: iid) }
+ scope :for_status, -> (status) { where(status: status) }
scope :for_fingerprint, -> (project, fingerprint) { where(project: project, fingerprint: fingerprint) }
scope :order_start_time, -> (sort_order) { order(started_at: sort_order) }
diff --git a/app/models/concerns/state_eventable.rb b/app/models/concerns/state_eventable.rb
new file mode 100644
index 00000000000..68129798543
--- /dev/null
+++ b/app/models/concerns/state_eventable.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module StateEventable
+ extend ActiveSupport::Concern
+
+ included do
+ has_many :resource_state_events
+ end
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 82643d8f5d6..90443cba81b 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -17,6 +17,7 @@ class Issue < ApplicationRecord
include IgnorableColumns
include MilestoneEventable
include WhereComposite
+ include StateEventable
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index c962f8c8c26..e24384156c9 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -19,6 +19,7 @@ class MergeRequest < ApplicationRecord
include ShaAttribute
include IgnorableColumns
include MilestoneEventable
+ include StateEventable
sha_attribute :squash_commit_sha
diff --git a/app/models/resource_state_event.rb b/app/models/resource_state_event.rb
new file mode 100644
index 00000000000..1d6573b180f
--- /dev/null
+++ b/app/models/resource_state_event.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class ResourceStateEvent < ResourceEvent
+ include IssueResourceEvent
+ include MergeRequestResourceEvent
+
+ validate :exactly_one_issuable
+
+ # state is used for issue and merge request states.
+ enum state: Issue.available_states.merge(MergeRequest.available_states).merge(reopened: 5)
+
+ def self.issuable_attrs
+ %i(issue merge_request).freeze
+ end
+end
diff --git a/app/services/issuable/clone/attributes_rewriter.rb b/app/services/issuable/clone/attributes_rewriter.rb
index 78d3fb2e4d2..a78e191c85f 100644
--- a/app/services/issuable/clone/attributes_rewriter.rb
+++ b/app/services/issuable/clone/attributes_rewriter.rb
@@ -20,6 +20,7 @@ module Issuable
copy_resource_label_events
copy_resource_weight_events
copy_resource_milestone_events
+ copy_resource_state_events
end
private
@@ -47,8 +48,6 @@ module Issuable
end
def copy_resource_label_events
- entity_key = new_entity.class.name.underscore.foreign_key
-
copy_events(ResourceLabelEvent.table_name, original_entity.resource_label_events) do |event|
event.attributes
.except('id', 'reference', 'reference_html')
@@ -80,9 +79,18 @@ module Issuable
end
end
- def event_attributes_with_milestone(event, milestone)
- entity_key = new_entity.class.name.underscore.foreign_key
+ def copy_resource_state_events
+ return unless state_events_supported?
+
+ copy_events(ResourceStateEvent.table_name, original_entity.resource_state_events) do |event|
+ event.attributes
+ .except('id')
+ .merge(entity_key => new_entity.id,
+ 'state' => ResourceStateEvent.states[event.state])
+ end
+ end
+ def event_attributes_with_milestone(event, milestone)
event.attributes
.except('id')
.merge(entity_key => new_entity.id,
@@ -102,12 +110,20 @@ module Issuable
end
def entity_key
- new_entity.class.name.parameterize('_').foreign_key
+ new_entity.class.name.underscore.foreign_key
end
def milestone_events_supported?
- original_entity.respond_to?(:resource_milestone_events) &&
- new_entity.respond_to?(:resource_milestone_events)
+ both_respond_to?(:resource_milestone_events)
+ end
+
+ def state_events_supported?
+ both_respond_to?(:resource_state_events)
+ end
+
+ def both_respond_to?(method)
+ original_entity.respond_to?(method) &&
+ new_entity.respond_to?(method)
end
end
end
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index e55697eebcc..a2167be7949 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -22,6 +22,8 @@ module Projects
import_data
+ after_execute_hook
+
success
rescue Gitlab::UrlBlocker::BlockedUrlError => e
Gitlab::ErrorTracking.track_exception(e, project_path: project.full_path, importer: project.import_type)
@@ -37,6 +39,10 @@ module Projects
private
+ def after_execute_hook
+ # Defined in EE::Projects::ImportService
+ end
+
def add_repository_to_project
if project.external_import? && !unknown_url?
begin
@@ -131,3 +137,5 @@ module Projects
end
end
end
+
+Projects::ImportService.prepend_if_ee('EE::Projects::ImportService')
diff --git a/app/views/groups/_flash_messages.html.haml b/app/views/groups/_flash_messages.html.haml
new file mode 100644
index 00000000000..fa1a9d2cca4
--- /dev/null
+++ b/app/views/groups/_flash_messages.html.haml
@@ -0,0 +1,2 @@
+= content_for :flash_message do
+ = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index e1cda7dbacd..032766327ca 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -8,6 +8,8 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
+= render partial: 'flash_messages'
+
%div{ class: [("limit-container-width" unless fluid_layout)] }
= render_if_exists 'trials/banner', namespace: @group
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index b9327c4573f..752ebcc6add 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1150,7 +1150,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
- :name: migrate_external_diffs
:feature_category: :source_code_management
:has_external_dependencies:
diff --git a/app/workers/incident_management/process_alert_worker.rb b/app/workers/incident_management/process_alert_worker.rb
index e63bcc4cb08..2ce9fe359b5 100644
--- a/app/workers/incident_management/process_alert_worker.rb
+++ b/app/workers/incident_management/process_alert_worker.rb
@@ -35,7 +35,7 @@ module IncidentManagement
return if alert.update(issue_id: issue_id)
- Gitlab::GitLogger.warn(
+ Gitlab::AppLogger.warn(
message: 'Cannot link an Issue with Alert',
issue_id: issue_id,
alert_id: alert_id,
diff --git a/app/workers/merge_request_mergeability_check_worker.rb b/app/workers/merge_request_mergeability_check_worker.rb
index a26c1a886f6..1a84efb4e52 100644
--- a/app/workers/merge_request_mergeability_check_worker.rb
+++ b/app/workers/merge_request_mergeability_check_worker.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-class MergeRequestMergeabilityCheckWorker # rubocop:disable Scalability/IdempotentWorker
+class MergeRequestMergeabilityCheckWorker
include ApplicationWorker
feature_category :source_code_management
+ idempotent!
def perform(merge_request_id)
merge_request = MergeRequest.find_by_id(merge_request_id)