diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-20 21:14:25 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-20 21:14:25 +0000 |
commit | 40a329556f63d919a68dd80bb37b087d1f0e6336 (patch) | |
tree | 86c2712bf48f66d0e7dbe7e115e5f01c78193ad0 /app | |
parent | 96b01499986c01d0c95176860a7606b7616a3836 (diff) | |
download | gitlab-ce-40a329556f63d919a68dd80bb37b087d1f0e6336.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue | 4 | ||||
-rw-r--r-- | app/assets/javascripts/admin/abuse_reports/utils.js | 5 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/app.vue | 14 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/description.vue | 28 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/edited.vue | 78 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_actions.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/product_analytics_tracking.rb | 40 | ||||
-rw-r--r-- | app/controllers/projects/pipelines_controller.rb | 1 | ||||
-rw-r--r-- | app/finders/abuse_reports_finder.rb | 7 | ||||
-rw-r--r-- | app/helpers/ci/pipelines_helper.rb | 2 | ||||
-rw-r--r-- | app/helpers/ide_helper.rb | 1 | ||||
-rw-r--r-- | app/helpers/issuables_helper.rb | 5 | ||||
-rw-r--r-- | app/services/notes/create_service.rb | 24 | ||||
-rw-r--r-- | app/workers/namespaces/root_statistics_worker.rb | 16 | ||||
-rw-r--r-- | app/workers/namespaces/schedule_aggregation_worker.rb | 16 |
15 files changed, 114 insertions, 129 deletions
diff --git a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue index b60fe3ae9b8..e1989cadd86 100644 --- a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue +++ b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue @@ -8,7 +8,7 @@ import { SORT_OPTIONS, isValidSortKey, } from '~/admin/abuse_reports/constants'; -import { buildFilteredSearchCategoryToken } from '~/admin/abuse_reports/utils'; +import { buildFilteredSearchCategoryToken, isValidStatus } from '~/admin/abuse_reports/utils'; export default { name: 'AbuseReportsFilteredSearchBar', @@ -32,7 +32,7 @@ export default { // Backend shows open reports by default if status param is not specified. // To match that behavior, update the current URL to include status=open // query when no status query is specified on load. - if (!query.status) { + if (!isValidStatus(query.status)) { query.status = 'open'; updateHistory({ url: setUrlParams(query), replace: true }); } diff --git a/app/assets/javascripts/admin/abuse_reports/utils.js b/app/assets/javascripts/admin/abuse_reports/utils.js index 84221901089..d30e8fb0ae5 100644 --- a/app/assets/javascripts/admin/abuse_reports/utils.js +++ b/app/assets/javascripts/admin/abuse_reports/utils.js @@ -1,6 +1,9 @@ -import { FILTERED_SEARCH_TOKEN_CATEGORY } from './constants'; +import { FILTERED_SEARCH_TOKEN_CATEGORY, FILTERED_SEARCH_TOKEN_STATUS } from './constants'; export const buildFilteredSearchCategoryToken = (categories) => { const options = categories.map((c) => ({ value: c, title: c })); return { ...FILTERED_SEARCH_TOKEN_CATEGORY, options }; }; + +export const isValidStatus = (status) => + FILTERED_SEARCH_TOKEN_STATUS.options.map((o) => o.value).includes(status); diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue index 15f97222971..6622fb7aa7b 100644 --- a/app/assets/javascripts/issues/show/components/app.vue +++ b/app/assets/javascripts/issues/show/components/app.vue @@ -95,10 +95,10 @@ export default { required: false, default: '', }, - initialTaskStatus: { - type: String, + initialTaskCompletionStatus: { + type: Object, required: false, - default: '', + default: () => ({}), }, updatedAt: { type: String, @@ -197,7 +197,7 @@ export default { updatedAt: this.updatedAt, updatedByName: this.updatedByName, updatedByPath: this.updatedByPath, - taskStatus: this.initialTaskStatus, + taskCompletionStatus: this.initialTaskCompletionStatus, lock_version: this.lockVersion, }); @@ -222,9 +222,6 @@ export default { formState() { return this.store.formState; }, - hasUpdated() { - return Boolean(this.state.updatedAt); - }, issueChanged() { const { store: { @@ -557,7 +554,6 @@ export default { :description-html="state.descriptionHtml" :description-text="state.descriptionText" :updated-at="state.updatedAt" - :task-status="state.taskStatus" :issuable-type="issuableType" :update-url="updateEndpoint" :lock-version="state.lock_version" @@ -570,7 +566,7 @@ export default { /> <edited-component - v-if="hasUpdated" + :task-completion-status="state.taskCompletionStatus" :updated-at="state.updatedAt" :updated-by-name="state.updatedByName" :updated-by-path="state.updatedByPath" diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index bdee6c5fe9a..6412a13e3e6 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -1,6 +1,5 @@ <script> import { GlToast } from '@gitlab/ui'; -import $ from 'jquery'; import Sortable from 'sortablejs'; import Vue from 'vue'; import getIssueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql'; @@ -59,11 +58,6 @@ export default { required: false, default: '', }, - taskStatus: { - type: String, - required: false, - default: '', - }, issuableType: { type: String, required: false, @@ -148,16 +142,12 @@ export default { this.renderGFM(); }); }, - taskStatus() { - this.updateTaskStatusText(); - }, }, mounted() { eventHub.$on('convert-task-list-item', this.convertTaskListItem); eventHub.$on('delete-task-list-item', this.deleteTaskListItem); this.renderGFM(); - this.updateTaskStatusText(); }, beforeDestroy() { eventHub.$off('convert-task-list-item', this.convertTaskListItem); @@ -282,24 +272,6 @@ export default { this.$emit('taskListUpdateFailed'); }, - updateTaskStatusText() { - const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/); - const $issuableHeader = $('.issuable-meta'); - const $tasks = $('#task_status', $issuableHeader); - const $tasksShort = $('#task_status_short', $issuableHeader); - - if (taskRegexMatches) { - $tasks.text(this.taskStatus); - $tasksShort.text( - `${taskRegexMatches[1]}/${taskRegexMatches[2]} checklist item${ - taskRegexMatches[2] > 1 ? 's' : '' - }`, - ); - } else { - $tasks.text(''); - $tasksShort.text(''); - } - }, createTaskListItemActions(provide) { const app = new Vue({ el: document.createElement('div'), diff --git a/app/assets/javascripts/issues/show/components/edited.vue b/app/assets/javascripts/issues/show/components/edited.vue index 5138a4530e9..6a0edb59b65 100644 --- a/app/assets/javascripts/issues/show/components/edited.vue +++ b/app/assets/javascripts/issues/show/components/edited.vue @@ -1,13 +1,20 @@ <script> -import { GlSprintf } from '@gitlab/ui'; +import { GlLink, GlSprintf } from '@gitlab/ui'; +import { n__, sprintf } from '~/locale'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; export default { components: { TimeAgoTooltip, + GlLink, GlSprintf, }, props: { + taskCompletionStatus: { + type: Object, + required: false, + default: () => ({}), + }, updatedAt: { type: String, required: false, @@ -25,36 +32,61 @@ export default { }, }, computed: { + completedCount() { + return this.taskCompletionStatus.completed_count; + }, + count() { + return this.taskCompletionStatus.count; + }, hasUpdatedBy() { return this.updatedByName && this.updatedByPath; }, + showCheck() { + return this.completedCount === this.count; + }, + taskStatus() { + const { completedCount, count } = this; + if (!count) { + return undefined; + } + + return sprintf( + n__( + '%{completedCount} of %{count} checklist item completed', + '%{completedCount} of %{count} checklist items completed', + count, + ), + { completedCount, count }, + ); + }, }, }; </script> <template> <small class="edited-text js-issue-widgets"> - <gl-sprintf v-if="!hasUpdatedBy" :message="__('Edited %{timeago}')"> - <template #timeago> - <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" /> - </template> - </gl-sprintf> - <gl-sprintf v-else-if="!updatedAt" :message="__('Edited by %{author}')"> - <template #author> - <a :href="updatedByPath" class="author-link gl-hover-text-decoration-underline"> - <span>{{ updatedByName }}</span> - </a> - </template> - </gl-sprintf> - <gl-sprintf v-else :message="__('Edited %{timeago} by %{author}')"> - <template #timeago> - <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" /> - </template> - <template #author> - <a :href="updatedByPath" class="author-link gl-hover-text-decoration-underline"> - <span>{{ updatedByName }}</span> - </a> - </template> - </gl-sprintf> + <template v-if="taskStatus"> + <template v-if="showCheck">✓</template> + {{ taskStatus }} + <template v-if="updatedAt">·</template> + </template> + + <template v-if="updatedAt"> + <gl-sprintf v-if="!hasUpdatedBy" :message="__('Edited %{timeago}')"> + <template #timeago> + <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" /> + </template> + </gl-sprintf> + <gl-sprintf v-else :message="__('Edited %{timeago} by %{author}')"> + <template #timeago> + <time-ago-tooltip :time="updatedAt" tooltip-placement="bottom" /> + </template> + <template #author> + <gl-link :href="updatedByPath" class="gl-font-sm gl-hover-text-gray-900 gl-text-gray-700"> + {{ updatedByName }} + </gl-link> + </template> + </gl-sprintf> + </template> </small> </template> diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index d364daf93c3..b8d47586a15 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -76,7 +76,7 @@ module IssuableActions title_text: issuable.title, description: view_context.markdown_field(issuable, :description), description_text: issuable.description, - task_status: issuable.task_status, + task_completion_status: issuable.task_completion_status, lock_version: issuable.lock_version } diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb index 5ed2b2a82eb..fc33770b4d8 100644 --- a/app/controllers/concerns/product_analytics_tracking.rb +++ b/app/controllers/concerns/product_analytics_tracking.rb @@ -5,30 +5,6 @@ module ProductAnalyticsTracking include RedisTracking extend ActiveSupport::Concern - MIGRATED_EVENTS = %w[ - g_analytics_valuestream - i_search_paid - i_search_total - i_search_advanced - i_ecosystem_jira_service_list_issues - users_viewing_analytics_group_devops_adoption - i_analytics_dev_ops_adoption - i_analytics_dev_ops_score - p_analytics_merge_request - i_analytics_instance_statistics - g_analytics_contribution - p_analytics_pipelines - p_analytics_code_reviews - p_analytics_valuestream - p_analytics_insights - p_analytics_issues - p_analytics_repo - g_analytics_insights - g_analytics_issues - g_analytics_productivity - i_analytics_cohorts - ].freeze - class_methods do def track_event(*controller_actions, name:, action: nil, label: nil, conditions: nil, destinations: [:redis_hll], &block) custom_conditions = [:trackable_html_request?, *conditions] @@ -44,7 +20,7 @@ module ProductAnalyticsTracking def route_events_to(destinations, name, action, label, &block) track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll) - return unless destinations.include?(:snowplow) && event_enabled?(name) + return unless destinations.include?(:snowplow) raise "action is required when destination is snowplow" unless action raise "label is required when destination is snowplow" unless label @@ -63,18 +39,4 @@ module ProductAnalyticsTracking **optional_arguments ) end - - def event_enabled?(event) - return true if MIGRATED_EVENTS.include?(event) - - events_to_ff = { - g_edit_by_sfe: :_phase4, - g_compliance_dashboard: :_phase4, - g_compliance_audit_events: :_phase4, - i_compliance_audit_events: :_phase4, - i_compliance_credential_inventory: :_phase4 - } - - Feature.enabled?("route_hll_to_snowplow#{events_to_ff[event.to_sym]}", tracking_namespace_source) - end end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 6fdd4906613..5b1a7f0bab7 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -339,6 +339,7 @@ class Projects::PipelinesController < Projects::ApplicationController return if helpers.has_gitlab_ci?(project) experiment(:runners_availability_section, namespace: project.root_ancestor) do |e| + e.control {} e.candidate {} end end diff --git a/app/finders/abuse_reports_finder.rb b/app/finders/abuse_reports_finder.rb index c3159198261..6a6d0413194 100644 --- a/app/finders/abuse_reports_finder.rb +++ b/app/finders/abuse_reports_finder.rb @@ -3,6 +3,7 @@ class AbuseReportsFinder attr_reader :params, :reports + DEFAULT_STATUS_FILTER = 'open' DEFAULT_SORT = 'created_at_desc' ALLOWED_SORT = [DEFAULT_SORT, *%w[created_at_asc updated_at_desc updated_at_asc]].freeze @@ -30,9 +31,13 @@ class AbuseReportsFinder end def filter_by_status + return unless Feature.enabled?(:abuse_reports_list) return unless params[:status].present? - case params[:status] + status = params[:status] + status = DEFAULT_STATUS_FILTER unless status.in?(AbuseReport.statuses.keys) + + case status when 'open' @reports = @reports.open when 'closed' diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb index 823332c3d1d..90806df1d64 100644 --- a/app/helpers/ci/pipelines_helper.rb +++ b/app/helpers/ci/pipelines_helper.rb @@ -105,10 +105,12 @@ module Ci } experiment(:runners_availability_section, namespace: project.root_ancestor) do |e| + e.control {} # rubocop:disable Lint/EmptyBlock e.candidate { data[:any_runners_available] = project.active_runners.exists?.to_s } end experiment(:ios_specific_templates, actor: current_user, project: project, sticky_to: project) do |e| + e.control {} # rubocop:disable Lint/EmptyBlock e.candidate do data[:registration_token] = project.runners_token if can?(current_user, :register_project_runners, project) data[:ios_runners_available] = (project.shared_runners_available? && Gitlab.com?).to_s diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb index 063eef41f77..2f25afb8057 100644 --- a/app/helpers/ide_helper.rb +++ b/app/helpers/ide_helper.rb @@ -72,6 +72,7 @@ module IdeHelper def enable_environments_guidance?(project) experiment(:in_product_guidance_environments_webide, project: project) do |e| + e.control { 'false' } e.candidate { !has_dismissed_ide_environments_callout? } e.run diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 9c68f54f42e..a2e8d268455 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -173,9 +173,6 @@ module IssuablesHelper output << content_tag(:span, (sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) - output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-md-inline-block gl-ml-3") - output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none") - output.join.html_safe end @@ -252,7 +249,7 @@ module IssuablesHelper initialTitleText: issuable.title, initialDescriptionHtml: markdown_field(issuable, :description), initialDescriptionText: issuable.description, - initialTaskStatus: issuable.task_status + initialTaskCompletionStatus: issuable.task_completion_status } data.merge!(issue_only_initial_data(issuable)) data.merge!(path_data(parent)) diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 8898f7feb17..39d0d0a7923 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -164,19 +164,17 @@ module Notes track_note_creation_in_ipynb(note) track_note_creation_visual_review(note) - if Feature.enabled?(:route_hll_to_snowplow_phase4, project&.namespace) && note.for_commit? - metric_key_path = 'counts.commit_comment' - - Gitlab::Tracking.event( - 'Notes::CreateService', - 'create_commit_comment', - project: project, - namespace: project&.namespace, - user: user, - label: metric_key_path, - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: metric_key_path).to_context] - ) - end + metric_key_path = 'counts.commit_comment' + + Gitlab::Tracking.event( + 'Notes::CreateService', + 'create_commit_comment', + project: project, + namespace: project&.namespace, + user: user, + label: metric_key_path, + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis, key_path: metric_key_path).to_context] + ) end def tracking_data_for(note) diff --git a/app/workers/namespaces/root_statistics_worker.rb b/app/workers/namespaces/root_statistics_worker.rb index 02b3468c052..c8527182d35 100644 --- a/app/workers/namespaces/root_statistics_worker.rb +++ b/app/workers/namespaces/root_statistics_worker.rb @@ -16,15 +16,23 @@ module Namespaces def perform(namespace_id) namespace = Namespace.find(namespace_id) + if Feature.enabled?(:remove_aggregation_schedule_lease, namespace) + Namespaces::StatisticsRefresherService.new.execute(namespace) + else + refresh_through_namespace_aggregation_schedule(namespace) + end + + notify_storage_usage(namespace) + rescue ::Namespaces::StatisticsRefresherService::RefresherError, ActiveRecord::RecordNotFound => ex + Gitlab::ErrorTracking.track_exception(ex, namespace_id: namespace_id, namespace: namespace&.full_path) + end + + def refresh_through_namespace_aggregation_schedule(namespace) return unless namespace.aggregation_scheduled? Namespaces::StatisticsRefresherService.new.execute(namespace) namespace.aggregation_schedule.destroy - - notify_storage_usage(namespace) - rescue ::Namespaces::StatisticsRefresherService::RefresherError, ActiveRecord::RecordNotFound => ex - Gitlab::ErrorTracking.track_exception(ex, namespace_id: namespace_id, namespace: namespace&.full_path) end private diff --git a/app/workers/namespaces/schedule_aggregation_worker.rb b/app/workers/namespaces/schedule_aggregation_worker.rb index 7cd7f5223d6..bf48eb8180e 100644 --- a/app/workers/namespaces/schedule_aggregation_worker.rb +++ b/app/workers/namespaces/schedule_aggregation_worker.rb @@ -13,16 +13,24 @@ module Namespaces idempotent! def perform(namespace_id) - return unless aggregation_schedules_table_exists? - namespace = Namespace.find(namespace_id) root_ancestor = namespace.root_ancestor + if Feature.enabled?(:remove_aggregation_schedule_lease, root_ancestor) + Namespaces::RootStatisticsWorker.perform_async(root_ancestor.id) + else + schedule_through_aggregation_schedules_table(root_ancestor) + end + rescue ActiveRecord::RecordNotFound => ex + Gitlab::ErrorTracking.track_exception(ex, namespace_id: namespace_id) + end + + def schedule_through_aggregation_schedules_table(root_ancestor) + return unless aggregation_schedules_table_exists? + return if root_ancestor.aggregation_scheduled? Namespace::AggregationSchedule.safe_find_or_create_by!(namespace_id: root_ancestor.id) - rescue ActiveRecord::RecordNotFound => ex - Gitlab::ErrorTracking.track_exception(ex, namespace_id: namespace_id) end private |