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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue28
-rw-r--r--app/assets/javascripts/vue_shared/constants.js2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_created_updated.vue23
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue39
-rw-r--r--app/models/ci/job_artifact.rb10
-rw-r--r--app/models/ci/runner.rb19
-rw-r--r--app/models/commit_status.rb8
-rw-r--r--app/models/concerns/ci/partitionable.rb1
-rw-r--r--app/models/concerns/ci/partitionable/switch.rb44
-rw-r--r--app/models/repository.rb4
-rw-r--r--app/services/metrics/users_starred_dashboards/create_service.rb76
-rw-r--r--app/services/metrics/users_starred_dashboards/delete_service.rb35
12 files changed, 116 insertions, 173 deletions
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
index bca43d0b20a..a545ad1d09c 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
@@ -1,7 +1,7 @@
<script>
import {
- GlDropdown,
- GlDropdownItem,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
GlFormCheckbox,
GlIcon,
GlSprintf,
@@ -28,8 +28,8 @@ import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
name: 'PackageListRow',
components: {
- GlDropdown,
- GlDropdownItem,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
GlFormCheckbox,
GlIcon,
GlSprintf,
@@ -194,18 +194,22 @@ export default {
</template>
<template v-if="packageEntity.canDestroy" #right-action>
- <gl-dropdown
+ <gl-disclosure-dropdown
+ category="tertiary"
data-testid="delete-dropdown"
icon="ellipsis_v"
- :text="$options.i18n.moreActions"
- :text-sr-only="true"
- category="tertiary"
+ :toggle-text="$options.i18n.moreActions"
+ text-sr-only
no-caret
>
- <gl-dropdown-item data-testid="action-delete" variant="danger" @click="$emit('delete')">{{
- $options.i18n.deletePackage
- }}</gl-dropdown-item>
- </gl-dropdown>
+ <gl-disclosure-dropdown-item data-testid="action-delete" @action="$emit('delete')">
+ <template #list-item>
+ <span class="gl-text-red-500">
+ {{ $options.i18n.deletePackage }}
+ </span>
+ </template>
+ </gl-disclosure-dropdown-item>
+ </gl-disclosure-dropdown>
</template>
</list-item>
</template>
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 8946a02e663..d9bc2c82688 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -86,7 +86,7 @@ export const confidentialityInfoText = (workspaceType, issuableType) =>
),
{
workspaceType: workspaceType === WORKSPACE_PROJECT ? __('project') : __('group'),
- issuableType: issuableType === TYPE_ISSUE ? __('issue') : __('epic'),
+ issuableType: issuableType.toLowerCase(),
permissions:
issuableType === TYPE_ISSUE
? __('at least the Reporter role, the author, and assignees')
diff --git a/app/assets/javascripts/work_items/components/work_item_created_updated.vue b/app/assets/javascripts/work_items/components/work_item_created_updated.vue
index a6cc37290fb..f93ea4a0753 100644
--- a/app/assets/javascripts/work_items/components/work_item_created_updated.vue
+++ b/app/assets/javascripts/work_items/components/work_item_created_updated.vue
@@ -1,8 +1,10 @@
<script>
-import { GlAvatarLink, GlSprintf } from '@gitlab/ui';
+import { GlAvatarLink, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { WORKSPACE_PROJECT } from '~/issues/constants';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import WorkItemStateBadge from '~/work_items/components/work_item_state_badge.vue';
+import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
@@ -13,6 +15,8 @@ export default {
TimeAgoTooltip,
WorkItemStateBadge,
WorkItemTypeIcon,
+ ConfidentialityBadge,
+ GlLoadingIcon,
},
inject: ['fullPath'],
props: {
@@ -21,6 +25,11 @@ export default {
required: false,
default: null,
},
+ updateInProgress: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
createdAt() {
@@ -44,6 +53,9 @@ export default {
workItemIconName() {
return this.workItem?.workItemType?.iconName;
},
+ isWorkItemConfidential() {
+ return this.workItem?.confidential;
+ },
},
apollo: {
workItem: {
@@ -62,12 +74,21 @@ export default {
},
},
},
+ WORKSPACE_PROJECT,
};
</script>
<template>
<div class="gl-mb-3 gl-text-gray-700">
<work-item-state-badge v-if="workItemState" :work-item-state="workItemState" />
+ <gl-loading-icon v-if="updateInProgress" :inline="true" class="gl-mr-3" />
+ <confidentiality-badge
+ v-if="isWorkItemConfidential"
+ class="gl-vertical-align-middle gl-display-inline-flex!"
+ data-testid="confidential"
+ :workspace-type="$options.WORKSPACE_PROJECT"
+ :issuable-type="workItemType"
+ />
<work-item-type-icon
class="gl-vertical-align-middle gl-mr-0!"
:work-item-icon-name="workItemIconName"
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 24fcc85dabf..d826ef9cbe7 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -5,7 +5,6 @@ import {
GlSkeletonLoader,
GlLoadingIcon,
GlIcon,
- GlBadge,
GlButton,
GlTooltipDirective,
GlEmptyState,
@@ -19,8 +18,9 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isLoggedIn } from '~/lib/utils/common_utils';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';
+import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
+import { WORKSPACE_PROJECT } from '~/issues/constants';
import {
- sprintfWorkItem,
i18n,
WIDGET_TYPE_ASSIGNEES,
WIDGET_TYPE_NOTIFICATIONS,
@@ -60,7 +60,6 @@ export default {
components: {
WorkItemStateToggleButton,
GlAlert,
- GlBadge,
GlButton,
GlLoadingIcon,
GlSkeletonLoader,
@@ -79,6 +78,7 @@ export default {
WorkItemDetailModal,
AbuseCategorySelector,
GlIntersectionObserver,
+ ConfidentialityBadge,
},
mixins: [glFeatureFlagMixin()],
inject: ['fullPath', 'reportAbusePath'],
@@ -186,9 +186,6 @@ export default {
canAssignUnassignUser() {
return this.workItemAssignees && this.canSetWorkItemMetadata;
},
- confidentialTooltip() {
- return sprintfWorkItem(this.$options.i18n.confidentialTooltip, this.workItemType);
- },
fullPath() {
return this.workItem?.project.fullPath;
},
@@ -377,8 +374,8 @@ export default {
}
},
},
-
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
+ WORKSPACE_PROJECT,
};
</script>
@@ -439,16 +436,6 @@ export default {
/>
{{ workItemBreadcrumbReference }}
</div>
- <gl-loading-icon v-if="updateInProgress" :inline="true" class="gl-mr-3" />
- <gl-badge
- v-if="workItem.confidential"
- v-gl-tooltip.bottom
- :title="confidentialTooltip"
- variant="warning"
- icon="eye-slash"
- class="gl-mr-3 gl-cursor-help"
- >{{ __('Confidential') }}</gl-badge
- >
<work-item-state-toggle-button
v-if="canUpdate"
:work-item-id="workItem.id"
@@ -503,7 +490,10 @@ export default {
:can-update="canUpdate"
@error="updateError = $event"
/>
- <work-item-created-updated :work-item-iid="workItemIid" />
+ <work-item-created-updated
+ :work-item-iid="workItemIid"
+ :update-in-progress="updateInProgress"
+ />
</div>
<gl-intersection-observer
v-if="showIntersectionObserver"
@@ -523,15 +513,12 @@ export default {
{{ workItem.title }}
</span>
<gl-loading-icon v-if="updateInProgress" class="gl-mr-3" />
- <gl-badge
+ <confidentiality-badge
v-if="workItem.confidential"
- v-gl-tooltip.bottom
- :title="confidentialTooltip"
- variant="warning"
- icon="eye-slash"
- class="gl-mr-3 gl-cursor-help"
- >{{ __('Confidential') }}</gl-badge
- >
+ data-testid="confidential"
+ :workspace-type="$options.WORKSPACE_PROJECT"
+ :issuable-type="workItemType"
+ />
<work-item-todos
v-if="showWorkItemCurrentUserTodos"
:work-item-id="workItem.id"
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 483386f1f1b..11d70e088e9 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -341,16 +341,10 @@ module Ci
end
def to_deleted_object_attrs(pick_up_at = nil)
- final_path_store_dir, final_path_filename = nil
- if file_final_path.present?
- final_path_store_dir = File.dirname(file_final_path)
- final_path_filename = File.basename(file_final_path)
- end
-
{
file_store: file_store,
- store_dir: final_path_store_dir || file.store_dir.to_s,
- file: final_path_filename || file_identifier,
+ store_dir: file.store_dir.to_s,
+ file: file_identifier,
pick_up_at: pick_up_at || expire_at || Time.current
}
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 4eb5c3c9ed2..0413bb480d4 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -87,19 +87,23 @@ module Ci
scope :active, -> (value = true) { where(active: value) }
scope :paused, -> { active(false) }
- scope :online, -> { where('contacted_at > ?', online_contact_time_deadline) }
+ scope :online, -> { where(arel_table[:contacted_at].gt(online_contact_time_deadline)) }
scope :recent, -> do
- where('ci_runners.created_at >= :datetime OR ci_runners.contacted_at >= :datetime', datetime: stale_deadline)
+ timestamp = stale_deadline
+
+ where(arel_table[:created_at].gteq(timestamp).or(arel_table[:contacted_at].gteq(timestamp)))
end
scope :stale, -> do
- where('ci_runners.created_at <= :datetime AND ' \
- '(ci_runners.contacted_at IS NULL OR ci_runners.contacted_at <= :datetime)', datetime: stale_deadline)
+ timestamp = stale_deadline
+
+ where(arel_table[:created_at].lteq(timestamp))
+ .where(arel_table[:contacted_at].eq(nil).or(arel_table[:contacted_at].lteq(timestamp)))
end
scope :offline, -> { where(arel_table[:contacted_at].lteq(online_contact_time_deadline)) }
scope :never_contacted, -> { where(contacted_at: nil) }
scope :ordered, -> { order(id: :desc) }
- scope :with_recent_runner_queue, -> { where('contacted_at > ?', recent_queue_deadline) }
+ scope :with_recent_runner_queue, -> { where(arel_table[:contacted_at].gt(recent_queue_deadline)) }
scope :with_running_builds, -> do
where('EXISTS(?)',
::Ci::Build.running.select(1)
@@ -513,7 +517,10 @@ module Ci
private
scope :with_upgrade_status, ->(upgrade_status) do
- joins(:runner_version).where(runner_version: { status: upgrade_status })
+ joins(:runner_managers)
+ .joins("INNER JOIN #{RunnerVersion.quoted_table_name} runner_version " \
+ "ON runner_version.version = #{RunnerManager.quoted_table_name}.version")
+ .where(runner_version: { status: upgrade_status })
end
EXECUTOR_NAME_TO_TYPES = {
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 3f631f583b6..c2425e9460a 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -9,10 +9,16 @@ class CommitStatus < Ci::ApplicationRecord
include BulkInsertableAssociations
include TaggableQueries
+ ROUTING_FEATURE_FLAG = :ci_partitioning_use_ci_builds_routing_table
+
self.table_name = 'ci_builds'
self.sequence_name = 'ci_builds_id_seq'
self.primary_key = :id
- partitionable scope: :pipeline
+
+ partitionable scope: :pipeline, through: {
+ table: :p_ci_builds,
+ flag: ROUTING_FEATURE_FLAG
+ }
belongs_to :user
belongs_to :project
diff --git a/app/models/concerns/ci/partitionable.rb b/app/models/concerns/ci/partitionable.rb
index a3bcc7bcbbc..ec6c85d888d 100644
--- a/app/models/concerns/ci/partitionable.rb
+++ b/app/models/concerns/ci/partitionable.rb
@@ -80,6 +80,7 @@ module Ci
def handle_partitionable_through(options)
return unless options
+ return if Gitlab::Utils.to_boolean(ENV['DISABLE_PARTITIONABLE_SWITCH'], default: false)
define_singleton_method(:routing_table_name) { options[:table] }
define_singleton_method(:routing_table_name_flag) { options[:flag] }
diff --git a/app/models/concerns/ci/partitionable/switch.rb b/app/models/concerns/ci/partitionable/switch.rb
index c1bbd107e9f..6195f92114f 100644
--- a/app/models/concerns/ci/partitionable/switch.rb
+++ b/app/models/concerns/ci/partitionable/switch.rb
@@ -2,6 +2,8 @@
module Ci
module Partitionable
+ MUTEX = Mutex.new
+
module Switch
extend ActiveSupport::Concern
@@ -14,18 +16,39 @@ module Ci
predicate_builder cached_find_by_statement].freeze
included do |base|
- partitioned = Class.new(base) do
- self.table_name = base.routing_table_name
+ install_partitioned_class(base)
+ end
+
+ class_methods do
+ # `Class.new(partitionable_model)` triggers `partitionable_model.inherited`
+ # and we need the mutex to break the recursion without adding extra accessors
+ # on the model. This will be used during code loading, not runtime.
+ #
+ def install_partitioned_class(partitionable_model)
+ Partitionable::MUTEX.synchronize do
+ partitioned = Class.new(partitionable_model) do
+ self.table_name = partitionable_model.routing_table_name
+
+ def self.routing_class?
+ true
+ end
+
+ def self.sti_name
+ superclass.sti_name
+ end
+ end
- def self.routing_class?
- true
+ partitionable_model.const_set(:Partitioned, partitioned)
end
end
- base.const_set(:Partitioned, partitioned)
- end
+ def inherited(child_class)
+ super
+ return if Partitionable::MUTEX.owned?
+
+ install_partitioned_class(child_class)
+ end
- class_methods do
def routing_class?
false
end
@@ -51,6 +74,13 @@ module Ci
end
end
end
+
+ def type_condition(table = arel_table)
+ sti_column = table[inheritance_column]
+ sti_names = ([self] + descendants).map(&:sti_name).uniq
+
+ predicate_builder.build(sti_column, sti_names)
+ end
end
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index cd269f928b5..6113f54367d 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1248,6 +1248,10 @@ class Repository
prohibited_branches.each { |name| raw_repository.delete_branch(name) }
end
+ def get_patch_id(old_revision, new_revision)
+ raw_repository.get_patch_id(old_revision, new_revision)
+ end
+
private
def ancestor_cache_key(ancestor_id, descendant_id)
diff --git a/app/services/metrics/users_starred_dashboards/create_service.rb b/app/services/metrics/users_starred_dashboards/create_service.rb
deleted file mode 100644
index 0d028f120d3..00000000000
--- a/app/services/metrics/users_starred_dashboards/create_service.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-# Create Metrics::UsersStarredDashboard entry for given user based on matched dashboard_path, project
-module Metrics
- module UsersStarredDashboards
- class CreateService < ::BaseService
- include Stepable
-
- steps :authorize_create_action,
- :parse_dashboard_path,
- :create
-
- def initialize(user, project, dashboard_path)
- @user = user
- @project = project
- @dashboard_path = dashboard_path
- end
-
- def execute
- keys = %i[status message starred_dashboard]
- status, message, dashboards = execute_steps.values_at(*keys)
-
- if status != :success
- ServiceResponse.error(message: message)
- else
- ServiceResponse.success(payload: dashboards)
- end
- end
-
- private
-
- attr_reader :user, :project, :dashboard_path
-
- def authorize_create_action(_options)
- if Ability.allowed?(user, :create_metrics_user_starred_dashboard, project)
- success(user: user, project: project)
- else
- error(s_('MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard'))
- end
- end
-
- def parse_dashboard_path(options)
- if dashboard_path_exists?
- options[:dashboard_path] = dashboard_path
- success(options)
- else
- error(s_('MetricsUsersStarredDashboards|Dashboard with requested path can not be found'))
- end
- end
-
- def create(options)
- starred_dashboard = build_starred_dashboard_from(options)
-
- if starred_dashboard.save
- success(starred_dashboard: starred_dashboard)
- else
- error(starred_dashboard.errors.messages)
- end
- end
-
- def build_starred_dashboard_from(options)
- Metrics::UsersStarredDashboard.new(
- user: options.fetch(:user),
- project: options.fetch(:project),
- dashboard_path: options.fetch(:dashboard_path)
- )
- end
-
- def dashboard_path_exists?
- Gitlab::Metrics::Dashboard::Finder
- .find_all_paths(project)
- .any? { |dashboard| dashboard[:path] == dashboard_path }
- end
- end
- end
-end
diff --git a/app/services/metrics/users_starred_dashboards/delete_service.rb b/app/services/metrics/users_starred_dashboards/delete_service.rb
deleted file mode 100644
index 229c0e8cfc0..00000000000
--- a/app/services/metrics/users_starred_dashboards/delete_service.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-# Delete all matching Metrics::UsersStarredDashboard entries for given user based on matched dashboard_path, project
-module Metrics
- module UsersStarredDashboards
- class DeleteService < ::BaseService
- def initialize(user, project, dashboard_path = nil)
- @user = user
- @project = project
- @dashboard_path = dashboard_path
- end
-
- def execute
- ServiceResponse.success(payload: { deleted_rows: starred_dashboards.delete_all })
- end
-
- private
-
- attr_reader :user, :project, :dashboard_path
-
- def starred_dashboards
- # since deleted records are scoped to their owner there is no need to
- # check if that user can delete them, also if user lost access to
- # project it shouldn't block that user from removing them
- dashboards = user.metrics_users_starred_dashboards
-
- if dashboard_path.present?
- dashboards.for_project_dashboard(project, dashboard_path)
- else
- dashboards.for_project(project)
- end
- end
- end
- end
-end