diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 11:18:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 11:18:50 +0000 |
commit | 8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 (patch) | |
tree | a77e7fe7a93de11213032ed4ab1f33a3db51b738 /app/models/project.rb | |
parent | 00b35af3db1abfe813a778f643dad221aad51fca (diff) | |
download | gitlab-ce-8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781.tar.gz |
Add latest changes from gitlab-org/gitlab@13-1-stable-ee
Diffstat (limited to 'app/models/project.rb')
-rw-r--r-- | app/models/project.rb | 132 |
1 files changed, 58 insertions, 74 deletions
diff --git a/app/models/project.rb b/app/models/project.rb index c0dd2eb8584..845e9e83e78 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -33,6 +33,7 @@ class Project < ApplicationRecord include OptionallySearch include FromUnion include IgnorableColumns + include Integration extend Gitlab::Cache::RequestCache extend Gitlab::ConfigHelper @@ -95,8 +96,7 @@ class Project < ApplicationRecord after_create :create_project_feature, unless: :project_feature after_create :create_ci_cd_settings, - unless: :ci_cd_settings, - if: proc { ProjectCiCdSetting.available? } + unless: :ci_cd_settings after_create :create_container_expiration_policy, unless: :container_expiration_policy @@ -198,7 +198,7 @@ class Project < ApplicationRecord has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting' has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting' has_one :grafana_integration, inverse_of: :project - has_one :project_setting, ->(project) { where_or_create_by(project: project) }, inverse_of: :project + has_one :project_setting, inverse_of: :project, autosave: true has_one :alerting_setting, inverse_of: :project, class_name: 'Alerting::ProjectAlertingSetting' # Merge Requests for target project should be removed with it @@ -282,7 +282,7 @@ class Project < ApplicationRecord class_name: 'Ci::Pipeline', inverse_of: :project has_many :stages, class_name: 'Ci::Stage', inverse_of: :project - has_many :ci_refs, class_name: 'Ci::Ref' + has_many :ci_refs, class_name: 'Ci::Ref', inverse_of: :project # Ci::Build objects store data on the file system such as artifact files and # build traces. Currently there's no efficient way of removing this data in @@ -291,6 +291,7 @@ class Project < ApplicationRecord has_many :builds, class_name: 'Ci::Build', inverse_of: :project, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :build_trace_section_names, class_name: 'Ci::BuildTraceSectionName' has_many :build_trace_chunks, class_name: 'Ci::BuildTraceChunk', through: :builds, source: :trace_chunks + has_many :build_report_results, class_name: 'Ci::BuildReportResult', inverse_of: :project has_many :job_artifacts, class_name: 'Ci::JobArtifact' has_many :runner_projects, class_name: 'Ci::RunnerProject', inverse_of: :project has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' @@ -328,6 +329,9 @@ class Project < ApplicationRecord has_many :repository_storage_moves, class_name: 'ProjectRepositoryStorageMove' + has_many :webide_pipelines, -> { webide_source }, class_name: 'Ci::Pipeline', inverse_of: :project + has_many :reviews, inverse_of: :project + accepts_nested_attributes_for :variables, allow_destroy: true accepts_nested_attributes_for :project_feature, update_only: true accepts_nested_attributes_for :project_setting, update_only: true @@ -368,9 +372,11 @@ class Project < ApplicationRecord delegate :root_ancestor, to: :namespace, allow_nil: true delegate :last_pipeline, to: :commit, allow_nil: true delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true + delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings delegate :actual_limits, :actual_plan_name, to: :namespace, allow_nil: true + delegate :allow_merge_on_skipped_pipeline, :allow_merge_on_skipped_pipeline?, :allow_merge_on_skipped_pipeline=, to: :project_setting # Validations validates :creator, presence: true, on: :create @@ -442,7 +448,7 @@ class Project < ApplicationRecord scope :archived, -> { where(archived: true) } scope :non_archived, -> { where(archived: false) } scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } - scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } + scope :with_push, -> { joins(:events).merge(Event.pushed_action) } scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') } scope :inc_routes, -> { includes(:route, namespace: :route) } scope :with_statistics, -> { includes(:statistics) } @@ -507,6 +513,11 @@ class Project < ApplicationRecord .where(project_pages_metadata: { project_id: nil }) end + scope :with_api_entity_associations, -> { + preload(:project_feature, :route, :tags, + group: :ip_restrictions, namespace: [:route, :owner]) + } + enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 } chronic_duration_attr :build_timeout_human_readable, :build_timeout, @@ -521,6 +532,10 @@ class Project < ApplicationRecord # Used by Projects::CleanupService to hold a map of rewritten object IDs mount_uploader :bfg_object_map, AttachmentUploader + def self.with_web_entity_associations + preload(:project_feature, :route, :creator, :group, namespace: [:route, :owner]) + end + def self.eager_load_namespace_and_owner includes(namespace: :owner) end @@ -602,8 +617,7 @@ class Project < ApplicationRecord # Searches for a list of projects based on the query given in `query`. # # On PostgreSQL this method uses "ILIKE" to perform a case-insensitive - # search. On MySQL a regular "LIKE" is used as it's already - # case-insensitive. + # search. # # query - The search query as a String. def search(query, include_namespace: false) @@ -713,6 +727,10 @@ class Project < ApplicationRecord super end + def project_setting + super.presence || build_project_setting + end + def all_pipelines if builds_enabled? super @@ -729,6 +747,10 @@ class Project < ApplicationRecord end end + def active_webide_pipelines(user:) + webide_pipelines.running_or_pending.for_user(user) + end + def autoclose_referenced_issues return true if super.nil? @@ -798,10 +820,6 @@ class Project < ApplicationRecord Feature.enabled?(:context_commits, default_enabled: true) end - def jira_issues_import_feature_flag_enabled? - Feature.enabled?(:jira_issue_import, self, default_enabled: true) - end - # LFS and hashed repository storage are required for using Design Management. def design_management_enabled? lfs_enabled? && hashed_storage?(:repository) @@ -889,18 +907,6 @@ class Project < ApplicationRecord latest_jira_import&.status || 'initial' end - def validate_jira_import_settings!(user: nil) - raise Projects::ImportService::Error, _('Jira import feature is disabled.') unless jira_issues_import_feature_flag_enabled? - raise Projects::ImportService::Error, _('Jira integration not configured.') unless jira_service&.active? - - if user - raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless feature_available?(:issues, user) - raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, self) - end - - raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service.test(nil)[:success] - end - def human_import_status_name import_state&.human_status_name || 'none' end @@ -921,17 +927,15 @@ class Project < ApplicationRecord job_id end - # rubocop:disable Gitlab/RailsLogger def log_import_activity(job_id, type: :import) job_type = type.to_s.capitalize if job_id - Rails.logger.info("#{job_type} job scheduled for #{full_path} with job ID #{job_id}.") + Gitlab::AppLogger.info("#{job_type} job scheduled for #{full_path} with job ID #{job_id}.") else - Rails.logger.error("#{job_type} job failed to create for #{full_path}.") + Gitlab::AppLogger.error("#{job_type} job failed to create for #{full_path}.") end end - # rubocop:enable Gitlab/RailsLogger def reset_cache_and_import_attrs run_after_commit do @@ -1007,7 +1011,7 @@ class Project < ApplicationRecord end def jira_import? - import_type == 'jira' && latest_jira_import.present? && jira_issues_import_feature_flag_enabled? + import_type == 'jira' && latest_jira_import.present? end def gitlab_project_import? @@ -1036,7 +1040,7 @@ class Project < ApplicationRecord remote_mirrors.stuck.update_all( update_status: :failed, last_error: _('The remote mirror took to long to complete.'), - last_update_at: Time.now + last_update_at: Time.current ) end @@ -1194,14 +1198,6 @@ class Project < ApplicationRecord get_issue(issue_id) end - def default_issue_tracker - gitlab_issue_tracker_service || create_gitlab_issue_tracker_service - end - - def issues_tracker - external_issue_tracker || default_issue_tracker - end - def external_issue_reference_pattern external_issue_tracker.class.reference_pattern(only_long: issues_enabled?) end @@ -1257,7 +1253,7 @@ class Project < ApplicationRecord available_services_names.map do |service_name| find_or_initialize_service(service_name) - end + end.sort_by(&:title) end def disabled_services @@ -1267,16 +1263,7 @@ class Project < ApplicationRecord def find_or_initialize_service(name) return if disabled_services.include?(name) - service = find_service(services, name) - return service if service - - template = find_service(services_templates, name) - - if template - Service.build_from_template(id, template) - else - public_send("build_#{name}_service") # rubocop:disable GitlabSecurity/PublicSend - end + find_service(services, name) || build_from_instance_or_template(name) || public_send("build_#{name}_service") # rubocop:disable GitlabSecurity/PublicSend end # rubocop: disable CodeReuse/ServiceClass @@ -1781,17 +1768,15 @@ class Project < ApplicationRecord ensure_pages_metadatum.update!(deployed: false) end - # rubocop:disable Gitlab/RailsLogger def write_repository_config(gl_full_path: full_path) # We'd need to keep track of project full path otherwise directory tree # created with hashed storage enabled cannot be usefully imported using # the import rake task. repository.raw_repository.write_config(full_path: gl_full_path) rescue Gitlab::Git::Repository::NoRepository => e - Rails.logger.error("Error writing to .git/config for project #{full_path} (#{id}): #{e.message}.") + Gitlab::AppLogger.error("Error writing to .git/config for project #{full_path} (#{id}): #{e.message}.") nil end - # rubocop:enable Gitlab/RailsLogger def after_import repository.expire_content_cache @@ -1834,17 +1819,15 @@ class Project < ApplicationRecord @pipeline_status ||= Gitlab::Cache::Ci::ProjectPipelineStatus.load_for_project(self) end - # rubocop:disable Gitlab/RailsLogger def add_export_job(current_user:, after_export_strategy: nil, params: {}) job_id = ProjectExportWorker.perform_async(current_user.id, self.id, after_export_strategy, params) if job_id - Rails.logger.info "Export job started for project ID #{self.id} with job ID #{job_id}" + Gitlab::AppLogger.info "Export job started for project ID #{self.id} with job ID #{job_id}" else - Rails.logger.error "Export job failed to start for project ID #{self.id}" + Gitlab::AppLogger.error "Export job failed to start for project ID #{self.id}" end end - # rubocop:enable Gitlab/RailsLogger def import_export_shared @import_export_shared ||= Gitlab::ImportExport::Shared.new(self) @@ -2082,21 +2065,6 @@ class Project < ApplicationRecord end end - def change_repository_storage(new_repository_storage_key) - return if repository_read_only? - return if repository_storage == new_repository_storage_key - - raise ArgumentError unless ::Gitlab.config.repositories.storages.key?(new_repository_storage_key) - - storage_move = repository_storage_moves.create!( - source_storage_name: repository_storage, - destination_storage_name: new_repository_storage_key - ) - storage_move.schedule! - - self.repository_read_only = true - end - def pushes_since_gc Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i } end @@ -2438,12 +2406,32 @@ class Project < ApplicationRecord touch(:last_activity_at, :last_repository_updated_at) end + def metrics_setting + super || build_metrics_setting + end + private def find_service(services, name) services.find { |service| service.to_param == name } end + def build_from_instance_or_template(name) + instance = find_service(services_instances, name) + return Service.build_from_integration(id, instance) if instance + + template = find_service(services_templates, name) + return Service.build_from_integration(id, template) if template + end + + def services_templates + @services_templates ||= Service.templates + end + + def services_instances + @services_instances ||= Service.instances + end + def closest_namespace_setting(name) namespace.closest_setting(name) end @@ -2572,10 +2560,6 @@ class Project < ApplicationRecord end end - def services_templates - @services_templates ||= Service.where(template: true) - end - def ensure_pages_metadatum pages_metadatum || create_pages_metadatum! rescue ActiveRecord::RecordNotUnique |