diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-18 11:11:44 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-18 11:11:44 +0000 |
commit | 25989ab7ef1a444ed2abd5479f176d58e1d9462a (patch) | |
tree | 271bb24f3c7178f320cb9de0be0833a285327d09 /app | |
parent | 9bbb32b29703f3ce33dd35d5101145774b793a6d (diff) | |
download | gitlab-ce-25989ab7ef1a444ed2abd5479f176d58e1d9462a.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
137 files changed, 706 insertions, 95 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 2e35ef8d4b0..b4ea415bb51 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -12,23 +12,19 @@ import { GlTooltipDirective, } from '@gitlab/ui'; import { __, s__ } from '~/locale'; +import createFlash from '~/flash'; import Icon from '~/vue_shared/components/icon.vue'; -import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility'; +import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility'; import invalidUrl from '~/lib/utils/invalid_url'; import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue'; +import DateTimePicker from './date_time_picker/date_time_picker.vue'; import MonitorTimeSeriesChart from './charts/time_series.vue'; import MonitorSingleStatChart from './charts/single_stat.vue'; import GraphGroup from './graph_group.vue'; import EmptyState from './empty_state.vue'; -import { sidebarAnimationDuration, timeWindows } from '../constants'; +import { sidebarAnimationDuration } from '../constants'; import TrackEventDirective from '~/vue_shared/directives/track_event'; - -import { - getTimeDiff, - getTimeWindow, - downloadCSVOptions, - generateLinkToChartOptions, -} from '../utils'; +import { getTimeDiff, isValidDate, downloadCSVOptions, generateLinkToChartOptions } from '../utils'; let sidebarMutationObserver; @@ -46,6 +42,7 @@ export default { GlDropdownItem, GlFormGroup, GlModal, + DateTimePicker, }, directives: { GlModal: GlModalDirective, @@ -171,10 +168,8 @@ export default { return { state: 'gettingStarted', elWidth: 0, - selectedTimeWindow: '', - selectedTimeWindowKey: '', formIsValid: null, - timeWindows: {}, + selectedTimeWindow: {}, isRearrangingPanels: false, }; }, @@ -237,11 +232,13 @@ export default { end, }; - this.timeWindows = timeWindows; - this.selectedTimeWindowKey = getTimeWindow(range); - this.selectedTimeWindow = this.timeWindows[this.selectedTimeWindowKey]; + this.selectedTimeWindow = range; - this.fetchData(range); + if (!isValidDate(start) || !isValidDate(end)) { + this.showInvalidDateError(); + } else { + this.fetchData(range); + } sidebarMutationObserver = new MutationObserver(this.onSidebarMutation); sidebarMutationObserver.observe(document.querySelector('.layout-page'), { @@ -298,6 +295,9 @@ export default { // See https://gitlab.com/gitlab-org/gitlab/issues/27835 metrics.splice(graphIndex, 1); }, + showInvalidDateError() { + createFlash(s__('Metrics|Link contains an invalid time window.')); + }, generateLink(group, title, yLabel) { const dashboard = this.currentDashboard || this.firstDashboard.path; const params = _.pick({ dashboard, group, title, y_label: yLabel }, value => value != null); @@ -320,16 +320,12 @@ export default { submitCustomMetricsForm() { this.$refs.customMetricsForm.submit(); }, - activeTimeWindow(key) { - return this.timeWindows[key] === this.selectedTimeWindow; - }, - setTimeWindowParameter(key) { - const { start, end } = getTimeDiff(key); - return `?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`; - }, groupHasData(group) { return this.chartsWithData(group.metrics).length > 0; }, + onDateTimePickerApply(timeWindowUrlParams) { + return redirectTo(mergeUrlParams(timeWindowUrlParams, window.location.href)); + }, downloadCSVOptions, generateLinkToChartOptions, }, @@ -342,14 +338,14 @@ export default { <template> <div class="prometheus-graphs"> - <div class="gl-p-3 pb-0 border-bottom bg-gray-light"> + <div class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light"> <div class="row"> <template v-if="environmentsEndpoint"> <gl-form-group :label="__('Dashboard')" label-size="sm" label-for="monitor-dashboards-dropdown" - class="col-sm-12 col-md-4 col-lg-2" + class="col-sm-12 col-md-6 col-lg-2" > <gl-dropdown id="monitor-dashboards-dropdown" @@ -372,7 +368,7 @@ export default { :label="s__('Metrics|Environment')" label-size="sm" label-for="monitor-environments-dropdown" - class="col-sm-6 col-md-4 col-lg-2" + class="col-sm-6 col-md-6 col-lg-2" > <gl-dropdown id="monitor-environments-dropdown" @@ -397,30 +393,19 @@ export default { :label="s__('Metrics|Show last')" label-size="sm" label-for="monitor-time-window-dropdown" - class="col-sm-6 col-md-4 col-lg-2" + class="col-sm-6 col-md-6 col-lg-4" > - <gl-dropdown - id="monitor-time-window-dropdown" - class="mb-0 d-flex js-time-window-dropdown" - toggle-class="dropdown-menu-toggle" - :text="selectedTimeWindow" - > - <gl-dropdown-item - v-for="(value, key) in timeWindows" - :key="key" - :active="activeTimeWindow(key)" - :href="setTimeWindowParameter(key)" - active-class="active" - >{{ value }}</gl-dropdown-item - > - </gl-dropdown> + <date-time-picker + :selected-time-window="selectedTimeWindow" + @onApply="onDateTimePickerApply" + /> </gl-form-group> </template> <gl-form-group v-if="addingMetricsAvailable || showRearrangePanelsBtn || externalDashboardUrl.length" label-for="prometheus-graphs-dropdown-buttons" - class="dropdown-buttons col-lg d-lg-flex align-items-end" + class="dropdown-buttons col-md d-md-flex col-lg d-lg-flex align-items-end" > <div id="prometheus-graphs-dropdown-buttons"> <gl-button diff --git a/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker.vue new file mode 100644 index 00000000000..4616a767295 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker.vue @@ -0,0 +1,151 @@ +<script> +import { GlButton, GlDropdown, GlDropdownItem, GlFormGroup } from '@gitlab/ui'; +import { s__, sprintf } from '~/locale'; +import Icon from '~/vue_shared/components/icon.vue'; +import DateTimePickerInput from './date_time_picker_input.vue'; +import { + getTimeDiff, + getTimeWindow, + stringToISODate, + ISODateToString, + truncateZerosInDateTime, + isDateTimePickerInputValid, +} from '~/monitoring/utils'; +import { timeWindows } from '~/monitoring/constants'; + +export default { + components: { + Icon, + DateTimePickerInput, + GlFormGroup, + GlButton, + GlDropdown, + GlDropdownItem, + }, + props: { + timeWindows: { + type: Object, + required: false, + default: () => timeWindows, + }, + selectedTimeWindow: { + type: Object, + required: false, + default: () => {}, + }, + }, + data() { + return { + selectedTimeWindowText: '', + customTime: { + from: null, + to: null, + }, + }; + }, + computed: { + applyEnabled() { + return Boolean(this.inputState.from && this.inputState.to); + }, + inputState() { + const { from, to } = this.customTime; + return { + from: from && isDateTimePickerInputValid(from), + to: to && isDateTimePickerInputValid(to), + }; + }, + }, + mounted() { + const range = getTimeWindow(this.selectedTimeWindow); + if (range) { + this.selectedTimeWindowText = this.timeWindows[range]; + } else { + this.customTime = { + from: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.start)), + to: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.end)), + }; + this.selectedTimeWindowText = sprintf(s__('%{from} to %{to}'), this.customTime); + } + }, + methods: { + activeTimeWindow(key) { + return this.timeWindows[key] === this.selectedTimeWindowText; + }, + setCustomTimeWindowParameter() { + this.$emit('onApply', { + start: stringToISODate(this.customTime.from), + end: stringToISODate(this.customTime.to), + }); + }, + setTimeWindowParameter(key) { + const { start, end } = getTimeDiff(key); + this.$emit('onApply', { + start, + end, + }); + }, + closeDropdown() { + this.$refs.dropdown.hide(); + }, + }, +}; +</script> +<template> + <gl-dropdown + ref="dropdown" + :text="selectedTimeWindowText" + menu-class="time-window-dropdown-menu" + class="js-time-window-dropdown" + > + <div class="d-flex justify-content-between time-window-dropdown-menu-container"> + <gl-form-group + :label="__('Custom range')" + label-for="custom-from-time" + class="custom-time-range-form-group col-md-7 p-0 m-0" + > + <date-time-picker-input + id="custom-time-from" + v-model="customTime.from" + :label="__('From')" + :state="inputState.from" + /> + <date-time-picker-input + id="custom-time-to" + v-model="customTime.to" + :label="__('To')" + :state="inputState.to" + /> + <gl-form-group> + <gl-button @click="closeDropdown">{{ __('Cancel') }}</gl-button> + <gl-button + variant="success" + :disabled="!applyEnabled" + @click="setCustomTimeWindowParameter" + >{{ __('Apply') }}</gl-button + > + </gl-form-group> + </gl-form-group> + <gl-form-group + :label="__('Quick range')" + label-for="group-id-dropdown" + label-align="center" + class="col-md-4 p-0 m-0" + > + <gl-dropdown-item + v-for="(value, key) in timeWindows" + :key="key" + :active="activeTimeWindow(key)" + active-class="active" + @click="setTimeWindowParameter(key)" + > + <icon + name="mobile-issue-close" + class="align-bottom" + :class="{ invisible: !activeTimeWindow(key) }" + /> + {{ value }} + </gl-dropdown-item> + </gl-form-group> + </div> + </gl-dropdown> +</template> diff --git a/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker_input.vue b/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker_input.vue new file mode 100644 index 00000000000..0388a6190d9 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/date_time_picker/date_time_picker_input.vue @@ -0,0 +1,77 @@ +<script> +import _ from 'underscore'; +import { s__, sprintf } from '~/locale'; +import { GlFormGroup, GlFormInput } from '@gitlab/ui'; +import { dateFormats } from '~/monitoring/constants'; + +const inputGroupText = { + invalidFeedback: sprintf(s__('Format: %{dateFormat}'), { + dateFormat: dateFormats.dateTimePicker.format, + }), + placeholder: dateFormats.dateTimePicker.format, +}; + +export default { + components: { + GlFormGroup, + GlFormInput, + }, + props: { + state: { + default: null, + required: true, + validator: prop => typeof prop === 'boolean' || prop === null, + }, + value: { + default: null, + required: false, + validator: prop => typeof prop === 'string' || prop === null, + }, + label: { + type: String, + default: '', + required: true, + }, + id: { + type: String, + required: false, + default: () => _.uniqueId('dateTimePicker_'), + }, + }, + data() { + return { + inputGroupText, + }; + }, + computed: { + invalidFeedback() { + return this.state ? '' : this.inputGroupText.invalidFeedback; + }, + inputState() { + // When the state is valid we want to show no + // green outline. Hence passing null and not true. + if (this.state === true) { + return null; + } + return this.state; + }, + }, + methods: { + onInputBlur(e) { + this.$emit('input', e.target.value.trim() || null); + }, + }, +}; +</script> + +<template> + <gl-form-group :label="label" label-size="sm" :label-for="id" :invalid-feedback="invalidFeedback"> + <gl-form-input + :id="id" + :value="value" + :state="inputState" + :placeholder="inputGroupText.placeholder" + @blur="onInputBlur" + /> + </gl-form-group> +</template> diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js index 13aba3d9f44..2836fe4fc26 100644 --- a/app/assets/javascripts/monitoring/constants.js +++ b/app/assets/javascripts/monitoring/constants.js @@ -3,6 +3,11 @@ import { __ } from '~/locale'; export const sidebarAnimationDuration = 300; // milliseconds. export const chartHeight = 300; +/** + * Valid strings for this regex are + * 2019-10-01 and 2019-10-01 01:02:03 + */ +export const dateTimePickerRegex = /^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])(?: (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?$/; export const graphTypes = { deploymentData: 'scatter', @@ -28,6 +33,11 @@ export const timeWindows = { export const dateFormats = { timeOfDay: 'h:MM TT', default: 'dd mmm yyyy, h:MMTT', + dateTimePicker: { + format: 'yyyy-mm-dd hh:mm:ss', + ISODate: "yyyy-mm-dd'T'HH:MM:ss'Z'", + stringDate: 'yyyy-mm-dd HH:MM:ss', + }, }; export const secondsIn = { diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js index 9049695b992..4c72f5226b7 100644 --- a/app/assets/javascripts/monitoring/utils.js +++ b/app/assets/javascripts/monitoring/utils.js @@ -1,4 +1,5 @@ -import { secondsIn, timeWindowsKeyNames } from './constants'; +import dateformat from 'dateformat'; +import { secondsIn, dateTimePickerRegex, dateFormats } from './constants'; const secondsToMilliseconds = seconds => seconds * 1000; @@ -19,7 +20,49 @@ export const getTimeWindow = ({ start, end }) => return timeRange; } return acc; - }, timeWindowsKeyNames.eightHours); + }, null); + +export const isDateTimePickerInputValid = val => dateTimePickerRegex.test(val); + +export const truncateZerosInDateTime = datetime => datetime.replace(' 00:00:00', ''); + +/** + * The URL params start and end need to be validated + * before passing them down to other components. + * + * @param {string} dateString + */ +export const isValidDate = dateString => { + try { + // dateformat throws error that can be caught. + // This is better than using `new Date()` + if (dateString && dateString.trim()) { + dateformat(dateString, 'isoDateTime'); + return true; + } + return false; + } catch { + return false; + } +}; + +/** + * Convert the input in Time picker component to ISO date. + * + * @param {string} val + * @returns {string} + */ +export const stringToISODate = val => + dateformat(new Date(val.replace(/-/g, '/')), dateFormats.dateTimePicker.ISODate, true); + +/** + * Convert the ISO date received from the URL to string + * for the Time picker component. + * + * @param {Date} date + * @returns {string} + */ +export const ISODateToString = date => dateformat(date, dateFormats.dateTimePicker.stringDate); /** * This method is used to validate if the graph data format for a chart component diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss index ceafff94719..154e505f7a4 100644 --- a/app/assets/stylesheets/pages/prometheus.scss +++ b/app/assets/stylesheets/pages/prometheus.scss @@ -46,6 +46,20 @@ } } +.prometheus-graphs-header { + .time-window-dropdown-menu { + padding: $gl-padding $gl-padding 0 $gl-padding-12; + } + + .time-window-dropdown-menu-container { + width: 360px; + } + + .custom-time-range-form-group > label { + padding-bottom: $gl-padding; + } +} + .prometheus-panel { margin-top: 20px; } diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 2364777cdc5..477093ddadf 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -161,7 +161,7 @@ class IssuableFinder labels_count = label_names.any? ? label_names.count : 1 labels_count = 1 if use_cte_for_search? - finder.execute.reorder(nil).group(:state).count.each do |key, value| + finder.execute.reorder(nil).group(:state_id).count.each do |key, value| counts[count_key(key)] += value / labels_count end @@ -385,7 +385,8 @@ class IssuableFinder end def count_key(value) - Array(value).last.to_sym + value = Array(value).last + klass.available_states.key(value) end # Negates all params found in `negatable_params` @@ -444,7 +445,6 @@ class IssuableFinder items end - # rubocop: disable CodeReuse/ActiveRecord def by_state(items) case params[:state].to_s when 'closed' @@ -454,12 +454,11 @@ class IssuableFinder when 'opened' items.opened when 'locked' - items.where(state: 'locked') + items.with_state(:locked) else items end end - # rubocop: enable CodeReuse/ActiveRecord def by_group(items) # Selection by group is already covered by `by_project` and `projects` diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 5e52062ef40..3bf19399cec 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -217,6 +217,8 @@ module Ci scope :for_sha, -> (sha) { where(sha: sha) } scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) } scope :for_sha_or_source_sha, -> (sha) { for_sha(sha).or(for_source_sha(sha)) } + scope :for_ref, -> (ref) { where(ref: ref) } + scope :for_id, -> (id) { where(id: id) } scope :created_after, -> (time) { where('ci_pipelines.created_at > ?', time) } scope :triggered_by_merge_request, -> (merge_request) do diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 94a0de556f4..852576dbbc2 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -25,12 +25,20 @@ module Issuable include UpdatedAtFilterable include IssuableStates include ClosedAtFilterable + include VersionedDescription TITLE_LENGTH_MAX = 255 TITLE_HTML_LENGTH_MAX = 800 DESCRIPTION_LENGTH_MAX = 1.megabyte DESCRIPTION_HTML_LENGTH_MAX = 5.megabytes + STATE_ID_MAP = { + opened: 1, + closed: 2, + merged: 3, + locked: 4 + }.with_indifferent_access.freeze + # This object is used to gather issuable meta data for displaying # upvotes, downvotes, notes and closing merge requests count for issues and merge requests # lists avoiding n+1 queries and improving performance. @@ -172,13 +180,17 @@ module Issuable fuzzy_search(query, [:title]) end - # Available state values persisted in state_id column using state machine + def available_states + @available_states ||= STATE_ID_MAP.slice(*available_state_names) + end + + # Available state names used to persist state_id column using state machine # # Override this on subclasses if different states are needed # - # Check MergeRequest.available_states for example - def available_states - @available_states ||= { opened: 1, closed: 2 }.with_indifferent_access + # Check MergeRequest.available_states_names for example + def available_state_names + [:opened, :closed] end # Searches for records with a matching title or description. @@ -297,6 +309,14 @@ module Issuable end end + def state + self.class.available_states.key(state_id) + end + + def state=(value) + self.state_id = self.class.available_states[value] + end + def resource_parent project end diff --git a/app/models/concerns/issuable_states.rb b/app/models/concerns/issuable_states.rb index 33bc41d7f44..f0b9f0d1f3a 100644 --- a/app/models/concerns/issuable_states.rb +++ b/app/models/concerns/issuable_states.rb @@ -4,22 +4,20 @@ module IssuableStates extend ActiveSupport::Concern # The state:string column is being migrated to state_id:integer column - # This is a temporary hook to populate state_id column with new values - # and should be removed after the state column is removed. - # Check https://gitlab.com/gitlab-org/gitlab-foss/issues/51789 for more information + # This is a temporary hook to keep state column in sync until it is removed. + # Check https: https://gitlab.com/gitlab-org/gitlab/issues/33814 for more information + # The state column can be safely removed after 2019-10-27 included do - before_save :set_state_id + before_save :sync_issuable_deprecated_state end - def set_state_id - return if state.nil? || state.empty? + def sync_issuable_deprecated_state + return if self.is_a?(Epic) + return unless respond_to?(:state) + return if state_id.nil? - # Needed to prevent breaking some migration specs that - # rollback database to a point where state_id does not exist. - # We can use this guard clause for now since this file will - # be removed in the next release. - return unless self.has_attribute?(:state_id) + deprecated_state = self.class.available_states.key(state_id) - self.state_id = self.class.available_states[state] + self.write_attribute(:state, deprecated_state) end end diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index 3deb86da6cf..42b370990ac 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -6,7 +6,9 @@ module Milestoneish end def closed_issues_count(user) - count_issues_by_state(user)['closed'].to_i + closed_state_id = Issue.available_states[:closed] + + count_issues_by_state(user)[closed_state_id].to_i end def complete?(user) @@ -117,7 +119,7 @@ module Milestoneish def count_issues_by_state(user) memoize_per_user(user, :count_issues_by_state) do - issues_visible_to_user(user).reorder(nil).group(:state).count + issues_visible_to_user(user).reorder(nil).group(:state_id).count end end diff --git a/app/models/concerns/versioned_description.rb b/app/models/concerns/versioned_description.rb new file mode 100644 index 00000000000..63a24aadc8a --- /dev/null +++ b/app/models/concerns/versioned_description.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module VersionedDescription + extend ActiveSupport::Concern + + included do + attr_accessor :saved_description_version + + has_many :description_versions + + after_update :save_description_version + end + + private + + def save_description_version + self.saved_description_version = nil + + return unless Feature.enabled?(:save_description_versions, issuing_parent) + return unless saved_change_to_description? + + unless description_versions.exists? + description_versions.create!( + description: description_before_last_save, + created_at: created_at + ) + end + + self.saved_description_version = description_versions.create!(description: description) + end +end diff --git a/app/models/concerns/worker_attributes.rb b/app/models/concerns/worker_attributes.rb new file mode 100644 index 00000000000..af40e9e3b19 --- /dev/null +++ b/app/models/concerns/worker_attributes.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module WorkerAttributes + extend ActiveSupport::Concern + + class_methods do + def feature_category(value) + raise "Invalid category. Use `feature_category_not_owned!` to mark a worker as not owned" if value == :not_owned + + worker_attributes[:feature_category] = value + end + + # Special case: mark this work as not associated with a feature category + # this should be used for cross-cutting concerns, such as mailer workers. + def feature_category_not_owned! + worker_attributes[:feature_category] = :not_owned + end + + def get_feature_category + get_worker_attribute(:feature_category) + end + + def feature_category_not_owned? + get_worker_attribute(:feature_category) == :not_owned + end + + protected + + # Returns a worker attribute declared on this class or its parent class. + # This approach allows declared attributes to be inherited by + # child classes. + def get_worker_attribute(name) + worker_attributes[name] || superclass_worker_attributes(name) + end + + private + + def worker_attributes + @attributes ||= {} + end + + def superclass_worker_attributes(name) + return unless superclass.include? WorkerAttributes + + superclass.get_worker_attribute(name) + end + end +end diff --git a/app/models/description_version.rb b/app/models/description_version.rb new file mode 100644 index 00000000000..abab7f94212 --- /dev/null +++ b/app/models/description_version.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class DescriptionVersion < ApplicationRecord + belongs_to :issue + belongs_to :merge_request + + validate :exactly_one_issuable + + def self.issuable_attrs + %i(issue merge_request).freeze + end + + private + + def exactly_one_issuable + issuable_count = self.class.issuable_attrs.count { |attr| self["#{attr}_id"] } + + errors.add(:base, "Exactly one of #{self.class.issuable_attrs.join(', ')} is required") if issuable_count != 1 + end +end + +DescriptionVersion.prepend_if_ee('EE::DescriptionVersion') diff --git a/app/models/issue.rb b/app/models/issue.rb index d0b2165fcc7..b9b481ac29b 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -71,7 +71,7 @@ class Issue < ApplicationRecord attr_spammable :title, spam_title: true attr_spammable :description, spam_description: true - state_machine :state, initial: :opened do + state_machine :state_id, initial: :opened do event :close do transition [:opened] => :closed end @@ -80,8 +80,8 @@ class Issue < ApplicationRecord transition closed: :opened end - state :opened - state :closed + state :opened, value: Issue.available_states[:opened] + state :closed, value: Issue.available_states[:closed] before_transition any => :closed do |issue| issue.closed_at = issue.system_note_timestamp @@ -93,6 +93,13 @@ class Issue < ApplicationRecord end end + # Alias to state machine .with_state_id method + # This needs to be defined after the state machine block to avoid errors + class << self + alias_method :with_state, :with_state_id + alias_method :with_states, :with_state_ids + end + def self.relative_positioning_query_base(issue) in_projects(issue.parent_ids) end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 50efe5d6aa0..7cdaa3e3ca7 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -85,7 +85,13 @@ class MergeRequest < ApplicationRecord # when creating new merge request attr_accessor :can_be_created, :compare_commits, :diff_options, :compare - state_machine :state, initial: :opened do + # Keep states definition to be evaluated before the state_machine block to avoid spec failures. + # If this gets evaluated after, the `merged` and `locked` states which are overrided can be nil. + def self.available_state_names + super + [:merged, :locked] + end + + state_machine :state_id, initial: :opened do event :close do transition [:opened] => :closed end @@ -116,10 +122,17 @@ class MergeRequest < ApplicationRecord end end - state :opened - state :closed - state :merged - state :locked + state :opened, value: MergeRequest.available_states[:opened] + state :closed, value: MergeRequest.available_states[:closed] + state :merged, value: MergeRequest.available_states[:merged] + state :locked, value: MergeRequest.available_states[:locked] + end + + # Alias to state machine .with_state_id method + # This needs to be defined after the state machine block to avoid errors + class << self + alias_method :with_state, :with_state_id + alias_method :with_states, :with_state_ids end state_machine :merge_status, initial: :unchecked do @@ -211,10 +224,6 @@ class MergeRequest < ApplicationRecord '!' end - def self.available_states - @available_states ||= super.merge(merged: 3, locked: 4) - end - # Returns the top 100 target branches # # The returned value is a Array containing branch names diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index fe8ba9765b7..735ad046f22 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -83,7 +83,7 @@ class MergeRequestDiff < ApplicationRecord metrics_join = mr_diffs.join(mr_metrics).on(metrics_join_condition) - condition = MergeRequest.arel_table[:state].eq(:merged) + condition = MergeRequest.arel_table[:state_id].eq(MergeRequest.available_states[:merged]) .and(MergeRequest::Metrics.arel_table[:merged_at].lteq(before)) .and(MergeRequest::Metrics.arel_table[:merged_at].not_eq(nil)) @@ -91,7 +91,7 @@ class MergeRequestDiff < ApplicationRecord end scope :old_closed_diffs, -> (before) do - condition = MergeRequest.arel_table[:state].eq(:closed) + condition = MergeRequest.arel_table[:state_id].eq(MergeRequest.available_states[:closed]) .and(MergeRequest::Metrics.arel_table[:latest_closed_at].lteq(before)) joins(merge_request: :metrics).where(condition) diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 1d0b37abf72..019bd54f48c 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -161,7 +161,7 @@ class HipchatService < Service obj_attr = data[:object_attributes] obj_attr = HashWithIndifferentAccess.new(obj_attr) title = render_line(obj_attr[:title]) - state = obj_attr[:state] + state = Issue.available_states.key(obj_attr[:state_id]) issue_iid = obj_attr[:iid] issue_url = obj_attr[:url] description = obj_attr[:description] diff --git a/app/models/push_event.rb b/app/models/push_event.rb index 6f7365a2763..5cab686f20b 100644 --- a/app/models/push_event.rb +++ b/app/models/push_event.rb @@ -54,7 +54,7 @@ class PushEvent < Event .select(1) .where('merge_requests.source_project_id = events.project_id') .where('merge_requests.source_branch = push_event_payloads.ref') - .where(state: :opened) + .with_state(:opened) # For reasons unknown the use of #eager_load will result in the # "push_event_payload" association not being set. Because of this we're diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb index 8ec90ca25d3..11cbeb60bba 100644 --- a/app/models/system_note_metadata.rb +++ b/app/models/system_note_metadata.rb @@ -23,6 +23,7 @@ class SystemNoteMetadata < ApplicationRecord validates :action, inclusion: { in: :icon_types }, allow_nil: true belongs_to :note + belongs_to :description_version def icon_types ICON_TYPES diff --git a/app/serializers/projects/serverless/service_entity.rb b/app/serializers/projects/serverless/service_entity.rb index 40ac52d96af..a1e0bf02d11 100644 --- a/app/serializers/projects/serverless/service_entity.rb +++ b/app/serializers/projects/serverless/service_entity.rb @@ -44,7 +44,7 @@ module Projects end expose :url do |service| - service.dig('status', 'url') + service.dig('status', 'url') || "http://#{service.dig('status', 'domain')}" end expose :description do |service| diff --git a/app/services/issuable/clone/content_rewriter.rb b/app/services/issuable/clone/content_rewriter.rb index f75b51c4be3..67d2f9fd3fe 100644 --- a/app/services/issuable/clone/content_rewriter.rb +++ b/app/services/issuable/clone/content_rewriter.rb @@ -39,6 +39,10 @@ module Issuable if note.system_note_metadata new_params[:system_note_metadata] = note.system_note_metadata.dup + + # TODO: Implement copying of description versions when an issue is moved + # https://gitlab.com/gitlab-org/gitlab/issues/32300 + new_params[:system_note_metadata].description_version = nil end new_note.update(new_params) diff --git a/app/services/note_summary.rb b/app/services/note_summary.rb index 60a68568833..6fe14939aaa 100644 --- a/app/services/note_summary.rb +++ b/app/services/note_summary.rb @@ -10,6 +10,10 @@ class NoteSummary project: project, author: author, note: body } @metadata = { action: action, commit_count: commit_count }.compact + if action == 'description' && noteable.saved_description_version + @metadata[:description_version] = noteable.saved_description_version + end + set_commit_params if note[:noteable].is_a?(Commit) end diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb index f99ad987156..36bde629f9c 100644 --- a/app/uploaders/object_storage.rb +++ b/app/uploaders/object_storage.rb @@ -180,10 +180,11 @@ module ObjectStorage end def workhorse_authorize(has_length:, maximum_size: nil) - { - RemoteObject: workhorse_remote_upload_options(has_length: has_length, maximum_size: maximum_size), - TempPath: workhorse_local_upload_path - }.compact + if self.object_store_enabled? && self.direct_upload_enabled? + { RemoteObject: workhorse_remote_upload_options(has_length: has_length, maximum_size: maximum_size) } + else + { TempPath: workhorse_local_upload_path } + end end def workhorse_local_upload_path diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 49e482ff1df..2633a3899f7 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -20,4 +20,5 @@ - if new_issue_email = render 'projects/issuable_by_email', email: new_issue_email, issuable_type: 'issue' - else - = render 'shared/empty_states/issues', button_path: new_project_issue_path(@project), show_import_button: true + - new_project_issue_button_path = @project.archived? ? false : new_project_issue_path(@project) + = render 'shared/empty_states/issues', new_project_issue_button_path: new_project_issue_button_path, show_import_button: true diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index 9173b802dd4..325e01bb5c8 100644 --- a/app/views/shared/empty_states/_issues.html.haml +++ b/app/views/shared/empty_states/_issues.html.haml @@ -1,4 +1,4 @@ -- button_path = local_assigns.fetch(:button_path, false) +- button_path = local_assigns.fetch(:new_project_issue_button_path, false) - project_select_button = local_assigns.fetch(:project_select_button, false) - show_import_button = local_assigns.fetch(:show_import_button, false) && can?(current_user, :import_issues, @project) - has_button = button_path || project_select_button @@ -56,4 +56,3 @@ - if show_import_button = render 'projects/issues/import_csv/modal' - diff --git a/app/workers/admin_email_worker.rb b/app/workers/admin_email_worker.rb index f69e74b2674..be05d2a6752 100644 --- a/app/workers/admin_email_worker.rb +++ b/app/workers/admin_email_worker.rb @@ -4,6 +4,8 @@ class AdminEmailWorker include ApplicationWorker include CronjobQueue + feature_category_not_owned! + def perform send_repository_check_mail if Gitlab::CurrentSettings.repository_checks_enabled end diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb index c9ddeb08613..577c439f4a2 100644 --- a/app/workers/authorized_projects_worker.rb +++ b/app/workers/authorized_projects_worker.rb @@ -4,6 +4,8 @@ class AuthorizedProjectsWorker include ApplicationWorker prepend WaitableWorker + feature_category :authentication_and_authorization + # This is a workaround for a Ruby 2.3.7 bug. rspec-mocks cannot restore the # visibility of prepended modules. See https://github.com/rspec/rspec-mocks/issues/1231 # for more details. diff --git a/app/workers/auto_merge_process_worker.rb b/app/workers/auto_merge_process_worker.rb index cd81cdbc60c..e4dccb891ce 100644 --- a/app/workers/auto_merge_process_worker.rb +++ b/app/workers/auto_merge_process_worker.rb @@ -4,6 +4,7 @@ class AutoMergeProcessWorker include ApplicationWorker queue_namespace :auto_merge + feature_category :continuous_delivery def perform(merge_request_id) MergeRequest.find_by_id(merge_request_id).try do |merge_request| diff --git a/app/workers/background_migration_worker.rb b/app/workers/background_migration_worker.rb index b83412b5e6e..20e2cdd7f96 100644 --- a/app/workers/background_migration_worker.rb +++ b/app/workers/background_migration_worker.rb @@ -3,6 +3,8 @@ class BackgroundMigrationWorker include ApplicationWorker + feature_category_not_owned! + # The minimum amount of time between processing two jobs of the same migration # class. # diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb index b0c3676714c..15b31acf3e5 100644 --- a/app/workers/build_hooks_worker.rb +++ b/app/workers/build_hooks_worker.rb @@ -5,6 +5,7 @@ class BuildHooksWorker include PipelineQueue queue_namespace :pipeline_hooks + feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord def perform(build_id) diff --git a/app/workers/build_queue_worker.rb b/app/workers/build_queue_worker.rb index 67d5b0f5f5b..6584fba4c65 100644 --- a/app/workers/build_queue_worker.rb +++ b/app/workers/build_queue_worker.rb @@ -5,6 +5,7 @@ class BuildQueueWorker include PipelineQueue queue_namespace :pipeline_processing + feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord def perform(build_id) diff --git a/app/workers/chat_notification_worker.rb b/app/workers/chat_notification_worker.rb index 25a306e94d8..3bc2edad62c 100644 --- a/app/workers/chat_notification_worker.rb +++ b/app/workers/chat_notification_worker.rb @@ -3,6 +3,8 @@ class ChatNotificationWorker include ApplicationWorker + feature_category :chatops + RESCHEDULE_INTERVAL = 2.seconds # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/workers/ci/archive_traces_cron_worker.rb b/app/workers/ci/archive_traces_cron_worker.rb index ad7a29719ac..74f389175b9 100644 --- a/app/workers/ci/archive_traces_cron_worker.rb +++ b/app/workers/ci/archive_traces_cron_worker.rb @@ -5,6 +5,8 @@ module Ci include ApplicationWorker include CronjobQueue + feature_category :continuous_integration + # rubocop: disable CodeReuse/ActiveRecord def perform # Archive stale live traces which still resides in redis or database diff --git a/app/workers/ci/build_prepare_worker.rb b/app/workers/ci/build_prepare_worker.rb index 1a35a74ae53..20208c18d03 100644 --- a/app/workers/ci/build_prepare_worker.rb +++ b/app/workers/ci/build_prepare_worker.rb @@ -6,6 +6,7 @@ module Ci include PipelineQueue queue_namespace :pipeline_processing + feature_category :continuous_integration def perform(build_id) Ci::Build.find_by_id(build_id).try do |build| diff --git a/app/workers/ci/build_schedule_worker.rb b/app/workers/ci/build_schedule_worker.rb index da219adffc6..f22ec4c7810 100644 --- a/app/workers/ci/build_schedule_worker.rb +++ b/app/workers/ci/build_schedule_worker.rb @@ -6,6 +6,7 @@ module Ci include PipelineQueue queue_namespace :pipeline_processing + feature_category :continuous_integration def perform(build_id) ::Ci::Build.find_by_id(build_id).try do |build| diff --git a/app/workers/cleanup_container_repository_worker.rb b/app/workers/cleanup_container_repository_worker.rb index 0331fc7b01c..83fb3e58d29 100644 --- a/app/workers/cleanup_container_repository_worker.rb +++ b/app/workers/cleanup_container_repository_worker.rb @@ -4,6 +4,7 @@ class CleanupContainerRepositoryWorker include ApplicationWorker queue_namespace :container_repository + feature_category :container_registry attr_reader :container_repository, :current_user diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb index 2b36ccb8304..62748808ff1 100644 --- a/app/workers/concerns/application_worker.rb +++ b/app/workers/concerns/application_worker.rb @@ -8,6 +8,7 @@ module ApplicationWorker extend ActiveSupport::Concern include Sidekiq::Worker # rubocop:disable Cop/IncludeSidekiqWorker + include WorkerAttributes included do set_queue diff --git a/app/workers/concerns/auto_devops_queue.rb b/app/workers/concerns/auto_devops_queue.rb index aba928ccaab..61e3c1544bd 100644 --- a/app/workers/concerns/auto_devops_queue.rb +++ b/app/workers/concerns/auto_devops_queue.rb @@ -5,5 +5,6 @@ module AutoDevopsQueue included do queue_namespace :auto_devops + feature_category :auto_devops end end diff --git a/app/workers/concerns/chaos_queue.rb b/app/workers/concerns/chaos_queue.rb index e406509d12d..c5db10491f2 100644 --- a/app/workers/concerns/chaos_queue.rb +++ b/app/workers/concerns/chaos_queue.rb @@ -5,5 +5,6 @@ module ChaosQueue included do queue_namespace :chaos + feature_category :chaos_engineering end end diff --git a/app/workers/concerns/cluster_queue.rb b/app/workers/concerns/cluster_queue.rb index e44b40c36c9..180b86b0124 100644 --- a/app/workers/concerns/cluster_queue.rb +++ b/app/workers/concerns/cluster_queue.rb @@ -8,5 +8,6 @@ module ClusterQueue included do queue_namespace :gcp_cluster + feature_category :kubernetes_configuration end end diff --git a/app/workers/concerns/gitlab/github_import/object_importer.rb b/app/workers/concerns/gitlab/github_import/object_importer.rb index eeeff6e93a0..b856a9329dd 100644 --- a/app/workers/concerns/gitlab/github_import/object_importer.rb +++ b/app/workers/concerns/gitlab/github_import/object_importer.rb @@ -12,6 +12,8 @@ module Gitlab include GithubImport::Queue include ReschedulingMethods include NotifyUponDeath + + feature_category :importers end # project - An instance of `Project` to import the data into. diff --git a/app/workers/concerns/gitlab/github_import/queue.rb b/app/workers/concerns/gitlab/github_import/queue.rb index 59b621f16ab..7cc23dd7c0b 100644 --- a/app/workers/concerns/gitlab/github_import/queue.rb +++ b/app/workers/concerns/gitlab/github_import/queue.rb @@ -7,6 +7,7 @@ module Gitlab included do queue_namespace :github_importer + feature_category :importers # If a job produces an error it may block a stage from advancing # forever. To prevent this from happening we prevent jobs from going to diff --git a/app/workers/concerns/object_pool_queue.rb b/app/workers/concerns/object_pool_queue.rb index 5b648df9c72..c2e84470fba 100644 --- a/app/workers/concerns/object_pool_queue.rb +++ b/app/workers/concerns/object_pool_queue.rb @@ -8,5 +8,6 @@ module ObjectPoolQueue included do queue_namespace :object_pool + feature_category :gitaly end end diff --git a/app/workers/concerns/pipeline_background_queue.rb b/app/workers/concerns/pipeline_background_queue.rb index bbb8ad0c982..0a23780b807 100644 --- a/app/workers/concerns/pipeline_background_queue.rb +++ b/app/workers/concerns/pipeline_background_queue.rb @@ -8,5 +8,6 @@ module PipelineBackgroundQueue included do queue_namespace :pipeline_background + feature_category :continuous_integration end end diff --git a/app/workers/concerns/pipeline_queue.rb b/app/workers/concerns/pipeline_queue.rb index 3aaed4669e5..27cbf6eb61c 100644 --- a/app/workers/concerns/pipeline_queue.rb +++ b/app/workers/concerns/pipeline_queue.rb @@ -8,5 +8,6 @@ module PipelineQueue included do queue_namespace :pipeline_default + feature_category :continuous_integration end end diff --git a/app/workers/concerns/repository_check_queue.rb b/app/workers/concerns/repository_check_queue.rb index 216d67e5dbc..76f6e1c2e91 100644 --- a/app/workers/concerns/repository_check_queue.rb +++ b/app/workers/concerns/repository_check_queue.rb @@ -6,7 +6,7 @@ module RepositoryCheckQueue included do queue_namespace :repository_check - sidekiq_options retry: false + feature_category :source_code_management end end diff --git a/app/workers/concerns/todos_destroyer_queue.rb b/app/workers/concerns/todos_destroyer_queue.rb index 8e2b1d30579..1bbccbfb1f9 100644 --- a/app/workers/concerns/todos_destroyer_queue.rb +++ b/app/workers/concerns/todos_destroyer_queue.rb @@ -8,5 +8,6 @@ module TodosDestroyerQueue included do queue_namespace :todos_destroyer + feature_category :issue_tracking end end diff --git a/app/workers/create_evidence_worker.rb b/app/workers/create_evidence_worker.rb index 5fc901ae514..027dbd2f101 100644 --- a/app/workers/create_evidence_worker.rb +++ b/app/workers/create_evidence_worker.rb @@ -3,6 +3,8 @@ class CreateEvidenceWorker include ApplicationWorker + feature_category :release_governance + def perform(release_id) release = Release.find_by_id(release_id) return unless release diff --git a/app/workers/create_gpg_signature_worker.rb b/app/workers/create_gpg_signature_worker.rb index e3fb5d479ae..fc36a2adccd 100644 --- a/app/workers/create_gpg_signature_worker.rb +++ b/app/workers/create_gpg_signature_worker.rb @@ -3,6 +3,8 @@ class CreateGpgSignatureWorker include ApplicationWorker + feature_category :source_code_management + # rubocop: disable CodeReuse/ActiveRecord def perform(commit_shas, project_id) # Older versions of Git::BranchPushService may push a single commit ID on diff --git a/app/workers/create_note_diff_file_worker.rb b/app/workers/create_note_diff_file_worker.rb index 0850250f7e3..ca200bd17b4 100644 --- a/app/workers/create_note_diff_file_worker.rb +++ b/app/workers/create_note_diff_file_worker.rb @@ -3,6 +3,8 @@ class CreateNoteDiffFileWorker include ApplicationWorker + feature_category :source_code_management + def perform(diff_note_id) diff_note = DiffNote.find(diff_note_id) diff --git a/app/workers/create_pipeline_worker.rb b/app/workers/create_pipeline_worker.rb index 037b4a57d4b..70412ffd095 100644 --- a/app/workers/create_pipeline_worker.rb +++ b/app/workers/create_pipeline_worker.rb @@ -5,6 +5,7 @@ class CreatePipelineWorker include PipelineQueue queue_namespace :pipeline_creation + feature_category :continuous_integration def perform(project_id, user_id, ref, source, params = {}) project = Project.find(project_id) diff --git a/app/workers/delete_container_repository_worker.rb b/app/workers/delete_container_repository_worker.rb index 42e66513ff1..e70b4fb0a58 100644 --- a/app/workers/delete_container_repository_worker.rb +++ b/app/workers/delete_container_repository_worker.rb @@ -5,6 +5,7 @@ class DeleteContainerRepositoryWorker include ExclusiveLeaseGuard queue_namespace :container_repository + feature_category :container_registry LEASE_TIMEOUT = 1.hour diff --git a/app/workers/delete_diff_files_worker.rb b/app/workers/delete_diff_files_worker.rb index f518dfe871c..e0c1724f1f7 100644 --- a/app/workers/delete_diff_files_worker.rb +++ b/app/workers/delete_diff_files_worker.rb @@ -3,6 +3,8 @@ class DeleteDiffFilesWorker include ApplicationWorker + feature_category :source_code_management + # rubocop: disable CodeReuse/ActiveRecord def perform(merge_request_diff_id) merge_request_diff = MergeRequestDiff.find(merge_request_diff_id) diff --git a/app/workers/delete_merged_branches_worker.rb b/app/workers/delete_merged_branches_worker.rb index 017d7fd1cb0..44b3db30d0d 100644 --- a/app/workers/delete_merged_branches_worker.rb +++ b/app/workers/delete_merged_branches_worker.rb @@ -3,6 +3,8 @@ class DeleteMergedBranchesWorker include ApplicationWorker + feature_category :source_code_management + def perform(project_id, user_id) begin project = Project.find(project_id) diff --git a/app/workers/delete_stored_files_worker.rb b/app/workers/delete_stored_files_worker.rb index ff7931849d8..8a693a64055 100644 --- a/app/workers/delete_stored_files_worker.rb +++ b/app/workers/delete_stored_files_worker.rb @@ -3,6 +3,8 @@ class DeleteStoredFilesWorker include ApplicationWorker + feature_category_not_owned! + def perform(class_name, keys) klass = begin class_name.constantize diff --git a/app/workers/delete_user_worker.rb b/app/workers/delete_user_worker.rb index efa8794b214..0e49e787d8a 100644 --- a/app/workers/delete_user_worker.rb +++ b/app/workers/delete_user_worker.rb @@ -3,6 +3,8 @@ class DeleteUserWorker include ApplicationWorker + feature_category :authentication_and_authorization + def perform(current_user_id, delete_user_id, options = {}) delete_user = User.find(delete_user_id) current_user = User.find(current_user_id) diff --git a/app/workers/deployments/finished_worker.rb b/app/workers/deployments/finished_worker.rb index c9d448d5d18..79a1caccc92 100644 --- a/app/workers/deployments/finished_worker.rb +++ b/app/workers/deployments/finished_worker.rb @@ -5,6 +5,7 @@ module Deployments include ApplicationWorker queue_namespace :deployment + feature_category :continuous_delivery def perform(deployment_id) Deployment.find_by_id(deployment_id).try(:execute_hooks) diff --git a/app/workers/deployments/success_worker.rb b/app/workers/deployments/success_worker.rb index 3c7e384365a..f6520307186 100644 --- a/app/workers/deployments/success_worker.rb +++ b/app/workers/deployments/success_worker.rb @@ -5,6 +5,7 @@ module Deployments include ApplicationWorker queue_namespace :deployment + feature_category :continuous_delivery def perform(deployment_id) Deployment.find_by_id(deployment_id).try do |deployment| diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb index 838c3be78f0..954d0f9336b 100644 --- a/app/workers/detect_repository_languages_worker.rb +++ b/app/workers/detect_repository_languages_worker.rb @@ -6,6 +6,7 @@ class DetectRepositoryLanguagesWorker include ExclusiveLeaseGuard sidekiq_options retry: 1 + feature_category :source_code_management LEASE_TIMEOUT = 300 diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb index e70bf17d5a9..c82728be329 100644 --- a/app/workers/email_receiver_worker.rb +++ b/app/workers/email_receiver_worker.rb @@ -3,6 +3,8 @@ class EmailReceiverWorker include ApplicationWorker + feature_category :issue_tracking + def perform(raw) return unless Gitlab::IncomingEmail.enabled? diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index ed3e354e4c2..2231c91a720 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -5,6 +5,8 @@ class EmailsOnPushWorker attr_reader :email, :skip_premailer + feature_category :source_code_management + def perform(project_id, recipients, push_data, options = {}) options.symbolize_keys! options.reverse_merge!( diff --git a/app/workers/expire_build_artifacts_worker.rb b/app/workers/expire_build_artifacts_worker.rb index 6f0e0fd33f7..9545227fa31 100644 --- a/app/workers/expire_build_artifacts_worker.rb +++ b/app/workers/expire_build_artifacts_worker.rb @@ -4,6 +4,8 @@ class ExpireBuildArtifactsWorker include ApplicationWorker include CronjobQueue + feature_category :continuous_integration + def perform if Feature.enabled?(:ci_new_expire_job_artifacts_service, default_enabled: true) perform_efficient_artifacts_removal diff --git a/app/workers/expire_build_instance_artifacts_worker.rb b/app/workers/expire_build_instance_artifacts_worker.rb index 71e61dcb878..db5240d5c8e 100644 --- a/app/workers/expire_build_instance_artifacts_worker.rb +++ b/app/workers/expire_build_instance_artifacts_worker.rb @@ -3,6 +3,8 @@ class ExpireBuildInstanceArtifactsWorker include ApplicationWorker + feature_category :continuous_integration + # rubocop: disable CodeReuse/ActiveRecord def perform(build_id) build = Ci::Build diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb index 5499e12e49b..ad119917774 100644 --- a/app/workers/git_garbage_collect_worker.rb +++ b/app/workers/git_garbage_collect_worker.rb @@ -4,6 +4,7 @@ class GitGarbageCollectWorker include ApplicationWorker sidekiq_options retry: false + feature_category :gitaly # Timeout set to 24h LEASE_TIMEOUT = 86400 diff --git a/app/workers/gitlab/github_import/advance_stage_worker.rb b/app/workers/gitlab/github_import/advance_stage_worker.rb index 0b3437a8a33..44e69e48694 100644 --- a/app/workers/gitlab/github_import/advance_stage_worker.rb +++ b/app/workers/gitlab/github_import/advance_stage_worker.rb @@ -10,6 +10,7 @@ module Gitlab include ApplicationWorker sidekiq_options dead: false + feature_category :importers INTERVAL = 30.seconds.to_i diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb index 0e4d40acc5c..9766331cf4b 100644 --- a/app/workers/gitlab_shell_worker.rb +++ b/app/workers/gitlab_shell_worker.rb @@ -4,6 +4,8 @@ class GitlabShellWorker include ApplicationWorker include Gitlab::ShellAdapter + feature_category :source_code_management + def perform(action, *arg) gitlab_shell.__send__(action, *arg) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/workers/gitlab_usage_ping_worker.rb b/app/workers/gitlab_usage_ping_worker.rb index a5e22f88a3b..ad8302a844a 100644 --- a/app/workers/gitlab_usage_ping_worker.rb +++ b/app/workers/gitlab_usage_ping_worker.rb @@ -6,6 +6,8 @@ class GitlabUsagePingWorker include ApplicationWorker include CronjobQueue + feature_category_not_owned! + # Retry for up to approximately three hours then give up. sidekiq_options retry: 10, dead: false diff --git a/app/workers/group_destroy_worker.rb b/app/workers/group_destroy_worker.rb index b4a3ddcae51..553fd359baf 100644 --- a/app/workers/group_destroy_worker.rb +++ b/app/workers/group_destroy_worker.rb @@ -4,6 +4,8 @@ class GroupDestroyWorker include ApplicationWorker include ExceptionBacktrace + feature_category :groups + def perform(group_id, user_id) begin group = Group.find(group_id) diff --git a/app/workers/hashed_storage/base_worker.rb b/app/workers/hashed_storage/base_worker.rb index 237e278c537..1ab2108f6bb 100644 --- a/app/workers/hashed_storage/base_worker.rb +++ b/app/workers/hashed_storage/base_worker.rb @@ -3,6 +3,9 @@ module HashedStorage class BaseWorker include ExclusiveLeaseGuard + include WorkerAttributes + + feature_category :source_code_management LEASE_TIMEOUT = 30.seconds.to_i LEASE_KEY_SEGMENT = 'project_migrate_hashed_storage_worker' diff --git a/app/workers/hashed_storage/migrator_worker.rb b/app/workers/hashed_storage/migrator_worker.rb index 49e347d4060..72a3faec5f4 100644 --- a/app/workers/hashed_storage/migrator_worker.rb +++ b/app/workers/hashed_storage/migrator_worker.rb @@ -5,6 +5,7 @@ module HashedStorage include ApplicationWorker queue_namespace :hashed_storage + feature_category :source_code_management # @param [Integer] start initial ID of the batch # @param [Integer] finish last ID of the batch diff --git a/app/workers/hashed_storage/rollbacker_worker.rb b/app/workers/hashed_storage/rollbacker_worker.rb index a4da8443787..8babdcfb96d 100644 --- a/app/workers/hashed_storage/rollbacker_worker.rb +++ b/app/workers/hashed_storage/rollbacker_worker.rb @@ -5,6 +5,7 @@ module HashedStorage include ApplicationWorker queue_namespace :hashed_storage + feature_category :source_code_management # @param [Integer] start initial ID of the batch # @param [Integer] finish last ID of the batch diff --git a/app/workers/import_export_project_cleanup_worker.rb b/app/workers/import_export_project_cleanup_worker.rb index da3debdeede..07c29d40b54 100644 --- a/app/workers/import_export_project_cleanup_worker.rb +++ b/app/workers/import_export_project_cleanup_worker.rb @@ -4,6 +4,8 @@ class ImportExportProjectCleanupWorker include ApplicationWorker include CronjobQueue + feature_category :importers + def perform ImportExportCleanUpService.new.execute end diff --git a/app/workers/import_issues_csv_worker.rb b/app/workers/import_issues_csv_worker.rb index b9d7099af71..d9834320318 100644 --- a/app/workers/import_issues_csv_worker.rb +++ b/app/workers/import_issues_csv_worker.rb @@ -3,6 +3,8 @@ class ImportIssuesCsvWorker include ApplicationWorker + feature_category :issue_tracking + sidekiq_retries_exhausted do |job| Upload.find(job['args'][2]).destroy end diff --git a/app/workers/invalid_gpg_signature_update_worker.rb b/app/workers/invalid_gpg_signature_update_worker.rb index fc8a731b427..573efdf9fb1 100644 --- a/app/workers/invalid_gpg_signature_update_worker.rb +++ b/app/workers/invalid_gpg_signature_update_worker.rb @@ -3,6 +3,8 @@ class InvalidGpgSignatureUpdateWorker include ApplicationWorker + feature_category :source_code_management + # rubocop: disable CodeReuse/ActiveRecord def perform(gpg_key_id) gpg_key = GpgKey.find_by(id: gpg_key_id) diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb index 29631c6b7ac..a133ed6ed1b 100644 --- a/app/workers/irker_worker.rb +++ b/app/workers/irker_worker.rb @@ -6,6 +6,8 @@ require 'socket' class IrkerWorker include ApplicationWorker + feature_category :integrations + def perform(project_id, chans, colors, push_data, settings) project = Project.find(project_id) diff --git a/app/workers/issue_due_scheduler_worker.rb b/app/workers/issue_due_scheduler_worker.rb index 476cba47ad7..d4d47659ef0 100644 --- a/app/workers/issue_due_scheduler_worker.rb +++ b/app/workers/issue_due_scheduler_worker.rb @@ -4,6 +4,8 @@ class IssueDueSchedulerWorker include ApplicationWorker include CronjobQueue + feature_category :issue_tracking + # rubocop: disable CodeReuse/ActiveRecord def perform project_ids = Issue.opened.due_tomorrow.group(:project_id).pluck(:project_id).map { |id| [id] } diff --git a/app/workers/mail_scheduler/issue_due_worker.rb b/app/workers/mail_scheduler/issue_due_worker.rb index 1e1dde1e829..6df816de71f 100644 --- a/app/workers/mail_scheduler/issue_due_worker.rb +++ b/app/workers/mail_scheduler/issue_due_worker.rb @@ -5,6 +5,8 @@ module MailScheduler include ApplicationWorker include MailSchedulerQueue + feature_category :issue_tracking + # rubocop: disable CodeReuse/ActiveRecord def perform(project_id) Issue.opened.due_tomorrow.in_projects(project_id).preload(:project).find_each do |issue| diff --git a/app/workers/mail_scheduler/notification_service_worker.rb b/app/workers/mail_scheduler/notification_service_worker.rb index 421fbf04e28..0d06dab3b2e 100644 --- a/app/workers/mail_scheduler/notification_service_worker.rb +++ b/app/workers/mail_scheduler/notification_service_worker.rb @@ -7,6 +7,8 @@ module MailScheduler include ApplicationWorker include MailSchedulerQueue + feature_category :issue_tracking + def perform(meth, *args) check_arguments!(args) diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index ee864b733cd..70b909afea8 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -3,6 +3,8 @@ class MergeWorker include ApplicationWorker + feature_category :source_code_management + def perform(merge_request_id, current_user_id, params) params = params.with_indifferent_access current_user = User.find(current_user_id) diff --git a/app/workers/migrate_external_diffs_worker.rb b/app/workers/migrate_external_diffs_worker.rb index fe757968d49..d248e2b5500 100644 --- a/app/workers/migrate_external_diffs_worker.rb +++ b/app/workers/migrate_external_diffs_worker.rb @@ -3,6 +3,8 @@ class MigrateExternalDiffsWorker include ApplicationWorker + feature_category :source_code_management + def perform(merge_request_diff_id) diff = MergeRequestDiff.find_by_id(merge_request_diff_id) return unless diff diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb index f6e98746055..113afc268f2 100644 --- a/app/workers/namespaceless_project_destroy_worker.rb +++ b/app/workers/namespaceless_project_destroy_worker.rb @@ -10,6 +10,8 @@ class NamespacelessProjectDestroyWorker include ApplicationWorker include ExceptionBacktrace + feature_category :authentication_and_authorization + def perform(project_id) begin project = Project.unscoped.find(project_id) @@ -31,6 +33,6 @@ class NamespacelessProjectDestroyWorker def unlink_fork(project) merge_requests = project.forked_from_project.merge_requests.opened.from_project(project) - merge_requests.update_all(state: 'closed') + merge_requests.update_all(state_id: MergeRequest.available_states[:closed]) end end diff --git a/app/workers/namespaces/prune_aggregation_schedules_worker.rb b/app/workers/namespaces/prune_aggregation_schedules_worker.rb index 4e40feee702..16259ffbfa6 100644 --- a/app/workers/namespaces/prune_aggregation_schedules_worker.rb +++ b/app/workers/namespaces/prune_aggregation_schedules_worker.rb @@ -5,6 +5,8 @@ module Namespaces include ApplicationWorker include CronjobQueue + feature_category :source_code_management + # Worker to prune pending rows on Namespace::AggregationSchedule # It's scheduled to run once a day at 1:05am. def perform diff --git a/app/workers/namespaces/root_statistics_worker.rb b/app/workers/namespaces/root_statistics_worker.rb index 0c1ca5eb975..fd772c8cff6 100644 --- a/app/workers/namespaces/root_statistics_worker.rb +++ b/app/workers/namespaces/root_statistics_worker.rb @@ -5,6 +5,7 @@ module Namespaces include ApplicationWorker queue_namespace :update_namespace_statistics + feature_category :source_code_management def perform(namespace_id) namespace = Namespace.find(namespace_id) diff --git a/app/workers/namespaces/schedule_aggregation_worker.rb b/app/workers/namespaces/schedule_aggregation_worker.rb index b7d580220d6..87e135fbf21 100644 --- a/app/workers/namespaces/schedule_aggregation_worker.rb +++ b/app/workers/namespaces/schedule_aggregation_worker.rb @@ -5,6 +5,7 @@ module Namespaces include ApplicationWorker queue_namespace :update_namespace_statistics + feature_category :source_code_management def perform(namespace_id) return unless aggregation_schedules_table_exists? diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb index 85b53973f56..1b0fec597e7 100644 --- a/app/workers/new_issue_worker.rb +++ b/app/workers/new_issue_worker.rb @@ -4,6 +4,8 @@ class NewIssueWorker include ApplicationWorker include NewIssuable + feature_category :issue_tracking + def perform(issue_id, user_id) return unless objects_found?(issue_id, user_id) diff --git a/app/workers/new_merge_request_worker.rb b/app/workers/new_merge_request_worker.rb index fa48c1b29a8..0a5b2f86331 100644 --- a/app/workers/new_merge_request_worker.rb +++ b/app/workers/new_merge_request_worker.rb @@ -4,6 +4,8 @@ class NewMergeRequestWorker include ApplicationWorker include NewIssuable + feature_category :source_code_management + def perform(merge_request_id, user_id) return unless objects_found?(merge_request_id, user_id) diff --git a/app/workers/new_note_worker.rb b/app/workers/new_note_worker.rb index 7648af3a8b9..d0d2a563738 100644 --- a/app/workers/new_note_worker.rb +++ b/app/workers/new_note_worker.rb @@ -3,6 +3,8 @@ class NewNoteWorker include ApplicationWorker + feature_category :issue_tracking + # Keep extra parameter to preserve backwards compatibility with # old `NewNoteWorker` jobs (can remove later) # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/workers/new_release_worker.rb b/app/workers/new_release_worker.rb index b80553a60db..28d2517238e 100644 --- a/app/workers/new_release_worker.rb +++ b/app/workers/new_release_worker.rb @@ -4,6 +4,7 @@ class NewReleaseWorker include ApplicationWorker queue_namespace :notifications + feature_category :release_orchestration def perform(release_id) release = Release.with_project_and_namespace.find_by_id(release_id) diff --git a/app/workers/object_storage/background_move_worker.rb b/app/workers/object_storage/background_move_worker.rb index 19ccae7739c..55f8e1c3ede 100644 --- a/app/workers/object_storage/background_move_worker.rb +++ b/app/workers/object_storage/background_move_worker.rb @@ -6,6 +6,7 @@ module ObjectStorage include ObjectStorageQueue sidekiq_options retry: 5 + feature_category_not_owned! def perform(uploader_class_name, subject_class_name, file_field, subject_id) uploader_class = uploader_class_name.constantize diff --git a/app/workers/object_storage/migrate_uploads_worker.rb b/app/workers/object_storage/migrate_uploads_worker.rb index c9fd19cf9d7..01e6fdb2d3e 100644 --- a/app/workers/object_storage/migrate_uploads_worker.rb +++ b/app/workers/object_storage/migrate_uploads_worker.rb @@ -5,6 +5,8 @@ module ObjectStorage include ApplicationWorker include ObjectStorageQueue + feature_category_not_owned! + SanityCheckError = Class.new(StandardError) class MigrationResult diff --git a/app/workers/pages_domain_removal_cron_worker.rb b/app/workers/pages_domain_removal_cron_worker.rb index 79f38e1b89f..25e747c78d0 100644 --- a/app/workers/pages_domain_removal_cron_worker.rb +++ b/app/workers/pages_domain_removal_cron_worker.rb @@ -4,6 +4,8 @@ class PagesDomainRemovalCronWorker include ApplicationWorker include CronjobQueue + feature_category :pages + def perform PagesDomain.for_removal.find_each do |domain| domain.destroy! diff --git a/app/workers/pages_domain_ssl_renewal_cron_worker.rb b/app/workers/pages_domain_ssl_renewal_cron_worker.rb index e5dde07a648..f7a243e9b3b 100644 --- a/app/workers/pages_domain_ssl_renewal_cron_worker.rb +++ b/app/workers/pages_domain_ssl_renewal_cron_worker.rb @@ -4,6 +4,8 @@ class PagesDomainSslRenewalCronWorker include ApplicationWorker include CronjobQueue + feature_category :pages + def perform return unless ::Gitlab::LetsEncrypt.enabled? diff --git a/app/workers/pages_domain_ssl_renewal_worker.rb b/app/workers/pages_domain_ssl_renewal_worker.rb index 87fd8059946..4db7d22ef7e 100644 --- a/app/workers/pages_domain_ssl_renewal_worker.rb +++ b/app/workers/pages_domain_ssl_renewal_worker.rb @@ -3,6 +3,8 @@ class PagesDomainSslRenewalWorker include ApplicationWorker + feature_category :pages + def perform(domain_id) domain = PagesDomain.find_by_id(domain_id) return unless domain&.enabled? diff --git a/app/workers/pages_domain_verification_cron_worker.rb b/app/workers/pages_domain_verification_cron_worker.rb index 60703c83e9e..bb3a7fede9a 100644 --- a/app/workers/pages_domain_verification_cron_worker.rb +++ b/app/workers/pages_domain_verification_cron_worker.rb @@ -4,6 +4,8 @@ class PagesDomainVerificationCronWorker include ApplicationWorker include CronjobQueue + feature_category :pages + def perform return if Gitlab::Database.read_only? diff --git a/app/workers/pages_domain_verification_worker.rb b/app/workers/pages_domain_verification_worker.rb index 7817b2ee5fc..b0888036498 100644 --- a/app/workers/pages_domain_verification_worker.rb +++ b/app/workers/pages_domain_verification_worker.rb @@ -3,6 +3,8 @@ class PagesDomainVerificationWorker include ApplicationWorker + feature_category :pages + # rubocop: disable CodeReuse/ActiveRecord def perform(domain_id) return if Gitlab::Database.read_only? diff --git a/app/workers/pages_worker.rb b/app/workers/pages_worker.rb index fa0dfa2ff4b..484d9053849 100644 --- a/app/workers/pages_worker.rb +++ b/app/workers/pages_worker.rb @@ -4,6 +4,7 @@ class PagesWorker include ApplicationWorker sidekiq_options retry: 3 + feature_category :pages def perform(action, *arg) send(action, *arg) # rubocop:disable GitlabSecurity/PublicSend diff --git a/app/workers/pipeline_process_worker.rb b/app/workers/pipeline_process_worker.rb index 96524d93f8d..96f3725dbbe 100644 --- a/app/workers/pipeline_process_worker.rb +++ b/app/workers/pipeline_process_worker.rb @@ -5,6 +5,7 @@ class PipelineProcessWorker include PipelineQueue queue_namespace :pipeline_processing + feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord def perform(pipeline_id, build_ids = nil) diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb index 9410fd1a786..f500ea08353 100644 --- a/app/workers/pipeline_schedule_worker.rb +++ b/app/workers/pipeline_schedule_worker.rb @@ -4,6 +4,8 @@ class PipelineScheduleWorker include ApplicationWorker include CronjobQueue + feature_category :continuous_integration + def perform Ci::PipelineSchedule.runnable_schedules.preloaded.find_in_batches do |schedules| schedules.each do |schedule| diff --git a/app/workers/plugin_worker.rb b/app/workers/plugin_worker.rb index c293e28be4a..e708031abdf 100644 --- a/app/workers/plugin_worker.rb +++ b/app/workers/plugin_worker.rb @@ -4,6 +4,7 @@ class PluginWorker include ApplicationWorker sidekiq_options retry: false + feature_category :integrations def perform(file_name, data) success, message = Gitlab::Plugin.execute(file_name, data) diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 4f193e95faa..a3bc7e5b9c9 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -3,6 +3,8 @@ class PostReceive include ApplicationWorker + feature_category :source_code_management + def perform(gl_repository, identifier, changes, push_options = {}) project, repo_type = Gitlab::GlRepository.parse(gl_repository) diff --git a/app/workers/process_commit_worker.rb b/app/workers/process_commit_worker.rb index f6ebe4ab006..1e4561fc6ea 100644 --- a/app/workers/process_commit_worker.rb +++ b/app/workers/process_commit_worker.rb @@ -10,6 +10,8 @@ class ProcessCommitWorker include ApplicationWorker + feature_category :source_code_management + # project_id - The ID of the project this commit belongs to. # user_id - The ID of the user that pushed the commit. # commit_hash - Hash containing commit details to use for constructing a diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index e3f1f61991c..57a01c0dd8e 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -5,6 +5,8 @@ class ProjectCacheWorker include ApplicationWorker LEASE_TIMEOUT = 15.minutes.to_i + feature_category :source_code_management + # project_id - The ID of the project for which to flush the cache. # files - An Array containing extra types of files to refresh such as # `:readme` to flush the README and `:changelog` to flush the diff --git a/app/workers/project_daily_statistics_worker.rb b/app/workers/project_daily_statistics_worker.rb index 101f5c28459..19c2fd67763 100644 --- a/app/workers/project_daily_statistics_worker.rb +++ b/app/workers/project_daily_statistics_worker.rb @@ -3,6 +3,8 @@ class ProjectDailyStatisticsWorker include ApplicationWorker + feature_category :source_code_management + def perform(project_id) project = Project.find_by_id(project_id) diff --git a/app/workers/project_destroy_worker.rb b/app/workers/project_destroy_worker.rb index 4447e867240..1d20837faa2 100644 --- a/app/workers/project_destroy_worker.rb +++ b/app/workers/project_destroy_worker.rb @@ -4,6 +4,8 @@ class ProjectDestroyWorker include ApplicationWorker include ExceptionBacktrace + feature_category :source_code_management + def perform(project_id, user_id, params) project = Project.find(project_id) user = User.find(user_id) diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb index ed9da39c7c3..bbcf3b72718 100644 --- a/app/workers/project_export_worker.rb +++ b/app/workers/project_export_worker.rb @@ -5,6 +5,7 @@ class ProjectExportWorker include ExceptionBacktrace sidekiq_options retry: 3 + feature_category :source_code_management def perform(current_user_id, project_id, after_export_strategy = {}, params = {}) current_user = User.find(current_user_id) diff --git a/app/workers/project_service_worker.rb b/app/workers/project_service_worker.rb index 25567cec08b..8041404fc71 100644 --- a/app/workers/project_service_worker.rb +++ b/app/workers/project_service_worker.rb @@ -4,6 +4,7 @@ class ProjectServiceWorker include ApplicationWorker sidekiq_options dead: false + feature_category :integrations def perform(hook_id, data) data = data.with_indifferent_access diff --git a/app/workers/propagate_service_template_worker.rb b/app/workers/propagate_service_template_worker.rb index 3ccd7615697..73a2b453207 100644 --- a/app/workers/propagate_service_template_worker.rb +++ b/app/workers/propagate_service_template_worker.rb @@ -4,6 +4,8 @@ class PropagateServiceTemplateWorker include ApplicationWorker + feature_category :source_code_management + LEASE_TIMEOUT = 4.hours.to_i # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/workers/prune_old_events_worker.rb b/app/workers/prune_old_events_worker.rb index e2d1fb3ed35..f421e8dbf59 100644 --- a/app/workers/prune_old_events_worker.rb +++ b/app/workers/prune_old_events_worker.rb @@ -4,6 +4,8 @@ class PruneOldEventsWorker include ApplicationWorker include CronjobQueue + feature_category_not_owned! + # rubocop: disable CodeReuse/ActiveRecord def perform # Contribution calendar shows maximum 12 months of events, we retain 3 years for data integrity. diff --git a/app/workers/prune_web_hook_logs_worker.rb b/app/workers/prune_web_hook_logs_worker.rb index 38054069f4e..8e48b45fc34 100644 --- a/app/workers/prune_web_hook_logs_worker.rb +++ b/app/workers/prune_web_hook_logs_worker.rb @@ -6,6 +6,8 @@ class PruneWebHookLogsWorker include ApplicationWorker include CronjobQueue + feature_category :integrations + # The maximum number of rows to remove in a single job. DELETE_LIMIT = 50_000 diff --git a/app/workers/reactive_caching_worker.rb b/app/workers/reactive_caching_worker.rb index b30864db802..af4a3def062 100644 --- a/app/workers/reactive_caching_worker.rb +++ b/app/workers/reactive_caching_worker.rb @@ -3,6 +3,8 @@ class ReactiveCachingWorker include ApplicationWorker + feature_category_not_owned! + def perform(class_name, id, *args) klass = begin class_name.constantize diff --git a/app/workers/rebase_worker.rb b/app/workers/rebase_worker.rb index 8d06adcd993..7343226fdcd 100644 --- a/app/workers/rebase_worker.rb +++ b/app/workers/rebase_worker.rb @@ -5,6 +5,8 @@ class RebaseWorker include ApplicationWorker + feature_category :source_code_management + def perform(merge_request_id, current_user_id) current_user = User.find(current_user_id) merge_request = MergeRequest.find(merge_request_id) diff --git a/app/workers/remote_mirror_notification_worker.rb b/app/workers/remote_mirror_notification_worker.rb index 368abfeda99..8bc19230caf 100644 --- a/app/workers/remote_mirror_notification_worker.rb +++ b/app/workers/remote_mirror_notification_worker.rb @@ -3,6 +3,8 @@ class RemoteMirrorNotificationWorker include ApplicationWorker + feature_category :source_code_management + def perform(remote_mirror_id) remote_mirror = RemoteMirror.find_by_id(remote_mirror_id) diff --git a/app/workers/remove_expired_group_links_worker.rb b/app/workers/remove_expired_group_links_worker.rb index 25128caf72f..147b412b772 100644 --- a/app/workers/remove_expired_group_links_worker.rb +++ b/app/workers/remove_expired_group_links_worker.rb @@ -4,6 +4,8 @@ class RemoveExpiredGroupLinksWorker include ApplicationWorker include CronjobQueue + feature_category :authentication_and_authorization + def perform ProjectGroupLink.expired.destroy_all # rubocop: disable DestroyAll end diff --git a/app/workers/remove_expired_members_worker.rb b/app/workers/remove_expired_members_worker.rb index 3497a1f9280..75f06fd9f6b 100644 --- a/app/workers/remove_expired_members_worker.rb +++ b/app/workers/remove_expired_members_worker.rb @@ -4,6 +4,8 @@ class RemoveExpiredMembersWorker include ApplicationWorker include CronjobQueue + feature_category :authentication_and_authorization + def perform Member.expired.find_each do |member| Members::DestroyService.new.execute(member, skip_authorization: true) diff --git a/app/workers/remove_unreferenced_lfs_objects_worker.rb b/app/workers/remove_unreferenced_lfs_objects_worker.rb index 95e7a9f537f..7f2c23f4685 100644 --- a/app/workers/remove_unreferenced_lfs_objects_worker.rb +++ b/app/workers/remove_unreferenced_lfs_objects_worker.rb @@ -4,6 +4,8 @@ class RemoveUnreferencedLfsObjectsWorker include ApplicationWorker include CronjobQueue + feature_category :source_code_management + def perform LfsObject.destroy_unreferenced end diff --git a/app/workers/repository_archive_cache_worker.rb b/app/workers/repository_archive_cache_worker.rb index c1dff8ced90..ebc83c1b17a 100644 --- a/app/workers/repository_archive_cache_worker.rb +++ b/app/workers/repository_archive_cache_worker.rb @@ -4,6 +4,8 @@ class RepositoryArchiveCacheWorker include ApplicationWorker include CronjobQueue + feature_category :source_code_management + def perform RepositoryArchiveCleanUpService.new.execute end diff --git a/app/workers/repository_check/dispatch_worker.rb b/app/workers/repository_check/dispatch_worker.rb index 0a7d9a14c6a..d2bd5f9b967 100644 --- a/app/workers/repository_check/dispatch_worker.rb +++ b/app/workers/repository_check/dispatch_worker.rb @@ -7,6 +7,8 @@ module RepositoryCheck include ::EachShardWorker include ExclusiveLeaseGuard + feature_category :source_code_management + LEASE_TIMEOUT = 1.hour def perform diff --git a/app/workers/repository_cleanup_worker.rb b/app/workers/repository_cleanup_worker.rb index aa26c173a72..dd2cbd42d1f 100644 --- a/app/workers/repository_cleanup_worker.rb +++ b/app/workers/repository_cleanup_worker.rb @@ -4,6 +4,7 @@ class RepositoryCleanupWorker include ApplicationWorker sidekiq_options retry: 3 + feature_category :source_code_management sidekiq_retries_exhausted do |msg, err| next if err.is_a?(ActiveRecord::RecordNotFound) diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index 35e9c58eb13..0adf745c7ac 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -6,6 +6,8 @@ class RepositoryForkWorker include ProjectStartImport include ProjectImportOptions + feature_category :source_code_management + def perform(*args) target_project_id = args.shift target_project = Project.find(target_project_id) diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index 85771fa8b31..bc2d0366fdd 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -6,6 +6,8 @@ class RepositoryImportWorker include ProjectStartImport include ProjectImportOptions + feature_category :importers + # technical debt: https://gitlab.com/gitlab-org/gitlab/issues/33991 sidekiq_options memory_killer_memory_growth_kb: ENV.fetch('MEMORY_KILLER_REPOSITORY_IMPORT_WORKER_MEMORY_GROWTH_KB', 50).to_i sidekiq_options memory_killer_max_memory_growth_kb: ENV.fetch('MEMORY_KILLER_REPOSITORY_IMPORT_WORKER_MAX_MEMORY_GROWTH_KB', 300_000).to_i diff --git a/app/workers/repository_remove_remote_worker.rb b/app/workers/repository_remove_remote_worker.rb index a85e9fa9394..3e55ebc77ed 100644 --- a/app/workers/repository_remove_remote_worker.rb +++ b/app/workers/repository_remove_remote_worker.rb @@ -4,6 +4,8 @@ class RepositoryRemoveRemoteWorker include ApplicationWorker include ExclusiveLeaseGuard + feature_category :source_code_management + LEASE_TIMEOUT = 1.hour attr_reader :project, :remote_name diff --git a/app/workers/repository_update_remote_mirror_worker.rb b/app/workers/repository_update_remote_mirror_worker.rb index d13c7641eb3..b4d96546fa4 100644 --- a/app/workers/repository_update_remote_mirror_worker.rb +++ b/app/workers/repository_update_remote_mirror_worker.rb @@ -7,6 +7,7 @@ class RepositoryUpdateRemoteMirrorWorker include Gitlab::ExclusiveLeaseHelpers sidekiq_options retry: 3, dead: false + feature_category :source_code_management LOCK_WAIT_TIME = 30.seconds MAX_TRIES = 3 diff --git a/app/workers/requests_profiles_worker.rb b/app/workers/requests_profiles_worker.rb index ae022d43e29..6ab020afb10 100644 --- a/app/workers/requests_profiles_worker.rb +++ b/app/workers/requests_profiles_worker.rb @@ -4,6 +4,8 @@ class RequestsProfilesWorker include ApplicationWorker include CronjobQueue + feature_category :source_code_management + def perform Gitlab::RequestProfiler.remove_all_profiles end diff --git a/app/workers/run_pipeline_schedule_worker.rb b/app/workers/run_pipeline_schedule_worker.rb index 659f8b80397..853f774875a 100644 --- a/app/workers/run_pipeline_schedule_worker.rb +++ b/app/workers/run_pipeline_schedule_worker.rb @@ -5,6 +5,7 @@ class RunPipelineScheduleWorker include PipelineQueue queue_namespace :pipeline_creation + feature_category :continuous_integration # rubocop: disable CodeReuse/ActiveRecord def perform(schedule_id, user_id) diff --git a/app/workers/schedule_migrate_external_diffs_worker.rb b/app/workers/schedule_migrate_external_diffs_worker.rb index 04a370f01af..8abb5922b54 100644 --- a/app/workers/schedule_migrate_external_diffs_worker.rb +++ b/app/workers/schedule_migrate_external_diffs_worker.rb @@ -5,6 +5,8 @@ class ScheduleMigrateExternalDiffsWorker include CronjobQueue include Gitlab::ExclusiveLeaseHelpers + feature_category :source_code_management + def perform in_lock(self.class.name.underscore, ttl: 2.hours, retries: 0) do MergeRequests::MigrateExternalDiffsService.enqueue! diff --git a/app/workers/stuck_ci_jobs_worker.rb b/app/workers/stuck_ci_jobs_worker.rb index 7e002d8822c..971edb1f14f 100644 --- a/app/workers/stuck_ci_jobs_worker.rb +++ b/app/workers/stuck_ci_jobs_worker.rb @@ -4,6 +4,8 @@ class StuckCiJobsWorker include ApplicationWorker include CronjobQueue + feature_category :continuous_integration + EXCLUSIVE_LEASE_KEY = 'stuck_ci_builds_worker_lease' BUILD_RUNNING_OUTDATED_TIMEOUT = 1.hour diff --git a/app/workers/stuck_import_jobs_worker.rb b/app/workers/stuck_import_jobs_worker.rb index a9ff5b22b25..4993cd1220c 100644 --- a/app/workers/stuck_import_jobs_worker.rb +++ b/app/workers/stuck_import_jobs_worker.rb @@ -4,6 +4,8 @@ class StuckImportJobsWorker include ApplicationWorker include CronjobQueue + feature_category :importers + IMPORT_JOBS_EXPIRATION = 15.hours.to_i def perform diff --git a/app/workers/stuck_merge_jobs_worker.rb b/app/workers/stuck_merge_jobs_worker.rb index e840ae47421..024863ab530 100644 --- a/app/workers/stuck_merge_jobs_worker.rb +++ b/app/workers/stuck_merge_jobs_worker.rb @@ -4,6 +4,8 @@ class StuckMergeJobsWorker include ApplicationWorker include CronjobQueue + feature_category :source_code_management + def self.logger Rails.logger # rubocop:disable Gitlab/RailsLogger end @@ -31,7 +33,7 @@ class StuckMergeJobsWorker def apply_current_state!(completed_jids, completed_ids) merge_requests = MergeRequest.where(id: completed_ids) - merge_requests.where.not(merge_commit_sha: nil).update_all(state: :merged) + merge_requests.where.not(merge_commit_sha: nil).update_all(state_id: MergeRequest.available_states[:merged]) merge_requests_to_reopen = merge_requests.where(merge_commit_sha: nil) diff --git a/app/workers/system_hook_push_worker.rb b/app/workers/system_hook_push_worker.rb index 15e369ebcfb..fc6237f359a 100644 --- a/app/workers/system_hook_push_worker.rb +++ b/app/workers/system_hook_push_worker.rb @@ -3,6 +3,8 @@ class SystemHookPushWorker include ApplicationWorker + feature_category :source_code_management + def perform(push_data, hook_id) SystemHooksService.new.execute_hooks(push_data, hook_id) end diff --git a/app/workers/trending_projects_worker.rb b/app/workers/trending_projects_worker.rb index 55b599ba38f..4c8ee1ee425 100644 --- a/app/workers/trending_projects_worker.rb +++ b/app/workers/trending_projects_worker.rb @@ -4,6 +4,8 @@ class TrendingProjectsWorker include ApplicationWorker include CronjobQueue + feature_category :source_code_management + def perform Rails.logger.info('Refreshing trending projects') # rubocop:disable Gitlab/RailsLogger diff --git a/app/workers/update_external_pull_requests_worker.rb b/app/workers/update_external_pull_requests_worker.rb index c5acfa82ada..8b0952528fa 100644 --- a/app/workers/update_external_pull_requests_worker.rb +++ b/app/workers/update_external_pull_requests_worker.rb @@ -3,6 +3,8 @@ class UpdateExternalPullRequestsWorker include ApplicationWorker + feature_category :source_code_management + def perform(project_id, user_id, ref) project = Project.find_by_id(project_id) return unless project diff --git a/app/workers/update_head_pipeline_for_merge_request_worker.rb b/app/workers/update_head_pipeline_for_merge_request_worker.rb index 4ec2b9d8fbe..77859abfea4 100644 --- a/app/workers/update_head_pipeline_for_merge_request_worker.rb +++ b/app/workers/update_head_pipeline_for_merge_request_worker.rb @@ -5,6 +5,7 @@ class UpdateHeadPipelineForMergeRequestWorker include PipelineQueue queue_namespace :pipeline_processing + feature_category :continuous_integration def perform(merge_request_id) MergeRequest.find_by_id(merge_request_id).try do |merge_request| diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb index 6c0e472e05a..8e1703cdd0b 100644 --- a/app/workers/update_merge_requests_worker.rb +++ b/app/workers/update_merge_requests_worker.rb @@ -3,6 +3,8 @@ class UpdateMergeRequestsWorker include ApplicationWorker + feature_category :source_code_management + LOG_TIME_THRESHOLD = 90 # seconds # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/workers/update_project_statistics_worker.rb b/app/workers/update_project_statistics_worker.rb index 3abb7e34a9d..e36cebf6f4f 100644 --- a/app/workers/update_project_statistics_worker.rb +++ b/app/workers/update_project_statistics_worker.rb @@ -4,6 +4,8 @@ class UpdateProjectStatisticsWorker include ApplicationWorker + feature_category :source_code_management + # project_id - The ID of the project for which to flush the cache. # statistics - An Array containing columns from ProjectStatistics to # refresh, if empty all columns will be refreshed diff --git a/app/workers/upload_checksum_worker.rb b/app/workers/upload_checksum_worker.rb index 834dcaa435d..d35367145b8 100644 --- a/app/workers/upload_checksum_worker.rb +++ b/app/workers/upload_checksum_worker.rb @@ -3,6 +3,8 @@ class UploadChecksumWorker include ApplicationWorker + feature_category :geo_replication + def perform(upload_id) upload = Upload.find(upload_id) upload.calculate_checksum! diff --git a/app/workers/web_hook_worker.rb b/app/workers/web_hook_worker.rb index 09219a24a16..fd7ca93683e 100644 --- a/app/workers/web_hook_worker.rb +++ b/app/workers/web_hook_worker.rb @@ -3,6 +3,7 @@ class WebHookWorker include ApplicationWorker + feature_category :integrations sidekiq_options retry: 4, dead: false def perform(hook_id, data, hook_name) |