diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-19 10:33:21 +0300 |
commit | 36a59d088eca61b834191dacea009677a96c052f (patch) | |
tree | e4f33972dab5d8ef79e3944a9f403035fceea43f /app/services/projects | |
parent | a1761f15ec2cae7c7f7bbda39a75494add0dfd6f (diff) |
Add latest changes from gitlab-org/gitlab@15-0-stable-eev15.0.0-rc42
Diffstat (limited to 'app/services/projects')
24 files changed, 286 insertions, 282 deletions
diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb deleted file mode 100644 index bb0d084d191..00000000000 --- a/app/services/projects/after_import_service.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module Projects - class AfterImportService - RESERVED_REF_PREFIXES = Repository::RESERVED_REFS_NAMES.map { |n| File.join('refs', n, '/') } - - def initialize(project) - @project = project - end - - def execute - service = Repositories::HousekeepingService.new(@project) - - service.execute do - import_failure_service.with_retry(action: 'delete_all_refs') do - repository.delete_all_refs_except(RESERVED_REF_PREFIXES) - end - end - - # Right now we don't actually have a way to know if a project - # import actually changed, so we increment the counter to avoid - # causing GC to run every time. - service.increment! - rescue Repositories::HousekeepingService::LeaseTaken => e - Gitlab::Import::Logger.info( - message: 'Project housekeeping failed', - project_full_path: @project.full_path, - project_id: @project.id, - 'error.message' => e.message - ) - end - - private - - def import_failure_service - Gitlab::ImportExport::ImportFailureService.new(@project) - end - - def repository - @project.repository - end - end -end diff --git a/app/services/projects/android_target_platform_detector_service.rb b/app/services/projects/android_target_platform_detector_service.rb new file mode 100644 index 00000000000..11635ad18d5 --- /dev/null +++ b/app/services/projects/android_target_platform_detector_service.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Projects + # Service class to detect if a project is made to run on the Android platform. + # + # This service searches for an AndroidManifest.xml file which all Android app + # project must have. It returns the symbol :android if the given project is an + # Android app project. + # + # Ref: https://developer.android.com/guide/topics/manifest/manifest-intro + # + # Example usage: + # > AndroidTargetPlatformDetectorService.new(a_project).execute + # => nil + # > AndroidTargetPlatformDetectorService.new(an_android_project).execute + # => :android + class AndroidTargetPlatformDetectorService < BaseService + # <manifest> element is required and must occur once inside AndroidManifest.xml + MANIFEST_FILE_SEARCH_QUERY = '<manifest filename:AndroidManifest.xml' + + def execute + detect + end + + private + + def file_finder + @file_finder ||= ::Gitlab::FileFinder.new(project, project.default_branch) + end + + def detect + return :android if file_finder.find(MANIFEST_FILE_SEARCH_QUERY).present? + end + end +end diff --git a/app/services/projects/blame_service.rb b/app/services/projects/blame_service.rb new file mode 100644 index 00000000000..f7c1240a3ba --- /dev/null +++ b/app/services/projects/blame_service.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +# Service class to correctly initialize Gitlab::Blame and Kaminari pagination +# objects +module Projects + class BlameService + PER_PAGE = 1000 + + def initialize(blob, commit, params) + @blob = blob + @commit = commit + @page = extract_page(params) + end + + def blame + Gitlab::Blame.new(blob, commit, range: blame_range) + end + + def pagination + return unless pagination_enabled? + + Kaminari.paginate_array([], total_count: blob_lines_count) + .page(page) + .per(per_page) + .limit(per_page) + end + + private + + attr_reader :blob, :commit, :page + + def blame_range + return unless pagination_enabled? + + first_line = (page - 1) * per_page + 1 + last_line = (first_line + per_page).to_i - 1 + + first_line..last_line + end + + def extract_page(params) + page = params.fetch(:page, 1).to_i + + return 1 if page < 1 || overlimit?(page) + + page + end + + def per_page + PER_PAGE + end + + def overlimit?(page) + page * per_page >= blob_lines_count + per_page + end + + def blob_lines_count + @blob_lines_count ||= blob.data.lines.count + end + + def pagination_enabled? + Feature.enabled?(:blame_page_pagination, commit.project) + end + end +end diff --git a/app/services/projects/branches_by_mode_service.rb b/app/services/projects/branches_by_mode_service.rb index 090671cc79a..0248f997a03 100644 --- a/app/services/projects/branches_by_mode_service.rb +++ b/app/services/projects/branches_by_mode_service.rb @@ -37,7 +37,7 @@ class Projects::BranchesByModeService def use_gitaly_pagination? return false if params[:page].present? || params[:search].present? - Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml) + Feature.enabled?(:branch_list_keyset_pagination, project) end def fetch_branches_via_offset_pagination diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb index 72f3fddb4c3..0a8e8e72766 100644 --- a/app/services/projects/container_repository/cleanup_tags_service.rb +++ b/app/services/projects/container_repository/cleanup_tags_service.rb @@ -117,7 +117,6 @@ module Projects @counts[:before_truncate_size] = @tags.size @counts[:after_truncate_size] = @tags.size - return unless throttling_enabled? return if max_list_size == 0 # truncate the list to make sure that after the #filter_keep_n @@ -151,10 +150,6 @@ module Projects !!result end - def throttling_enabled? - Feature.enabled?(:container_registry_expiration_policies_throttling, default_enabled: :yaml) - end - def max_list_size ::Gitlab::CurrentSettings.current_application_settings.container_registry_cleanup_tags_service_max_list_size.to_i end diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb index b4a57c70111..a3e533c670e 100644 --- a/app/services/projects/container_repository/delete_tags_service.rb +++ b/app/services/projects/container_repository/delete_tags_service.rb @@ -8,13 +8,13 @@ module Projects def execute(container_repository) @container_repository = container_repository - unless params[:container_expiration_policy] + unless container_expiration_policy? return error('access denied') unless can?(current_user, :destroy_container_image, project) end @tag_names = params[:tags] return error('not tags specified') if @tag_names.blank? - return error('repository importing') if @container_repository.migration_importing? + return error('repository importing') if cancel_while_importing? delete_tags end @@ -49,6 +49,20 @@ module Projects log_error(log_data) end end + + def cancel_while_importing? + return true if @container_repository.importing? + + if container_expiration_policy? + return @container_repository.pre_importing? || @container_repository.pre_import_done? + end + + false + end + + def container_expiration_policy? + params[:container_expiration_policy].present? + end 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 f109cb0ca20..81cef554dec 100644 --- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb +++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb @@ -46,18 +46,11 @@ module Projects end def timeout?(start_time) - return false unless throttling_enabled? return false if service_timeout.in?(DISABLED_TIMEOUTS) (Time.zone.now - start_time) > service_timeout end - def throttling_enabled? - strong_memoize(:feature_flag) do - Feature.enabled?(:container_registry_expiration_policies_throttling, default_enabled: :yaml) - end - end - def service_timeout ::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 3e26c8c35b2..c7f284bec9b 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -4,6 +4,9 @@ module Projects class CreateService < BaseService include ValidatesClassificationLabel + ImportSourceDisabledError = Class.new(StandardError) + INTERNAL_IMPORT_SOURCES = %w[bare_repository gitlab_custom_project_template gitlab_project_migration].freeze + def initialize(user, params) @current_user = user @params = params.dup @@ -25,6 +28,8 @@ module Projects @project = Project.new(params) + validate_import_source_enabled! + @project.visibility_level = @project.group.visibility_level unless @project.visibility_level_allowed_by_group? # If a project is newly created it should have shared runners settings @@ -77,6 +82,9 @@ module Projects rescue ActiveRecord::RecordInvalid => e message = "Unable to save #{e.inspect}: #{e.record.errors.full_messages.join(", ")}" fail(error: message) + rescue ImportSourceDisabledError => e + @project.errors.add(:import_source_disabled, e.message) if @project + fail(error: e.message) rescue StandardError => e @project.errors.add(:base, e.message) if @project fail(error: e.message) @@ -124,11 +132,7 @@ module Projects end def create_project_settings - if Feature.enabled?(:create_project_settings, default_enabled: :yaml) - @project.project_setting.save if @project.project_setting.changed? - else - @project.create_project_setting unless @project.project_setting - end + @project.project_setting.save if @project.project_setting.changed? end # Add an authorization for the current user authorizations inline @@ -157,6 +161,13 @@ module Projects ) else @project.add_owner(@project.namespace.owner, current_user: current_user) + # During the process of adding a project owner, a check on permissions is made on the user which caches + # the max member access for that user on this project. + # Since that is `0` before the member is created - and we are still inside the request + # cycle when we need to do other operations that might check those permissions (e.g. write a commit) + # we need to purge that cache so that the updated permissions is fetched instead of using the outdated cached value of 0 + # from before member creation + @project.team.purge_member_access_cache_for_user_id(@project.namespace.owner.id) end end @@ -242,6 +253,18 @@ module Projects private + def validate_import_source_enabled! + return unless @params[:import_type] + + import_type = @params[:import_type].to_s + + return if INTERNAL_IMPORT_SOURCES.include?(import_type) + + unless ::Gitlab::CurrentSettings.import_sources&.include?(import_type) + raise ImportSourceDisabledError, "#{import_type} import source is disabled" + end + end + def parent_namespace @parent_namespace ||= Namespace.find_by_id(@params[:namespace_id]) || current_user.namespace end diff --git a/app/services/projects/group_links/create_service.rb b/app/services/projects/group_links/create_service.rb index a0232779c97..72036aaff35 100644 --- a/app/services/projects/group_links/create_service.rb +++ b/app/services/projects/group_links/create_service.rb @@ -3,26 +3,31 @@ module Projects module GroupLinks class CreateService < BaseService - def execute(group) - return error('Not Found', 404) unless group && can?(current_user, :read_namespace, group) + include GroupLinkable - link = project.project_group_links.new( - group: group, - group_access: params[:link_group_access], - expires_at: params[:expires_at] - ) + def initialize(project, shared_with_group, user, params) + @shared_with_group = shared_with_group - if link.save - setup_authorizations(group) - success(link: link) - else - error(link.errors.full_messages.to_sentence, 409) - end + super(project, user, params) end private - def setup_authorizations(group) + delegate :root_ancestor, to: :project + + def valid_to_create? + can?(current_user, :read_namespace, shared_with_group) && sharing_allowed? + end + + def build_link + @link = project.project_group_links.new( + group: shared_with_group, + group_access: params[:link_group_access], + expires_at: params[:expires_at] + ) + end + + def setup_authorizations AuthorizedProjectUpdate::ProjectRecalculateWorker.perform_async(project.id) # AuthorizedProjectsWorker uses an exclusive lease per user but @@ -30,7 +35,7 @@ module Projects # compare the inconsistency rates of both approaches, we still run # AuthorizedProjectsWorker but with some delay and lower urgency as a # safety net. - group.refresh_members_authorized_projects( + shared_with_group.refresh_members_authorized_projects( blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY ) diff --git a/app/services/projects/in_product_marketing_campaign_emails_service.rb b/app/services/projects/in_product_marketing_campaign_emails_service.rb new file mode 100644 index 00000000000..249a2d89fc1 --- /dev/null +++ b/app/services/projects/in_product_marketing_campaign_emails_service.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Projects + class InProductMarketingCampaignEmailsService + include Gitlab::Experiment::Dsl + + def initialize(project, campaign) + @project = project + @campaign = campaign + @sent_email_records = ::Users::InProductMarketingEmailRecords.new + end + + def execute + send_emails + end + + private + + attr_reader :project, :campaign, :sent_email_records + + def send_emails + project_users.each do |user| + send_email(user) + end + + 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)) + end + # rubocop: enable CodeReuse/ActiveRecord + + def project_users_max_access_levels + ids = project_users.map(&:id) + @project_users_max_access_levels ||= project.team.max_member_access_for_user_ids(ids) + end + + def send_email(user) + return unless user.can?(:receive_notifications) + return unless target_user?(user) + + Notify.build_ios_app_guide_email(user.notification_email_or_default).deliver_later + + sent_email_records.add(user, campaign: campaign) + experiment(:build_ios_app_guide_email, project: project).track(:email_sent) + end + + def target_user?(user) + max_access_level = project_users_max_access_levels[user.id] + max_access_level >= Gitlab::Access::DEVELOPER + end + end +end diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb index 76005a1c96e..c032fbf1508 100644 --- a/app/services/projects/lfs_pointers/lfs_download_service.rb +++ b/app/services/projects/lfs_pointers/lfs_download_service.rb @@ -23,7 +23,7 @@ module Projects def execute return unless project&.lfs_enabled? && lfs_download_object return error("LFS file with oid #{lfs_oid} has invalid attributes") unless lfs_download_object.valid? - return link_existing_lfs_object! if Feature.enabled?(:lfs_link_existing_object, project, default_enabled: :yaml) && lfs_size > LARGE_FILE_SIZE && lfs_object + return link_existing_lfs_object! if Feature.enabled?(:lfs_link_existing_object, project) && lfs_size > LARGE_FILE_SIZE && lfs_object wrap_download_errors do download_lfs_file! diff --git a/app/services/projects/open_issues_count_service.rb b/app/services/projects/open_issues_count_service.rb index 8b7a418edf5..ee4d559e612 100644 --- a/app/services/projects/open_issues_count_service.rb +++ b/app/services/projects/open_issues_count_service.rb @@ -7,12 +7,8 @@ module Projects include Gitlab::Utils::StrongMemoize # Cache keys used to store issues count - # TOTAL_COUNT_KEY includes confidential and hidden issues (admin) - # TOTAL_COUNT_WITHOUT_HIDDEN_KEY includes confidential issues but not hidden issues (reporter and above) - # PUBLIC_COUNT_WITHOUT_HIDDEN_KEY does not include confidential or hidden issues (guest) - TOTAL_COUNT_KEY = 'project_open_issues_including_hidden_count' - TOTAL_COUNT_WITHOUT_HIDDEN_KEY = 'project_open_issues_without_hidden_count' - PUBLIC_COUNT_WITHOUT_HIDDEN_KEY = 'project_open_public_issues_without_hidden_count' + PUBLIC_COUNT_KEY = 'public_open_issues_count' + TOTAL_COUNT_KEY = 'total_open_issues_count' def initialize(project, user = nil) @user = user @@ -20,98 +16,59 @@ module Projects super(project) end - # rubocop: disable CodeReuse/ActiveRecord - def refresh_cache(&block) - if block_given? - super(&block) - else - update_cache_for_key(total_count_cache_key) do - issues_with_hidden - end - - update_cache_for_key(public_count_without_hidden_cache_key) do - issues_without_hidden_without_confidential - end - - update_cache_for_key(total_count_without_hidden_cache_key) do - issues_without_hidden_with_confidential - end - end - end - - private - - def relation_for_count - self.class.query(@project, public_only: public_only?, include_hidden: include_hidden?) - end - def cache_key_name - if include_hidden? - TOTAL_COUNT_KEY - elsif public_only? - PUBLIC_COUNT_WITHOUT_HIDDEN_KEY - else - TOTAL_COUNT_WITHOUT_HIDDEN_KEY - end - end - - def include_hidden? - user_is_admin? + public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY end def public_only? !user_is_at_least_reporter? end - def user_is_admin? - strong_memoize(:user_is_admin) do - @user&.can_admin_all_resources? - end - end - def user_is_at_least_reporter? strong_memoize(:user_is_at_least_reporter) do @user && @project.team.member?(@user, Gitlab::Access::REPORTER) end end - def total_count_without_hidden_cache_key - cache_key(TOTAL_COUNT_WITHOUT_HIDDEN_KEY) + def relation_for_count + self.class.query(@project, public_only: public_only?) end - def public_count_without_hidden_cache_key - cache_key(PUBLIC_COUNT_WITHOUT_HIDDEN_KEY) + def public_count_cache_key + cache_key(PUBLIC_COUNT_KEY) end def total_count_cache_key cache_key(TOTAL_COUNT_KEY) end - def issues_with_hidden - self.class.query(@project, public_only: false, include_hidden: true).count - end + # rubocop: disable CodeReuse/ActiveRecord + def refresh_cache(&block) + count_grouped_by_confidential = self.class.query(@project, public_only: false).group(:confidential).count + public_count = count_grouped_by_confidential[false] || 0 + total_count = public_count + (count_grouped_by_confidential[true] || 0) - def issues_without_hidden_without_confidential - self.class.query(@project, public_only: true, include_hidden: false).count - end + update_cache_for_key(public_count_cache_key) do + public_count + end - def issues_without_hidden_with_confidential - self.class.query(@project, public_only: false, include_hidden: false).count + update_cache_for_key(total_count_cache_key) do + total_count + end end - # We only show total issues count for admins, who are allowed to view hidden issues. - # We also only show issues count including confidential for reporters, who are allowed to view confidential issues. + # We only show issues count including confidential for reporters, who are allowed to view confidential issues. # This will still show a discrepancy on issues number but should be less than before. # Check https://gitlab.com/gitlab-org/gitlab-foss/issues/38418 description. + # rubocop: disable CodeReuse/ActiveRecord + def self.query(projects, public_only: true) + issues_filtered_by_type = Issue.opened.with_issue_type(Issue::TYPES_FOR_LIST) - def self.query(projects, public_only: true, include_hidden: false) - if include_hidden - Issue.opened.with_issue_type(Issue::TYPES_FOR_LIST).where(project: projects) - elsif public_only - Issue.public_only.opened.with_issue_type(Issue::TYPES_FOR_LIST).where(project: projects) + if public_only + issues_filtered_by_type.public_only.where(project: projects) else - Issue.without_hidden.opened.with_issue_type(Issue::TYPES_FOR_LIST).where(project: projects) + issues_filtered_by_type.where(project: projects) end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/projects/overwrite_project_service.rb b/app/services/projects/overwrite_project_service.rb index eea8f867b45..d3fed43363c 100644 --- a/app/services/projects/overwrite_project_service.rb +++ b/app/services/projects/overwrite_project_service.rb @@ -41,7 +41,7 @@ module Projects private def track_service(start_time, source_project, exception) - return if ::Feature.disabled?(:project_overwrite_service_tracking, source_project, default_enabled: :yaml) + return if ::Feature.disabled?(:project_overwrite_service_tracking, source_project) duration = ::Gitlab::Metrics::System.monotonic_time - start_time diff --git a/app/services/projects/participants_service.rb b/app/services/projects/participants_service.rb index c7a34afffb3..c29770d0c5f 100644 --- a/app/services/projects/participants_service.rb +++ b/app/services/projects/participants_service.rb @@ -45,7 +45,7 @@ module Projects def visible_groups visible_groups = project.invited_groups - unless project_owner? + unless project.team.owner?(current_user) visible_groups = visible_groups.public_or_visible_to_user(current_user) end @@ -60,13 +60,5 @@ module Projects def individual_project_members project.project_members.select(*GroupMember.cached_column_list) end - - def project_owner? - if project.group.present? - project.group.owners.include?(current_user) - else - project.namespace.owner == current_user - end - end end end diff --git a/app/services/projects/prometheus/alerts/alert_params.rb b/app/services/projects/prometheus/alerts/alert_params.rb deleted file mode 100644 index 1c39ed36b12..00000000000 --- a/app/services/projects/prometheus/alerts/alert_params.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Alerts - module AlertParams - def alert_params - return params if params[:operator].blank? - - params.merge( - operator: PrometheusAlert.operator_to_enum(params[:operator]) - ) - end - end - end - end -end diff --git a/app/services/projects/prometheus/alerts/create_service.rb b/app/services/projects/prometheus/alerts/create_service.rb deleted file mode 100644 index 0d7d8ab1a62..00000000000 --- a/app/services/projects/prometheus/alerts/create_service.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Alerts - class CreateService < BaseProjectService - include AlertParams - - def execute - project.prometheus_alerts.create(alert_params) - end - end - end - end -end diff --git a/app/services/projects/prometheus/alerts/destroy_service.rb b/app/services/projects/prometheus/alerts/destroy_service.rb deleted file mode 100644 index 243b12eb654..00000000000 --- a/app/services/projects/prometheus/alerts/destroy_service.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Alerts - class DestroyService < BaseProjectService - def execute(alert) - alert.destroy - end - end - end - end -end diff --git a/app/services/projects/prometheus/alerts/update_service.rb b/app/services/projects/prometheus/alerts/update_service.rb deleted file mode 100644 index 1802f35dae9..00000000000 --- a/app/services/projects/prometheus/alerts/update_service.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Alerts - class UpdateService < BaseProjectService - include AlertParams - - def execute(alert) - alert.update(alert_params) - end - end - end - end -end diff --git a/app/services/projects/prometheus/metrics/base_service.rb b/app/services/projects/prometheus/metrics/base_service.rb index be1783dde70..15247d45776 100644 --- a/app/services/projects/prometheus/metrics/base_service.rb +++ b/app/services/projects/prometheus/metrics/base_service.rb @@ -8,40 +8,12 @@ module Projects def initialize(metric, params = {}) @metric = metric - @project = metric.project @params = params.dup end protected - attr_reader :metric, :project, :params - - def application - alert.environment.cluster_prometheus_adapter - end - - def schedule_alert_update - return unless alert - return unless alert.environment - - ::Clusters::Applications::ScheduleUpdateService.new( - alert.environment.cluster_prometheus_adapter, project).execute - end - - def alert - strong_memoize(:alert) { find_alert(metric) } - end - - def find_alert(metric) - Projects::Prometheus::AlertsFinder - .new(project: project, metric: metric) - .execute - .first - end - - def has_alert? - alert.present? - end + attr_reader :metric, :params end end end diff --git a/app/services/projects/prometheus/metrics/destroy_service.rb b/app/services/projects/prometheus/metrics/destroy_service.rb index 6a46eb5516c..d85499dc4ae 100644 --- a/app/services/projects/prometheus/metrics/destroy_service.rb +++ b/app/services/projects/prometheus/metrics/destroy_service.rb @@ -5,7 +5,6 @@ module Projects module Metrics class DestroyService < Metrics::BaseService def execute - schedule_alert_update if has_alert? metric.destroy end end diff --git a/app/services/projects/prometheus/metrics/update_service.rb b/app/services/projects/prometheus/metrics/update_service.rb deleted file mode 100644 index 9b51f4ab47d..00000000000 --- a/app/services/projects/prometheus/metrics/update_service.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Metrics - class UpdateService < Metrics::BaseService - def execute - metric.update!(params) - schedule_alert_update if requires_alert_update? - metric - end - - private - - def requires_alert_update? - has_alert? && (changing_title? || changing_query?) - end - - def changing_title? - metric.previous_changes.include?(:title) - end - - def changing_query? - metric.previous_changes.include?(:query) - end - end - end - end -end diff --git a/app/services/projects/record_target_platforms_service.rb b/app/services/projects/record_target_platforms_service.rb index 224e16f53b3..664e72e9785 100644 --- a/app/services/projects/record_target_platforms_service.rb +++ b/app/services/projects/record_target_platforms_service.rb @@ -4,26 +4,50 @@ module Projects class RecordTargetPlatformsService < BaseService include Gitlab::Utils::StrongMemoize + def initialize(project, detector_service) + @project = project + @detector_service = detector_service + end + def execute record_target_platforms end private + attr_reader :project, :detector_service + def target_platforms strong_memoize(:target_platforms) do - AppleTargetPlatformDetectorService.new(project).execute + Array(detector_service.new(project).execute) end end def record_target_platforms return unless target_platforms.present? - setting = ::ProjectSetting.find_or_initialize_by(project: project) # rubocop:disable CodeReuse/ActiveRecord - setting.target_platforms = target_platforms - setting.save + project_setting.target_platforms = target_platforms + project_setting.save + + send_build_ios_app_guide_email + + project_setting.target_platforms + end + + def project_setting + @project_setting ||= ::ProjectSetting.find_or_initialize_by(project: project) # rubocop:disable CodeReuse/ActiveRecord + end + + def experiment_candidate? + experiment(:build_ios_app_guide_email, project: project).run + end + + def send_build_ios_app_guide_email + return unless target_platforms.include? :ios + return unless experiment_candidate? - setting.target_platforms + campaign = Users::InProductMarketingEmail::BUILD_IOS_APP_GUIDE + Projects::InProductMarketingCampaignEmailsService.new(project, campaign).execute end end end diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 2ec965fe2f4..c6ea364320f 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -30,6 +30,7 @@ module Projects validate_state! validate_max_size! + validate_public_folder! validate_max_entries! build.artifacts_file.use_file do |artifacts_path| @@ -180,6 +181,10 @@ module Projects end end + def validate_public_folder! + raise InvalidStateError, 'Error: The `public/` folder is missing, or not declared in `.gitlab-ci.yml`.' unless total_size > 0 + end + def entries_count # we're using the full archive and pages daemon needs to read it # so we want the total count from entries, not only "public/" directory diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb index f3ea0967a99..705d23ec704 100644 --- a/app/services/projects/update_remote_mirror_service.rb +++ b/app/services/projects/update_remote_mirror_service.rb @@ -65,7 +65,7 @@ module Projects message += "Error synchronizing LFS files:" message += "\n\n#{lfs_status[:message]}\n\n" - failed = Feature.enabled?(:remote_mirror_fail_on_lfs, project, default_enabled: :yaml) + failed = Feature.enabled?(:remote_mirror_fail_on_lfs, project) end if response.divergent_refs.any? |