diff options
Diffstat (limited to 'app/services/projects')
-rw-r--r-- | app/services/projects/alerting/notify_service.rb | 94 | ||||
-rw-r--r-- | app/services/projects/branches_by_mode_service.rb | 88 | ||||
-rw-r--r-- | app/services/projects/cleanup_service.rb | 2 | ||||
-rw-r--r-- | app/services/projects/container_repository/cleanup_tags_service.rb | 1 | ||||
-rw-r--r-- | app/services/projects/create_service.rb | 20 | ||||
-rw-r--r-- | app/services/projects/fork_service.rb | 11 | ||||
-rw-r--r-- | app/services/projects/import_export/export_service.rb | 6 | ||||
-rw-r--r-- | app/services/projects/update_pages_service.rb | 4 | ||||
-rw-r--r-- | app/services/projects/update_service.rb | 18 |
9 files changed, 141 insertions, 103 deletions
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb index 014fb0e3ed3..2ba64b73699 100644 --- a/app/services/projects/alerting/notify_service.rb +++ b/app/services/projects/alerting/notify_service.rb @@ -3,9 +3,8 @@ module Projects module Alerting class NotifyService - include BaseServiceUtility - include Gitlab::Utils::StrongMemoize - include ::IncidentManagement::Settings + extend ::Gitlab::Utils::Override + include ::AlertManagement::AlertProcessing def initialize(project, payload) @project = project @@ -22,8 +21,7 @@ module Projects process_alert return bad_request unless alert.persisted? - process_incident_issues if process_issues? - send_alert_email if send_email? + complete_post_processing_tasks ServiceResponse.success end @@ -32,93 +30,15 @@ module Projects attr_reader :project, :payload, :integration - def process_alert - if alert.persisted? - process_existing_alert - else - create_alert - end - end - - def process_existing_alert - if incoming_payload.ends_at.present? - process_resolved_alert - else - alert.register_new_event! - end - - alert - end - - def process_resolved_alert - return unless auto_close_incident? - - if alert.resolve(incoming_payload.ends_at) - close_issue(alert.issue) - end - - alert - end - - def close_issue(issue) - return if issue.blank? || issue.closed? - - ::Issues::CloseService - .new(project, User.alert_bot) - .execute(issue, system_note: false) - - SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed? - end - - def create_alert - return unless alert.save - - alert.execute_services - SystemNoteService.create_new_alert(alert, notification_source) - end - - def process_incident_issues - return if alert.issue || alert.resolved? - - ::IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id) - end - - def send_alert_email - notification_service - .async - .prometheus_alerts_fired(project, [alert]) - end - - def alert - strong_memoize(:alert) do - existing_alert || new_alert - end - end - - def existing_alert - return unless incoming_payload.gitlab_fingerprint - - AlertManagement::Alert.not_resolved.for_fingerprint(project, incoming_payload.gitlab_fingerprint).first - end - - def new_alert - AlertManagement::Alert.new(**incoming_payload.alert_params, ended_at: nil) - end - - def incoming_payload - strong_memoize(:incoming_payload) do - Gitlab::AlertManagement::Payload.parse(project, payload.to_h) - end + def valid_payload_size? + Gitlab::Utils::DeepSize.new(payload).valid? end - def notification_source + override :alert_source + def alert_source alert.monitoring_tool || integration&.name || 'Generic Alert Endpoint' end - def valid_payload_size? - Gitlab::Utils::DeepSize.new(payload).valid? - end - def active_integration? integration&.active? end diff --git a/app/services/projects/branches_by_mode_service.rb b/app/services/projects/branches_by_mode_service.rb new file mode 100644 index 00000000000..fb66bfa073b --- /dev/null +++ b/app/services/projects/branches_by_mode_service.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +# Projects::BranchesByModeService uses Gitaly page-token pagination +# in order to optimally fetch branches. +# The drawback of the page-token pagination is that it doesn't provide +# an option of going to the previous page of the collection. +# That's why we need to fall back to offset pagination when previous page +# is requested. +class Projects::BranchesByModeService + include Gitlab::Routing + + attr_reader :project, :params + + def initialize(project, params = {}) + @project = project + @params = params + end + + def execute + return fetch_branches_via_gitaly_pagination if use_gitaly_pagination? + + fetch_branches_via_offset_pagination + end + + private + + def mode + params[:mode] + end + + def by_mode(branches) + return branches unless %w[active stale].include?(mode) + + branches.select { |b| b.state.to_s == mode } + end + + def use_gitaly_pagination? + return false if params[:page].present? || params[:search].present? + + Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: true) + end + + def fetch_branches_via_offset_pagination + branches = BranchesFinder.new(project.repository, params).execute + branches = Kaminari.paginate_array(by_mode(branches)).page(params[:page]) + + branches_with_links(branches, last_page: branches.last_page?) + end + + def fetch_branches_via_gitaly_pagination + per_page = Kaminari.config.default_per_page + options = params.merge(per_page: per_page + 1, page_token: params[:page_token]) + + branches = BranchesFinder.new(project.repository, options).execute(gitaly_pagination: true) + + # Branch is stale if it hasn't been updated for 3 months + # This logic is specified in Gitlab Rails and isn't specified in Gitaly + # To display stale branches we fetch branches sorted as most-stale-at-the-top + # If the result contains active branches we filter them out and define that no more stale branches left + # Same logic applies to fetching active branches + branches = by_mode(branches) + last_page = branches.size <= per_page + + branches = branches.take(per_page) # rubocop:disable CodeReuse/ActiveRecord + + branches_with_links(branches, last_page: last_page) + end + + def branches_with_links(branches, last_page:) + # To fall back to offset pagination we need to track current page via offset param + # And increase it whenever we go to the next page + previous_offset = params[:offset].to_i + + previous_path, next_path = nil, nil + + return [branches, previous_path, next_path] if branches.blank? + + unless last_page + next_path = project_branches_filtered_path(project, state: mode, page_token: branches.last.name, sort: params[:sort], offset: previous_offset + 1) + end + + if previous_offset > 0 + previous_path = project_branches_filtered_path(project, state: mode, sort: params[:sort], page: previous_offset, offset: previous_offset - 1) + end + + [branches, previous_path, next_path] + end +end diff --git a/app/services/projects/cleanup_service.rb b/app/services/projects/cleanup_service.rb index 6e3b320afbe..7bcaee75813 100644 --- a/app/services/projects/cleanup_service.rb +++ b/app/services/projects/cleanup_service.rb @@ -40,7 +40,7 @@ module Projects apply_bfg_object_map! # Remove older objects that are no longer referenced - GitGarbageCollectWorker.new.perform(project.id, :prune, "project_cleanup:gc:#{project.id}") + Projects::GitGarbageCollectWorker.new.perform(project.id, :prune, "project_cleanup:gc:#{project.id}") # The cache may now be inaccurate, and holding onto it could prevent # bugs assuming the presence of some object from manifesting for some diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb index af0107436c8..793d2fec033 100644 --- a/app/services/projects/container_repository/cleanup_tags_service.rb +++ b/app/services/projects/container_repository/cleanup_tags_service.rb @@ -25,6 +25,7 @@ module Projects result[:before_truncate_size] = before_truncate_size result[:after_truncate_size] = after_truncate_size result[:before_delete_size] = tags.size + result[:deleted_size] = result[:deleted]&.size result[:status] = :error if before_truncate_size != after_truncate_size end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index a01db4b498c..08f569662a8 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -127,7 +127,7 @@ module Projects access_level: group_access_level) end - if Feature.enabled?(:specialized_project_authorization_workers) + if Feature.enabled?(:specialized_project_authorization_workers, default_enabled: :yaml) AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id) # AuthorizedProjectsWorker uses an exclusive lease per user but # specialized workers might have synchronization issues. Until we @@ -210,16 +210,22 @@ module Projects end def set_project_name_from_path - # Set project name from path - if @project.name.present? && @project.path.present? - # if both name and path set - everything is ok - elsif @project.path.present? + # if both name and path set - everything is ok + return if @project.name.present? && @project.path.present? + + if @project.path.present? # Set project name from path @project.name = @project.path.dup elsif @project.name.present? # For compatibility - set path from name - # TODO: remove this in 8.0 - @project.path = @project.name.dup.parameterize + @project.path = @project.name.dup + + # TODO: Retained for backwards compatibility. Remove in API v5. + # When removed, validation errors will get bubbled up automatically. + # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52725 + unless @project.path.match?(Gitlab::PathRegex.project_path_format_regex) + @project.path = @project.path.parameterize + end end end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 050bfdd862d..fd9b64a4ee0 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -43,8 +43,8 @@ module Projects def new_fork_params new_params = { forked_from_project: @project, - visibility_level: allowed_visibility_level, - description: @project.description, + visibility_level: target_visibility_level, + description: target_description, name: target_name, path: target_path, shared_runners_enabled: @project.shared_runners_enabled, @@ -107,6 +107,10 @@ module Projects @target_name ||= @params[:name] || @project.name end + def target_description + @target_description ||= @params[:description] || @project.description + end + def target_namespace @target_namespace ||= @params[:namespace] || current_user.namespace end @@ -115,8 +119,9 @@ module Projects @skip_disk_validation ||= @params[:skip_disk_validation] || false end - def allowed_visibility_level + def target_visibility_level target_level = [@project.visibility_level, target_namespace.visibility_level].min + target_level = [target_level, Gitlab::VisibilityLevel.level_value(params[:visibility])].min if params.key?(:visibility) Gitlab::VisibilityLevel.closest_allowed_level(target_level) end diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb index 031b99753c3..c2a8db7b657 100644 --- a/app/services/projects/import_export/export_service.rb +++ b/app/services/projects/import_export/export_service.rb @@ -86,11 +86,11 @@ module Projects end def repo_saver - Gitlab::ImportExport::RepoSaver.new(project: project, shared: shared) + Gitlab::ImportExport::RepoSaver.new(exportable: project, shared: shared) end def wiki_repo_saver - Gitlab::ImportExport::WikiRepoSaver.new(project: project, shared: shared) + Gitlab::ImportExport::WikiRepoSaver.new(exportable: project, shared: shared) end def lfs_saver @@ -102,7 +102,7 @@ module Projects end def design_repo_saver - Gitlab::ImportExport::DesignRepoSaver.new(project: project, shared: shared) + Gitlab::ImportExport::DesignRepoSaver.new(exportable: project, shared: shared) end def cleanup diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 25d46ada885..29e92d725e2 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -80,6 +80,10 @@ module Projects end def deploy_to_legacy_storage(artifacts_path) + # path today used by one project can later be used by another + # so we can't really scope this feature flag by project or group + return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true) + # Create temporary directory in which we will extract the artifacts make_secure_tmp_dir(tmp_path) do |tmp_path| extract_archive!(artifacts_path, tmp_path) diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 50a544ed1a5..8384bfa813f 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -56,11 +56,25 @@ module Projects raise ValidationError.new(s_('UpdateProject|Cannot rename project because it contains container registry tags!')) end - if changing_default_branch? - raise ValidationError.new(s_("UpdateProject|Could not set the default branch")) unless project.change_head(params[:default_branch]) + validate_default_branch_change + end + + def validate_default_branch_change + return unless changing_default_branch? + + previous_default_branch = project.default_branch + + if project.change_head(params[:default_branch]) + after_default_branch_change(previous_default_branch) + else + raise ValidationError.new(s_("UpdateProject|Could not set the default branch")) end end + def after_default_branch_change(previous_default_branch) + # overridden by EE module + end + def remove_unallowed_params params.delete(:emails_disabled) unless can?(current_user, :set_emails_disabled, project) end |