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/behaviors/toggler_behavior.js16
-rw-r--r--app/models/group.rb7
-rw-r--r--app/models/packages/dependency_link.rb28
-rw-r--r--app/models/project_authorization.rb9
-rw-r--r--app/models/project_authorizations/changes.rb4
-rw-r--r--app/services/packages/npm/generate_metadata_service.rb70
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml2
-rw-r--r--app/views/projects/merge_requests/_page.html.haml1
-rw-r--r--app/workers/all_queues.yml27
-rw-r--r--app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb76
-rw-r--r--app/workers/gitlab/bitbucket_import/advance_stage_worker.rb37
-rw-r--r--app/workers/gitlab/bitbucket_import/stage/finish_import_worker.rb19
-rw-r--r--app/workers/gitlab/bitbucket_import/stage/import_repository_worker.rb29
13 files changed, 308 insertions, 17 deletions
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js
index 30424fee46a..4e643f71c4b 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.js
+++ b/app/assets/javascripts/behaviors/toggler_behavior.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { fixTitle } from '~/tooltips';
import { getLocationHash } from '../lib/utils/url_utility';
// Toggle button. Show/hide content inside parent container.
@@ -29,9 +30,22 @@ $(() => {
$container.find('.js-toggle-content').toggle(toggleState);
}
+ function updateTitle(el, container) {
+ const $container = $(container);
+ const isExpanded = $container.data('is-expanded');
+
+ el.setAttribute('title', isExpanded ? el.dataset.collapseTitle : el.dataset.expandTitle);
+
+ fixTitle(el);
+ }
+
$('body').on('click', '.js-toggle-button', function toggleButton(e) {
e.currentTarget.classList.toggle(e.currentTarget.dataset.toggleOpenClass || 'selected');
- toggleContainer($(this).closest('.js-toggle-container'));
+
+ const containerEl = this.closest('.js-toggle-container');
+
+ toggleContainer(containerEl);
+ updateTitle(this, containerEl);
const targetTag = e.currentTarget.tagName.toLowerCase();
if (targetTag === 'a' || targetTag === 'button') {
diff --git a/app/models/group.rb b/app/models/group.rb
index 6fc050c0c5f..7baf86b878b 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -35,7 +35,8 @@ class Group < Namespace
foreign_key: :member_namespace_id, inverse_of: :group, class_name: 'GroupMember'
alias_method :members, :group_members
- has_many :users, through: :group_members
+ has_many :users, -> { allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/422405") },
+ through: :group_members
has_many :owners, -> {
where(members: { access_level: Gitlab::Access::OWNER })
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/422405")
@@ -341,10 +342,6 @@ class Group < Namespace
end
end
- def users
- super.loaded? ? super : super.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/422405")
- end
-
# Overrides notification_settings has_many association
# This allows to apply notification settings from parent groups
# to child groups and projects.
diff --git a/app/models/packages/dependency_link.rb b/app/models/packages/dependency_link.rb
index 51018602bdc..400b4cce208 100644
--- a/app/models/packages/dependency_link.rb
+++ b/app/models/packages/dependency_link.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
class Packages::DependencyLink < ApplicationRecord
+ include EachBatch
+
belongs_to :package, inverse_of: :dependency_links
belongs_to :dependency, inverse_of: :dependency_links, class_name: 'Packages::Dependency'
has_one :nuget_metadatum, inverse_of: :dependency_link, class_name: 'Packages::Nuget::DependencyLinkMetadatum'
@@ -14,6 +16,32 @@ class Packages::DependencyLink < ApplicationRecord
scope :with_dependency_type, ->(dependency_type) { where(dependency_type: dependency_type) }
scope :includes_dependency, -> { includes(:dependency) }
scope :for_package, ->(package) { where(package_id: package.id) }
+ scope :for_packages, ->(packages) { where(package: packages) }
scope :preload_dependency, -> { preload(:dependency) }
scope :preload_nuget_metadatum, -> { preload(:nuget_metadatum) }
+ scope :select_dependency_id, -> { select(:dependency_id) }
+
+ def self.dependency_ids_grouped_by_type(packages)
+ inner_query = where(package_id: packages)
+ .select('
+ package_id,
+ dependency_type,
+ ARRAY_AGG(dependency_id) as dependency_ids
+ ')
+ .group(:package_id, :dependency_type)
+
+ cte = Gitlab::SQL::CTE.new(:dependency_links_cte, inner_query)
+ cte_alias = cte.table.alias(table_name)
+
+ with(cte.to_arel)
+ .select('
+ package_id,
+ JSON_OBJECT_AGG(
+ dependency_type,
+ dependency_ids
+ ) AS dependency_ids_by_type
+ ')
+ .from(cte_alias)
+ .group(:package_id)
+ end
end
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index cc3b38a7703..3161bdaacd8 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -13,6 +13,9 @@ class ProjectAuthorization < ApplicationRecord
scope :non_guests, -> { where('access_level > ?', ::Gitlab::Access::GUEST) }
+ # TODO: To be removed after https://gitlab.com/gitlab-org/gitlab/-/issues/418205
+ before_create :assign_is_unique
+
def self.select_from_union(relations)
from_union(relations)
.select(['project_id', 'MAX(access_level) AS access_level'])
@@ -27,6 +30,12 @@ class ProjectAuthorization < ApplicationRecord
def self.insert_all(attributes)
super(attributes, unique_by: connection.schema_cache.primary_keys(table_name))
end
+
+ private
+
+ def assign_is_unique
+ self.is_unique = true if Feature.enabled?(:write_project_authorizations_is_unique)
+ end
end
ProjectAuthorization.prepend_mod_with('ProjectAuthorization')
diff --git a/app/models/project_authorizations/changes.rb b/app/models/project_authorizations/changes.rb
index 1d717950c1c..d0175b4662d 100644
--- a/app/models/project_authorizations/changes.rb
+++ b/app/models/project_authorizations/changes.rb
@@ -89,7 +89,11 @@ module ProjectAuthorizations
add_delay = add_delay_between_batches?(entire_size: attributes.size, batch_size: BATCH_SIZE)
log_details(entire_size: attributes.size, batch_size: BATCH_SIZE) if add_delay
+ write_is_unique = Feature.enabled?(:write_project_authorizations_is_unique)
+
attributes.each_slice(BATCH_SIZE) do |attributes_batch|
+ attributes_batch.each { |attrs| attrs[:is_unique] = true } if write_is_unique
+
ProjectAuthorization.insert_all(attributes_batch)
perform_delay if add_delay
end
diff --git a/app/services/packages/npm/generate_metadata_service.rb b/app/services/packages/npm/generate_metadata_service.rb
index e1795079513..cae086d74c5 100644
--- a/app/services/packages/npm/generate_metadata_service.rb
+++ b/app/services/packages/npm/generate_metadata_service.rb
@@ -4,6 +4,7 @@ module Packages
module Npm
class GenerateMetadataService
include API::Helpers::RelatedResourcesHelpers
+ include Gitlab::Utils::StrongMemoize
# Allowed fields are those defined in the abbreviated form
# defined here: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
@@ -13,6 +14,8 @@ module Packages
def initialize(name, packages)
@name = name
@packages = packages
+ @dependencies = {}
+ @dependency_ids = Hash.new { |h, key| h[key] = {} }
end
def execute(only_dist_tags: false)
@@ -21,7 +24,7 @@ module Packages
private
- attr_reader :name, :packages
+ attr_reader :name, :packages, :dependencies, :dependency_ids
def metadata(only_dist_tags)
result = { dist_tags: dist_tags }
@@ -38,9 +41,17 @@ module Packages
package_versions = {}
packages.each_batch do |relation|
- batched_packages = relation.including_dependency_links
- .preload_files
- .preload_npm_metadatum
+ batched_packages = if optimization_enabled?
+ load_dependencies(relation)
+ load_dependency_ids(relation)
+
+ relation.preload_files
+ .preload_npm_metadatum
+ else
+ relation.including_dependency_links
+ .preload_files
+ .preload_npm_metadatum
+ end
batched_packages.each do |package|
package_file = package.installable_package_files.last
@@ -82,14 +93,23 @@ module Packages
end
def build_package_dependencies(package)
- dependencies = Hash.new { |h, key| h[key] = {} }
+ if optimization_enabled?
+ inverted_dependency_types = Packages::DependencyLink.dependency_types.invert.stringify_keys
+ dependency_ids[package.id].each_with_object(Hash.new { |h, key| h[key] = {} }) do |(type, ids), memo|
+ ids.each do |id|
+ memo[inverted_dependency_types[type]].merge!(dependencies[id])
+ end
+ end
+ else
+ dependencies = Hash.new { |h, key| h[key] = {} }
- package.dependency_links.each do |dependency_link|
- dependency = dependency_link.dependency
- dependencies[dependency_link.dependency_type][dependency.name] = dependency.version_pattern
- end
+ package.dependency_links.each do |dependency_link|
+ dependency = dependency_link.dependency
+ dependencies[dependency_link.dependency_type][dependency.name] = dependency.version_pattern
+ end
- dependencies
+ dependencies
+ end
end
def sorted_versions
@@ -106,6 +126,36 @@ module Packages
json = package.npm_metadatum&.package_json || {}
json.slice(*PACKAGE_JSON_ALLOWED_FIELDS)
end
+
+ def load_dependencies(packages)
+ Packages::Dependency
+ .id_in(
+ Packages::DependencyLink
+ .for_packages(packages)
+ .select_dependency_id
+ )
+ .id_not_in(dependencies.keys)
+ .each_batch do |relation|
+ relation.each do |dependency|
+ dependencies[dependency.id] = { dependency.name => dependency.version_pattern }
+ end
+ end
+ end
+
+ def load_dependency_ids(packages)
+ Packages::DependencyLink
+ .dependency_ids_grouped_by_type(packages)
+ .each_batch(column: :package_id) do |relation|
+ relation.each do |dependency_link|
+ dependency_ids[dependency_link.package_id] = dependency_link.dependency_ids_by_type
+ end
+ end
+ end
+
+ def optimization_enabled?
+ Feature.enabled?(:npm_optimize_metadata_generation)
+ end
+ strong_memoize_attr :optimization_enabled?
end
end
end
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 988153d45a4..1f56487cea4 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -6,7 +6,7 @@
= _('Gitpod')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
- .gl-text-secondary
+ .gl-text-secondary.gl-mb-5
#js-gitpod-settings-help-text{ data: {"message" => gitpod_enable_description, "message-url" => "https://gitpod.io/" } }
= link_to sprite_icon('question-o'), help_page_path('integration/gitpod.md'), target: '_blank', class: 'has-tooltip', title: _('More information')
diff --git a/app/views/projects/merge_requests/_page.html.haml b/app/views/projects/merge_requests/_page.html.haml
index dc97aa62c26..dfb18b52021 100644
--- a/app/views/projects/merge_requests/_page.html.haml
+++ b/app/views/projects/merge_requests/_page.html.haml
@@ -61,6 +61,7 @@
= render "projects/merge_requests/tabs/pane", id: "notes", class: "notes voting_notes" do
%div{ class: "#{'merge-request-overview' if moved_mr_sidebar_enabled?}" }
%section
+ = render_if_exists "projects/merge_requests/diff_summary"
.issuable-discussion.js-vue-notes-event
- if @merge_request.description.present?
.detail-page-description.gl-pb-0
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 94b9acbc48b..606a0cfeee4 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2334,6 +2334,33 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: bitbucket_import_advance_stage
+ :worker_name: Gitlab::BitbucketImport::AdvanceStageWorker
+ :feature_category: :importers
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
+- :name: bitbucket_import_stage_finish_import
+ :worker_name: Gitlab::BitbucketImport::Stage::FinishImportWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
+- :name: bitbucket_import_stage_import_repository
+ :worker_name: Gitlab::BitbucketImport::Stage::ImportRepositoryWorker
+ :feature_category: :importers
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: false
+ :tags: []
- :name: bitbucket_server_import_advance_stage
:worker_name: Gitlab::BitbucketServerImport::AdvanceStageWorker
:feature_category: :importers
diff --git a/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb
new file mode 100644
index 00000000000..2885cc29532
--- /dev/null
+++ b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BitbucketImport
+ module StageMethods
+ extend ActiveSupport::Concern
+
+ included do
+ include ApplicationWorker
+
+ worker_has_external_dependencies!
+
+ feature_category :importers
+
+ data_consistency :always
+
+ sidekiq_options dead: false, retry: 3
+
+ sidekiq_retries_exhausted do |msg, e|
+ Gitlab::Import::ImportFailureService.track(
+ project_id: msg['args'][0],
+ exception: e,
+ fail_import: true
+ )
+ end
+ end
+
+ # project_id - The ID of the GitLab project to import the data into.
+ def perform(project_id)
+ info(project_id, message: 'starting stage')
+
+ project = find_project(project_id)
+
+ return unless project
+
+ import(project)
+
+ info(project_id, message: 'stage finished')
+ rescue StandardError => e
+ Gitlab::Import::ImportFailureService.track(
+ project_id: project_id,
+ exception: e,
+ error_source: self.class.name,
+ fail_import: abort_on_failure
+ )
+
+ raise(e)
+ end
+
+ def find_project(id)
+ # If the project has been marked as failed we want to bail out
+ # automatically.
+ # rubocop: disable CodeReuse/ActiveRecord
+ Project.joins_import_state.where(import_state: { status: :started }).find_by_id(id)
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ def abort_on_failure
+ false
+ end
+
+ private
+
+ def info(project_id, extra = {})
+ Logger.info(log_attributes(project_id, extra))
+ end
+
+ def log_attributes(project_id, extra = {})
+ extra.merge(
+ project_id: project_id,
+ import_stage: self.class.name
+ )
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb b/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb
new file mode 100644
index 00000000000..7f281352a1b
--- /dev/null
+++ b/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BitbucketImport
+ # AdvanceStageWorker is a worker used by the BitBucket Importer to wait for a
+ # number of jobs to complete, without blocking a thread. Once all jobs have
+ # been completed this worker will advance the import process to the next
+ # stage.
+ class AdvanceStageWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+ include ::Gitlab::Import::AdvanceStage
+
+ data_consistency :delayed
+
+ sidekiq_options dead: false, retry: 3
+
+ feature_category :importers
+
+ loggable_arguments 1, 2
+
+ # The known importer stages and their corresponding Sidekiq workers.
+ STAGES = {
+ finish: Stage::FinishImportWorker
+ }.freeze
+
+ def find_import_state(project_id)
+ ProjectImportState.jid_by(project_id: project_id, status: :started)
+ end
+
+ private
+
+ def next_stage_worker(next_stage)
+ STAGES.fetch(next_stage.to_sym)
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/bitbucket_import/stage/finish_import_worker.rb b/app/workers/gitlab/bitbucket_import/stage/finish_import_worker.rb
new file mode 100644
index 00000000000..a1c5f5787be
--- /dev/null
+++ b/app/workers/gitlab/bitbucket_import/stage/finish_import_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BitbucketImport
+ module Stage
+ class FinishImportWorker # rubocop:disable Scalability/IdempotentWorker
+ include StageMethods
+
+ private
+
+ def import(project)
+ project.after_import
+
+ Gitlab::Import::Metrics.new(:bitbucket_importer, project).track_finished_import
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/bitbucket_import/stage/import_repository_worker.rb b/app/workers/gitlab/bitbucket_import/stage/import_repository_worker.rb
new file mode 100644
index 00000000000..e311b837311
--- /dev/null
+++ b/app/workers/gitlab/bitbucket_import/stage/import_repository_worker.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BitbucketImport
+ module Stage
+ class ImportRepositoryWorker # rubocop:disable Scalability/IdempotentWorker
+ include StageMethods
+
+ private
+
+ def import(project)
+ importer = importer_class.new(project)
+
+ importer.execute
+
+ FinishImportWorker.perform_async(project.id)
+ end
+
+ def importer_class
+ Importers::RepositoryImporter
+ end
+
+ def abort_on_failure
+ true
+ end
+ end
+ end
+ end
+end