diff options
Diffstat (limited to 'app/services/projects')
14 files changed, 101 insertions, 93 deletions
diff --git a/app/services/projects/apple_target_platform_detector_service.rb b/app/services/projects/apple_target_platform_detector_service.rb index ec4c16a1416..087bb1f22e1 100644 --- a/app/services/projects/apple_target_platform_detector_service.rb +++ b/app/services/projects/apple_target_platform_detector_service.rb @@ -20,7 +20,7 @@ module Projects # > AppleTargetPlatformDetectorService.new(multiplatform_project).execute # => [:ios, :osx, :tvos, :watchos] class AppleTargetPlatformDetectorService < BaseService - BUILD_CONFIG_FILENAMES = %w(project.pbxproj *.xcconfig).freeze + BUILD_CONFIG_FILENAMES = %w[project.pbxproj *.xcconfig].freeze # For the current iteration, we only want to detect when the project targets # iOS. In the future, we can use the same logic to detect projects that diff --git a/app/services/projects/container_repository/cleanup_tags_base_service.rb b/app/services/projects/container_repository/cleanup_tags_base_service.rb index 45557d03502..61b09de1643 100644 --- a/app/services/projects/container_repository/cleanup_tags_base_service.rb +++ b/app/services/projects/container_repository/cleanup_tags_base_service.rb @@ -100,7 +100,7 @@ module Projects def older_than_in_seconds strong_memoize(:older_than_in_seconds) do - ChronicDuration.parse(older_than).seconds + ChronicDuration.parse(older_than, use_complete_matcher: true).seconds end end end diff --git a/app/services/projects/container_repository/gitlab/delete_tags_service.rb b/app/services/projects/container_repository/gitlab/delete_tags_service.rb index 530cf87c338..a5b7f4bbb6f 100644 --- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb +++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb @@ -39,7 +39,7 @@ module Projects end end - @deleted_tags.any? ? success(deleted: @deleted_tags) : error('could not delete tags') + @deleted_tags.any? ? success(deleted: @deleted_tags) : error("could not delete tags: #{@tag_names.join(', ')}".truncate(1000)) end end end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index bca78b88630..e4987438c57 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -144,6 +144,8 @@ module Projects end def create_project_settings + Gitlab::Pages.add_unique_domain_to(project) + @project.project_setting.save if @project.project_setting.changed? end @@ -223,22 +225,26 @@ module Projects end def save_project_and_import_data - ApplicationRecord.transaction do - @project.create_or_update_import_data(data: @import_data[:data], credentials: @import_data[:credentials]) if @import_data + Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.temporary_ignore_tables_in_transaction( + %w[routes redirect_routes], url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/424281' + ) do + ApplicationRecord.transaction do + @project.create_or_update_import_data(data: @import_data[:data], credentials: @import_data[:credentials]) if @import_data - # Avoid project callbacks being triggered multiple times by saving the parent first. - # See https://github.com/rails/rails/issues/41701. - Namespaces::ProjectNamespace.create_from_project!(@project) if @project.valid? + # Avoid project callbacks being triggered multiple times by saving the parent first. + # See https://github.com/rails/rails/issues/41701. + Namespaces::ProjectNamespace.create_from_project!(@project) if @project.valid? - if @project.saved? - Integration.create_from_active_default_integrations(@project, :project_id) + if @project.saved? + Integration.create_from_active_default_integrations(@project, :project_id) - @project.create_labels unless @project.gitlab_project_import? + @project.create_labels unless @project.gitlab_project_import? - next if @project.import? + next if @project.import? - unless @project.create_repository(default_branch: default_branch) - raise 'Failed to create repository' + unless @project.create_repository(default_branch: default_branch) + raise 'Failed to create repository' + end end end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 0ae6fcb4d97..a2a2f9d2800 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -255,7 +255,11 @@ module Projects # We need to remove them when a project is deleted # rubocop: disable CodeReuse/ActiveRecord def destroy_project_bots! - project.members.includes(:user).references(:user).merge(User.project_bot).each do |member| + members = project.members + .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/422405') + .includes(:user).references(:user).merge(User.project_bot) + + members.each do |member| Users::DestroyService.new(current_user).execute(member.user, skip_authorization: true) end end diff --git a/app/services/projects/download_service.rb b/app/services/projects/download_service.rb index 22104409199..d67b7832bf8 100644 --- a/app/services/projects/download_service.rb +++ b/app/services/projects/download_service.rb @@ -28,7 +28,7 @@ module Projects end def http?(url) - url =~ /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/ + url =~ /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/ end def valid_domain?(url) diff --git a/app/services/projects/hashed_storage/migrate_attachments_service.rb b/app/services/projects/hashed_storage/migrate_attachments_service.rb index 023f8494d99..40c4fd5376c 100644 --- a/app/services/projects/hashed_storage/migrate_attachments_service.rb +++ b/app/services/projects/hashed_storage/migrate_attachments_service.rb @@ -6,7 +6,7 @@ module Projects extend ::Gitlab::Utils::Override # List of paths that can be excluded while evaluation if a target can be discarded - DISCARDABLE_PATHS = %w(tmp tmp/cache tmp/work).freeze + DISCARDABLE_PATHS = %w[tmp tmp/cache tmp/work].freeze def initialize(project:, old_disk_path:, logger: nil) super diff --git a/app/services/projects/import_error_filter.rb b/app/services/projects/import_error_filter.rb index 737b794484d..a0fc5149bb4 100644 --- a/app/services/projects/import_error_filter.rb +++ b/app/services/projects/import_error_filter.rb @@ -4,7 +4,7 @@ module Projects # Used by project imports, it removes any potential paths # included in an error message that could be stored in the DB class ImportErrorFilter - ERROR_MESSAGE_FILTER = /[^\s]*#{File::SEPARATOR}[^\s]*(?=(\s|\z))/.freeze + ERROR_MESSAGE_FILTER = /[^\s]*#{File::SEPARATOR}[^\s]*(?=(\s|\z))/ FILTER_MESSAGE = '[FILTERED]' def self.filter_message(message) diff --git a/app/services/projects/in_product_marketing_campaign_emails_service.rb b/app/services/projects/in_product_marketing_campaign_emails_service.rb index 249a2d89fc1..a549d8f594e 100644 --- a/app/services/projects/in_product_marketing_campaign_emails_service.rb +++ b/app/services/projects/in_product_marketing_campaign_emails_service.rb @@ -26,13 +26,9 @@ module Projects sent_email_records.save! end - # rubocop: disable CodeReuse/ActiveRecord def project_users - @project_users ||= project.users - .where(email_opted_in: true) - .merge(Users::InProductMarketingEmail.without_campaign(campaign)) + @project_users ||= project.users.merge(Users::InProductMarketingEmail.without_campaign(campaign)) end - # rubocop: enable CodeReuse/ActiveRecord def project_users_max_access_levels ids = project_users.map(&:id) diff --git a/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb b/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb index 09fec9939b9..0efe9fb16f6 100644 --- a/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb +++ b/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb @@ -9,7 +9,7 @@ module Projects include Gitlab::Utils::StrongMemoize HEAD_REV = 'HEAD' - LFS_ENDPOINT_PATTERN = /^\t?url\s*=\s*(.+)$/.freeze + LFS_ENDPOINT_PATTERN = /^\t?url\s*=\s*(.+)$/ LFS_BATCH_API_ENDPOINT = '/info/lfs/objects/batch' LfsObjectDownloadListError = Class.new(StandardError) @@ -101,7 +101,7 @@ module Projects # The import url must end with '.git' here we ensure it is def default_endpoint_uri @default_endpoint_uri ||= import_uri.dup.tap do |uri| - path = uri.path.gsub(%r(/$), '') + path = uri.path.gsub(%r{/$}, '') path += '.git' unless path.ends_with?('.git') uri.path = path + LFS_BATCH_API_ENDPOINT end diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 642ec37619f..3d08039942b 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -110,36 +110,40 @@ module Projects end def proceed_to_transfer - Project.transaction do - project.expire_caches_before_rename(@old_path) + Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.temporary_ignore_tables_in_transaction( + %w[routes redirect_routes], url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/424282' + ) do + Project.transaction do + project.expire_caches_before_rename(@old_path) - # Apply changes to the project - update_namespace_and_visibility(@new_namespace) - project.reconcile_shared_runners_setting! - project.save! + # Apply changes to the project + update_namespace_and_visibility(@new_namespace) + project.reconcile_shared_runners_setting! + project.save! - # Notifications - project.send_move_instructions(@old_path) + # Notifications + project.send_move_instructions(@old_path) - # Directories on disk - move_project_folders(project) + # Directories on disk + move_project_folders(project) - transfer_missing_group_resources(@old_group) + transfer_missing_group_resources(@old_group) - # Move uploads - move_project_uploads(project) + # Move uploads + move_project_uploads(project) - update_integrations + update_integrations - remove_paid_features + remove_paid_features - project.old_path_with_namespace = @old_path + project.old_path_with_namespace = @old_path - update_repository_configuration(@new_path) + update_repository_configuration(@new_path) - remove_issue_contacts + remove_issue_contacts - execute_system_hooks + execute_system_hooks + end end update_pending_builds diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 403f645392c..dc92c501b8c 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -2,10 +2,12 @@ module Projects class UpdatePagesService < BaseService + include Gitlab::Utils::StrongMemoize + # old deployment can be cached by pages daemon # so we need to give pages daemon some time update cache # 10 minutes is enough, but 30 feels safer - OLD_DEPLOYMENTS_DESTRUCTION_DELAY = 30.minutes.freeze + OLD_DEPLOYMENTS_DESTRUCTION_DELAY = 30.minutes attr_reader :build, :deployment_update @@ -18,9 +20,7 @@ module Projects def execute register_attempt - # Create status notifying the deployment of pages - @commit_status = build_commit_status - ::Ci::Pipelines::AddJobService.new(@build.pipeline).execute!(@commit_status) do |job| + ::Ci::Pipelines::AddJobService.new(@build.pipeline).execute!(commit_status) do |job| job.enqueue! job.run! end @@ -31,13 +31,10 @@ module Projects deployment = create_pages_deployment(artifacts_path, build) break error('The uploaded artifact size does not match the expected value') unless deployment + break error(deployment_update.errors.first.full_message) unless deployment_update.valid? - if deployment_update.valid? - update_project_pages_deployment(deployment) - success - else - error(deployment_update.errors.first.full_message) - end + update_project_pages_deployment(deployment) + success end rescue StandardError => e error(e.message) @@ -47,7 +44,7 @@ module Projects private def success - @commit_status.success + commit_status.success @project.mark_pages_as_deployed publish_deployed_event super @@ -56,15 +53,14 @@ module Projects def error(message) register_failure log_error("Projects::UpdatePagesService: #{message}") - @commit_status.allow_failure = !deployment_update.latest? - @commit_status.description = message - @commit_status.drop(:script_failure) + commit_status.allow_failure = !deployment_update.latest? + commit_status.description = message + commit_status.drop(:script_failure) super end - def build_commit_status - stage = create_stage - + # Create status notifying the deployment of pages + def commit_status GenericCommitStatus.new( user: build.user, ci_stage: stage, @@ -73,26 +69,22 @@ module Projects stage_idx: stage.position ) end + strong_memoize_attr :commit_status # rubocop: disable Performance/ActiveRecordSubtransactionMethods - def create_stage + def stage build.pipeline.stages.safe_find_or_create_by(name: 'deploy', pipeline_id: build.pipeline.id) do |stage| stage.position = GenericCommitStatus::EXTERNAL_STAGE_IDX stage.project = build.project end end + strong_memoize_attr :commit_status # rubocop: enable Performance/ActiveRecordSubtransactionMethods def create_pages_deployment(artifacts_path, build) - sha256 = build.job_artifacts_archive.file_sha256 File.open(artifacts_path) do |file| - deployment = project.pages_deployments.create!( - file: file, - file_count: deployment_update.entries_count, - file_sha256: sha256, - ci_build_id: build.id, - root_directory: build.options[:publish] - ) + attributes = pages_deployment_attributes(file, build) + deployment = project.pages_deployments.create!(**attributes) break if deployment.size != file.size || deployment.file.size != file.size @@ -100,21 +92,28 @@ module Projects end end + # overridden on EE + def pages_deployment_attributes(file, build) + { + file: file, + file_count: deployment_update.entries_count, + file_sha256: build.job_artifacts_archive.file_sha256, + ci_build_id: build.id, + root_directory: build.options[:publish] + } + end + def update_project_pages_deployment(deployment) project.update_pages_deployment!(deployment) + + PagesDeployment.deactivate_deployments_older_than( + deployment, + time: OLD_DEPLOYMENTS_DESTRUCTION_DELAY.from_now) + DestroyPagesDeploymentsWorker.perform_in( OLD_DEPLOYMENTS_DESTRUCTION_DELAY, project.id, - deployment.id - ) - end - - def ref - build.ref - end - - def artifacts - build.artifacts_file.path + deployment.id) end def register_attempt @@ -126,12 +125,14 @@ module Projects end def pages_deployments_total_counter - @pages_deployments_total_counter ||= Gitlab::Metrics.counter(:pages_deployments_total, "Counter of GitLab Pages deployments triggered") + Gitlab::Metrics.counter(:pages_deployments_total, "Counter of GitLab Pages deployments triggered") end + strong_memoize_attr :pages_deployments_total_counter def pages_deployments_failed_total_counter - @pages_deployments_failed_total_counter ||= Gitlab::Metrics.counter(:pages_deployments_failed_total, "Counter of GitLab Pages deployments which failed") + Gitlab::Metrics.counter(:pages_deployments_failed_total, "Counter of GitLab Pages deployments which failed") end + strong_memoize_attr :pages_deployments_failed_total_counter def publish_deployed_event event = ::Pages::PageDeployedEvent.new(data: { @@ -144,3 +145,5 @@ module Projects end end end + +::Projects::UpdatePagesService.prepend_mod diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb index f5f6bb85995..799ae5677c3 100644 --- a/app/services/projects/update_repository_storage_service.rb +++ b/app/services/projects/update_repository_storage_service.rb @@ -80,8 +80,8 @@ module Projects end def pool_repository_exists_for?(shard_name:, pool_repository:) - PoolRepository.by_source_project_and_shard_name( - pool_repository.source_project, + PoolRepository.by_disk_path_and_shard_name( + pool_repository.disk_path, shard_name ).exists? end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 8639e2f833f..e5e39247dbf 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -53,13 +53,7 @@ module Projects def add_pages_unique_domain return unless params.dig(:project_setting_attributes, :pages_unique_domain_enabled) - # If the project used a unique domain once, it'll always use the same - return if project.project_setting.pages_unique_domain_in_database.present? - - params[:project_setting_attributes][:pages_unique_domain] = Gitlab::Pages::RandomDomain.generate( - project_path: project.path, - namespace_path: project.parent.full_path - ) + Gitlab::Pages.add_unique_domain_to(project) end def validate! @@ -112,6 +106,7 @@ module Projects # overridden by EE module end + # overridden by EE module def remove_unallowed_params params.delete(:emails_enabled) unless can?(current_user, :set_emails_disabled, project) @@ -119,11 +114,11 @@ module Projects end def after_update - todos_features_changes = %w( + todos_features_changes = %w[ issues_access_level merge_requests_access_level repository_access_level - ) + ] project_changed_feature_keys = project.project_feature.previous_changes.keys if project.visibility_level_previous_changes && project.private? |