summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/abuse_report.rb2
-rw-r--r--app/models/appearance.rb2
-rw-r--r--app/models/application_record.rb8
-rw-r--r--app/models/application_setting.rb284
-rw-r--r--app/models/application_setting/term.rb2
-rw-r--r--app/models/application_setting_implementation.rb281
-rw-r--r--app/models/audit_event.rb2
-rw-r--r--app/models/award_emoji.rb2
-rw-r--r--app/models/badge.rb2
-rw-r--r--app/models/board.rb2
-rw-r--r--app/models/board_group_recent_visit.rb2
-rw-r--r--app/models/board_project_recent_visit.rb2
-rw-r--r--app/models/broadcast_message.rb4
-rw-r--r--app/models/chat_name.rb2
-rw-r--r--app/models/chat_team.rb2
-rw-r--r--app/models/ci/build.rb32
-rw-r--r--app/models/ci/build_metadata.rb2
-rw-r--r--app/models/ci/build_runner_session.rb2
-rw-r--r--app/models/ci/build_trace_chunk.rb2
-rw-r--r--app/models/ci/build_trace_section.rb2
-rw-r--r--app/models/ci/build_trace_section_name.rb2
-rw-r--r--app/models/ci/group_variable.rb2
-rw-r--r--app/models/ci/job_artifact.rb2
-rw-r--r--app/models/ci/pipeline.rb55
-rw-r--r--app/models/ci/pipeline_chat_data.rb2
-rw-r--r--app/models/ci/pipeline_schedule.rb2
-rw-r--r--app/models/ci/pipeline_schedule_variable.rb2
-rw-r--r--app/models/ci/pipeline_variable.rb2
-rw-r--r--app/models/ci/runner.rb4
-rw-r--r--app/models/ci/runner_namespace.rb2
-rw-r--r--app/models/ci/runner_project.rb2
-rw-r--r--app/models/ci/stage.rb9
-rw-r--r--app/models/ci/trigger.rb2
-rw-r--r--app/models/ci/trigger_request.rb2
-rw-r--r--app/models/ci/variable.rb2
-rw-r--r--app/models/clusters/applications/cert_manager.rb2
-rw-r--r--app/models/clusters/applications/helm.rb2
-rw-r--r--app/models/clusters/applications/ingress.rb2
-rw-r--r--app/models/clusters/applications/jupyter.rb2
-rw-r--r--app/models/clusters/applications/knative.rb6
-rw-r--r--app/models/clusters/applications/prometheus.rb2
-rw-r--r--app/models/clusters/applications/runner.rb19
-rw-r--r--app/models/clusters/cluster.rb19
-rw-r--r--app/models/clusters/group.rb2
-rw-r--r--app/models/clusters/kubernetes_namespace.rb2
-rw-r--r--app/models/clusters/platforms/kubernetes.rb8
-rw-r--r--app/models/clusters/project.rb2
-rw-r--r--app/models/clusters/providers/gcp.rb2
-rw-r--r--app/models/commit_collection.rb35
-rw-r--r--app/models/commit_status.rb23
-rw-r--r--app/models/commit_status_enums.rb3
-rw-r--r--app/models/concerns/atomic_internal_id.rb2
-rw-r--r--app/models/concerns/cache_markdown_field.rb24
-rw-r--r--app/models/concerns/has_status.rb17
-rw-r--r--app/models/concerns/ignorable_column.rb2
-rw-r--r--app/models/concerns/participable.rb2
-rw-r--r--app/models/concerns/reactive_caching.rb2
-rw-r--r--app/models/concerns/sha_attribute.rb2
-rw-r--r--app/models/concerns/strip_attribute.rb2
-rw-r--r--app/models/concerns/token_authenticatable.rb19
-rw-r--r--app/models/container_repository.rb2
-rw-r--r--app/models/conversational_development_index/metric.rb2
-rw-r--r--app/models/deploy_keys_project.rb2
-rw-r--r--app/models/deploy_token.rb2
-rw-r--r--app/models/deployment.rb6
-rw-r--r--app/models/diff_note.rb6
-rw-r--r--app/models/email.rb2
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/epic.rb2
-rw-r--r--app/models/error_tracking/project_error_tracking_setting.rb9
-rw-r--r--app/models/event.rb2
-rw-r--r--app/models/fork_network.rb2
-rw-r--r--app/models/fork_network_member.rb2
-rw-r--r--app/models/gpg_key.rb2
-rw-r--r--app/models/gpg_key_subkey.rb2
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/group_custom_attribute.rb2
-rw-r--r--app/models/hooks/web_hook.rb2
-rw-r--r--app/models/hooks/web_hook_log.rb2
-rw-r--r--app/models/identity.rb2
-rw-r--r--app/models/identity/uniqueness_scopes.rb2
-rw-r--r--app/models/import_export_upload.rb2
-rw-r--r--app/models/internal_id.rb2
-rw-r--r--app/models/issue.rb2
-rw-r--r--app/models/issue/metrics.rb2
-rw-r--r--app/models/issue_assignee.rb2
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/label.rb2
-rw-r--r--app/models/label_link.rb2
-rw-r--r--app/models/label_priority.rb2
-rw-r--r--app/models/lfs_file_lock.rb2
-rw-r--r--app/models/lfs_object.rb2
-rw-r--r--app/models/lfs_objects_project.rb2
-rw-r--r--app/models/list.rb2
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/members/group_member.rb2
-rw-r--r--app/models/merge_request.rb24
-rw-r--r--app/models/merge_request/metrics.rb2
-rw-r--r--app/models/merge_request_assignee.rb6
-rw-r--r--app/models/merge_request_diff.rb174
-rw-r--r--app/models/merge_request_diff_commit.rb2
-rw-r--r--app/models/merge_request_diff_file.rb2
-rw-r--r--app/models/merge_requests_closing_issues.rb2
-rw-r--r--app/models/milestone.rb3
-rw-r--r--app/models/note.rb2
-rw-r--r--app/models/note_diff_file.rb2
-rw-r--r--app/models/notification_setting.rb2
-rw-r--r--app/models/pages_domain.rb2
-rw-r--r--app/models/personal_access_token.rb2
-rw-r--r--app/models/pool_repository.rb2
-rw-r--r--app/models/postgresql/replication_slot.rb2
-rw-r--r--app/models/programming_language.rb2
-rw-r--r--app/models/project.rb58
-rw-r--r--app/models/project_authorization.rb2
-rw-r--r--app/models/project_auto_devops.rb2
-rw-r--r--app/models/project_ci_cd_setting.rb2
-rw-r--r--app/models/project_custom_attribute.rb2
-rw-r--r--app/models/project_daily_statistic.rb2
-rw-r--r--app/models/project_deploy_token.rb2
-rw-r--r--app/models/project_feature.rb2
-rw-r--r--app/models/project_group_link.rb2
-rw-r--r--app/models/project_import_data.rb2
-rw-r--r--app/models/project_import_state.rb2
-rw-r--r--app/models/project_repository.rb2
-rw-r--r--app/models/project_services/kubernetes_service.rb4
-rw-r--r--app/models/project_statistics.rb2
-rw-r--r--app/models/project_wiki.rb6
-rw-r--r--app/models/prometheus_metric.rb2
-rw-r--r--app/models/protected_branch.rb2
-rw-r--r--app/models/protected_branch/merge_access_level.rb2
-rw-r--r--app/models/protected_branch/push_access_level.rb2
-rw-r--r--app/models/protected_tag.rb2
-rw-r--r--app/models/protected_tag/create_access_level.rb2
-rw-r--r--app/models/push_event_payload.rb2
-rw-r--r--app/models/redirect_route.rb2
-rw-r--r--app/models/release.rb2
-rw-r--r--app/models/releases/link.rb2
-rw-r--r--app/models/remote_mirror.rb2
-rw-r--r--app/models/repository.rb8
-rw-r--r--app/models/repository_language.rb2
-rw-r--r--app/models/resource_label_event.rb2
-rw-r--r--app/models/route.rb2
-rw-r--r--app/models/sent_notification.rb2
-rw-r--r--app/models/service.rb2
-rw-r--r--app/models/shard.rb2
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/models/spam_log.rb2
-rw-r--r--app/models/subscription.rb2
-rw-r--r--app/models/suggestion.rb46
-rw-r--r--app/models/system_note_metadata.rb2
-rw-r--r--app/models/term_agreement.rb2
-rw-r--r--app/models/timelog.rb2
-rw-r--r--app/models/todo.rb2
-rw-r--r--app/models/trending_project.rb2
-rw-r--r--app/models/u2f_registration.rb2
-rw-r--r--app/models/upload.rb2
-rw-r--r--app/models/user.rb6
-rw-r--r--app/models/user_agent_detail.rb2
-rw-r--r--app/models/user_callout.rb2
-rw-r--r--app/models/user_custom_attribute.rb2
-rw-r--r--app/models/user_interacted_project.rb2
-rw-r--r--app/models/user_preference.rb2
-rw-r--r--app/models/user_status.rb2
-rw-r--r--app/models/user_synced_attributes_metadata.rb2
-rw-r--r--app/models/users_star_project.rb2
165 files changed, 909 insertions, 565 deletions
diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb
index 1b78fd04ebb..a3a1748142f 100644
--- a/app/models/abuse_report.rb
+++ b/app/models/abuse_report.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AbuseReport < ActiveRecord::Base
+class AbuseReport < ApplicationRecord
include CacheMarkdownField
cache_markdown_field :message, pipeline: :single_line
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index bdee9b2b73c..2815a117f7f 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Appearance < ActiveRecord::Base
+class Appearance < ApplicationRecord
include CacheableAttributes
include CacheMarkdownField
include ObjectStorage::BackgroundMove
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index a3d662d8250..6976185264e 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -7,6 +7,14 @@ class ApplicationRecord < ActiveRecord::Base
where(id: ids)
end
+ def self.id_not_in(ids)
+ where.not(id: ids)
+ end
+
+ def self.pluck_primary_key
+ where(nil).pluck(self.primary_key)
+ end
+
def self.safe_find_or_create_by!(*args)
safe_find_or_create_by(*args).tap do |record|
record.validate! unless record.persisted?
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index cd36c963ee5..9e91e4ab4b9 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -1,26 +1,20 @@
# frozen_string_literal: true
-class ApplicationSetting < ActiveRecord::Base
+class ApplicationSetting < ApplicationRecord
include CacheableAttributes
include CacheMarkdownField
include TokenAuthenticatable
include IgnorableColumn
include ChronicDurationAttribute
- add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption) ? :optional : :required }
+ add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
add_authentication_token_field :health_check_access_token
- DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
- | # or
- \s # any whitespace character
- | # or
- [\r\n] # any number of newline characters
- }x
-
- # Setting a key restriction to `-1` means that all keys of this type are
- # forbidden.
- FORBIDDEN_KEY_VALUE = KeyRestrictionValidator::FORBIDDEN
- SUPPORTED_KEY_TYPES = %i[rsa dsa ecdsa ed25519].freeze
+ # Include here so it can override methods from
+ # `add_authentication_token_field`
+ # We don't prepend for now because otherwise we'll need to
+ # fix a lot of tests using allow_any_instance_of
+ include ApplicationSettingImplementation
serialize :restricted_visibility_levels # rubocop:disable Cop/ActiveRecordSerialize
serialize :import_sources # rubocop:disable Cop/ActiveRecordSerialize
@@ -42,8 +36,6 @@ class ApplicationSetting < ActiveRecord::Base
cache_markdown_field :shared_runners_text, pipeline: :plain_markdown
cache_markdown_field :after_sign_up_text
- attr_accessor :domain_whitelist_raw, :domain_blacklist_raw
-
default_value_for :id, 1
chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
@@ -231,266 +223,4 @@ class ApplicationSetting < ActiveRecord::Base
reset_memoized_terms
end
after_commit :expire_performance_bar_allowed_user_ids_cache, if: -> { previous_changes.key?('performance_bar_allowed_group_id') }
-
- def self.defaults
- {
- after_sign_up_text: nil,
- akismet_enabled: false,
- allow_local_requests_from_hooks_and_services: false,
- authorized_keys_enabled: true, # TODO default to false if the instance is configured to use AuthorizedKeysCommand
- container_registry_token_expire_delay: 5,
- default_artifacts_expire_in: '30 days',
- default_branch_protection: Settings.gitlab['default_branch_protection'],
- default_group_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- default_projects_limit: Settings.gitlab['default_projects_limit'],
- default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- disabled_oauth_sign_in_sources: [],
- domain_whitelist: Settings.gitlab['domain_whitelist'],
- dsa_key_restriction: 0,
- ecdsa_key_restriction: 0,
- ed25519_key_restriction: 0,
- first_day_of_week: 0,
- gitaly_timeout_default: 55,
- gitaly_timeout_fast: 10,
- gitaly_timeout_medium: 30,
- gravatar_enabled: Settings.gravatar['enabled'],
- help_page_hide_commercial_content: false,
- help_page_text: nil,
- hide_third_party_offers: false,
- housekeeping_bitmaps_enabled: true,
- housekeeping_enabled: true,
- housekeeping_full_repack_period: 50,
- housekeeping_gc_period: 200,
- housekeeping_incremental_repack_period: 10,
- import_sources: Settings.gitlab['import_sources'],
- max_artifacts_size: Settings.artifacts['max_size'],
- max_attachment_size: Settings.gitlab['max_attachment_size'],
- mirror_available: true,
- password_authentication_enabled_for_git: true,
- password_authentication_enabled_for_web: Settings.gitlab['signin_enabled'],
- performance_bar_allowed_group_id: nil,
- rsa_key_restriction: 0,
- plantuml_enabled: false,
- plantuml_url: nil,
- polling_interval_multiplier: 1,
- project_export_enabled: true,
- recaptcha_enabled: false,
- repository_checks_enabled: true,
- repository_storages: ['default'],
- require_two_factor_authentication: false,
- restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
- session_expire_delay: Settings.gitlab['session_expire_delay'],
- send_user_confirmation_email: false,
- shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
- shared_runners_text: nil,
- sign_in_text: nil,
- signup_enabled: Settings.gitlab['signup_enabled'],
- terminal_max_session_time: 0,
- throttle_authenticated_api_enabled: false,
- throttle_authenticated_api_period_in_seconds: 3600,
- throttle_authenticated_api_requests_per_period: 7200,
- throttle_authenticated_web_enabled: false,
- throttle_authenticated_web_period_in_seconds: 3600,
- throttle_authenticated_web_requests_per_period: 7200,
- throttle_unauthenticated_enabled: false,
- throttle_unauthenticated_period_in_seconds: 3600,
- throttle_unauthenticated_requests_per_period: 3600,
- two_factor_grace_period: 48,
- unique_ips_limit_enabled: false,
- unique_ips_limit_per_user: 10,
- unique_ips_limit_time_window: 3600,
- usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
- instance_statistics_visibility_private: false,
- user_default_external: false,
- user_default_internal_regex: nil,
- user_show_add_ssh_key_message: true,
- usage_stats_set_by_user_id: nil,
- diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
- commit_email_hostname: default_commit_email_hostname,
- protected_ci_variables: false,
- local_markdown_version: 0
- }
- end
-
- def self.default_commit_email_hostname
- "users.noreply.#{Gitlab.config.gitlab.host}"
- end
-
- def self.create_from_defaults
- build_from_defaults.tap(&:save)
- end
-
- def self.human_attribute_name(attr, _options = {})
- if attr == :default_artifacts_expire_in
- 'Default artifacts expiration'
- else
- super
- end
- end
-
- def home_page_url_column_exists?
- ::Gitlab::Database.cached_column_exists?(:application_settings, :home_page_url)
- end
-
- def help_page_support_url_column_exists?
- ::Gitlab::Database.cached_column_exists?(:application_settings, :help_page_support_url)
- end
-
- def disabled_oauth_sign_in_sources=(sources)
- sources = (sources || []).map(&:to_s) & Devise.omniauth_providers.map(&:to_s)
- super(sources)
- end
-
- def domain_whitelist_raw
- self.domain_whitelist&.join("\n")
- end
-
- def domain_blacklist_raw
- self.domain_blacklist&.join("\n")
- end
-
- def domain_whitelist_raw=(values)
- self.domain_whitelist = []
- self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
- self.domain_whitelist.reject! { |d| d.empty? }
- self.domain_whitelist
- end
-
- def domain_blacklist_raw=(values)
- self.domain_blacklist = []
- self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR)
- self.domain_blacklist.reject! { |d| d.empty? }
- self.domain_blacklist
- end
-
- def domain_blacklist_file=(file)
- self.domain_blacklist_raw = file.read
- end
-
- def repository_storages
- Array(read_attribute(:repository_storages))
- end
-
- def commit_email_hostname
- super.presence || self.class.default_commit_email_hostname
- end
-
- def default_project_visibility=(level)
- super(Gitlab::VisibilityLevel.level_value(level))
- end
-
- def default_snippet_visibility=(level)
- super(Gitlab::VisibilityLevel.level_value(level))
- end
-
- def default_group_visibility=(level)
- super(Gitlab::VisibilityLevel.level_value(level))
- end
-
- def restricted_visibility_levels=(levels)
- super(levels&.map { |level| Gitlab::VisibilityLevel.level_value(level) })
- end
-
- def strip_sentry_values
- sentry_dsn.strip! if sentry_dsn.present?
- clientside_sentry_dsn.strip! if clientside_sentry_dsn.present?
- end
-
- def performance_bar_allowed_group
- Group.find_by_id(performance_bar_allowed_group_id)
- end
-
- # Return true if the Performance Bar is enabled for a given group
- def performance_bar_enabled
- performance_bar_allowed_group_id.present?
- end
-
- # Choose one of the available repository storage options. Currently all have
- # equal weighting.
- def pick_repository_storage
- repository_storages.sample
- end
-
- def runners_registration_token
- ensure_runners_registration_token!
- end
-
- def health_check_access_token
- ensure_health_check_access_token!
- end
-
- def usage_ping_can_be_configured?
- Settings.gitlab.usage_ping_enabled
- end
-
- def usage_ping_enabled
- usage_ping_can_be_configured? && super
- end
-
- def allowed_key_types
- SUPPORTED_KEY_TYPES.select do |type|
- key_restriction_for(type) != FORBIDDEN_KEY_VALUE
- end
- end
-
- def key_restriction_for(type)
- attr_name = "#{type}_key_restriction"
-
- has_attribute?(attr_name) ? public_send(attr_name) : FORBIDDEN_KEY_VALUE # rubocop:disable GitlabSecurity/PublicSend
- end
-
- def allow_signup?
- signup_enabled? && password_authentication_enabled_for_web?
- end
-
- def password_authentication_enabled?
- password_authentication_enabled_for_web? || password_authentication_enabled_for_git?
- end
-
- def user_default_internal_regex_enabled?
- user_default_external? && user_default_internal_regex.present?
- end
-
- def user_default_internal_regex_instance
- Regexp.new(user_default_internal_regex, Regexp::IGNORECASE)
- end
-
- delegate :terms, to: :latest_terms, allow_nil: true
- def latest_terms
- @latest_terms ||= Term.latest
- end
-
- def reset_memoized_terms
- @latest_terms = nil
- latest_terms
- end
-
- def archive_builds_older_than
- archive_builds_in_seconds.seconds.ago if archive_builds_in_seconds
- end
-
- private
-
- def ensure_uuid!
- return if uuid?
-
- self.uuid = SecureRandom.uuid
- end
-
- def check_repository_storages
- invalid = repository_storages - Gitlab.config.repositories.storages.keys
- errors.add(:repository_storages, "can't include: #{invalid.join(", ")}") unless
- invalid.empty?
- end
-
- def terms_exist
- return unless enforce_terms?
-
- errors.add(:terms, "You need to set terms to be enforced") unless terms.present?
- end
-
- def expire_performance_bar_allowed_user_ids_cache
- Gitlab::PerformanceBar.expire_allowed_user_ids_cache
- end
end
diff --git a/app/models/application_setting/term.rb b/app/models/application_setting/term.rb
index 498701ba22b..723540c9b91 100644
--- a/app/models/application_setting/term.rb
+++ b/app/models/application_setting/term.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class ApplicationSetting
- class Term < ActiveRecord::Base
+ class Term < ApplicationRecord
include CacheMarkdownField
has_many :term_agreements
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
new file mode 100644
index 00000000000..265aa1d4965
--- /dev/null
+++ b/app/models/application_setting_implementation.rb
@@ -0,0 +1,281 @@
+# frozen_string_literal: true
+
+module ApplicationSettingImplementation
+ extend ActiveSupport::Concern
+
+ DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
+ | # or
+ \s # any whitespace character
+ | # or
+ [\r\n] # any number of newline characters
+ }x
+
+ # Setting a key restriction to `-1` means that all keys of this type are
+ # forbidden.
+ FORBIDDEN_KEY_VALUE = KeyRestrictionValidator::FORBIDDEN
+ SUPPORTED_KEY_TYPES = %i[rsa dsa ecdsa ed25519].freeze
+
+ class_methods do
+ def defaults
+ {
+ after_sign_up_text: nil,
+ akismet_enabled: false,
+ allow_local_requests_from_hooks_and_services: false,
+ authorized_keys_enabled: true, # TODO default to false if the instance is configured to use AuthorizedKeysCommand
+ container_registry_token_expire_delay: 5,
+ default_artifacts_expire_in: '30 days',
+ default_branch_protection: Settings.gitlab['default_branch_protection'],
+ default_group_visibility: Settings.gitlab.default_projects_features['visibility_level'],
+ default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
+ default_projects_limit: Settings.gitlab['default_projects_limit'],
+ default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
+ disabled_oauth_sign_in_sources: [],
+ domain_whitelist: Settings.gitlab['domain_whitelist'],
+ dsa_key_restriction: 0,
+ ecdsa_key_restriction: 0,
+ ed25519_key_restriction: 0,
+ first_day_of_week: 0,
+ gitaly_timeout_default: 55,
+ gitaly_timeout_fast: 10,
+ gitaly_timeout_medium: 30,
+ gravatar_enabled: Settings.gravatar['enabled'],
+ help_page_hide_commercial_content: false,
+ help_page_text: nil,
+ hide_third_party_offers: false,
+ housekeeping_bitmaps_enabled: true,
+ housekeeping_enabled: true,
+ housekeeping_full_repack_period: 50,
+ housekeeping_gc_period: 200,
+ housekeeping_incremental_repack_period: 10,
+ import_sources: Settings.gitlab['import_sources'],
+ max_artifacts_size: Settings.artifacts['max_size'],
+ max_attachment_size: Settings.gitlab['max_attachment_size'],
+ mirror_available: true,
+ password_authentication_enabled_for_git: true,
+ password_authentication_enabled_for_web: Settings.gitlab['signin_enabled'],
+ performance_bar_allowed_group_id: nil,
+ rsa_key_restriction: 0,
+ plantuml_enabled: false,
+ plantuml_url: nil,
+ polling_interval_multiplier: 1,
+ project_export_enabled: true,
+ recaptcha_enabled: false,
+ repository_checks_enabled: true,
+ repository_storages: ['default'],
+ require_two_factor_authentication: false,
+ restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
+ session_expire_delay: Settings.gitlab['session_expire_delay'],
+ send_user_confirmation_email: false,
+ shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
+ shared_runners_text: nil,
+ sign_in_text: nil,
+ signup_enabled: Settings.gitlab['signup_enabled'],
+ terminal_max_session_time: 0,
+ throttle_authenticated_api_enabled: false,
+ throttle_authenticated_api_period_in_seconds: 3600,
+ throttle_authenticated_api_requests_per_period: 7200,
+ throttle_authenticated_web_enabled: false,
+ throttle_authenticated_web_period_in_seconds: 3600,
+ throttle_authenticated_web_requests_per_period: 7200,
+ throttle_unauthenticated_enabled: false,
+ throttle_unauthenticated_period_in_seconds: 3600,
+ throttle_unauthenticated_requests_per_period: 3600,
+ two_factor_grace_period: 48,
+ unique_ips_limit_enabled: false,
+ unique_ips_limit_per_user: 10,
+ unique_ips_limit_time_window: 3600,
+ usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
+ instance_statistics_visibility_private: false,
+ user_default_external: false,
+ user_default_internal_regex: nil,
+ user_show_add_ssh_key_message: true,
+ usage_stats_set_by_user_id: nil,
+ diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
+ commit_email_hostname: default_commit_email_hostname,
+ protected_ci_variables: false,
+ local_markdown_version: 0
+ }
+ end
+
+ def default_commit_email_hostname
+ "users.noreply.#{Gitlab.config.gitlab.host}"
+ end
+
+ def create_from_defaults
+ build_from_defaults.tap(&:save)
+ end
+
+ def human_attribute_name(attr, _options = {})
+ if attr == :default_artifacts_expire_in
+ 'Default artifacts expiration'
+ else
+ super
+ end
+ end
+ end
+
+ def home_page_url_column_exists?
+ ::Gitlab::Database.cached_column_exists?(:application_settings, :home_page_url)
+ end
+
+ def help_page_support_url_column_exists?
+ ::Gitlab::Database.cached_column_exists?(:application_settings, :help_page_support_url)
+ end
+
+ def disabled_oauth_sign_in_sources=(sources)
+ sources = (sources || []).map(&:to_s) & Devise.omniauth_providers.map(&:to_s)
+ super(sources)
+ end
+
+ def domain_whitelist_raw
+ self.domain_whitelist&.join("\n")
+ end
+
+ def domain_blacklist_raw
+ self.domain_blacklist&.join("\n")
+ end
+
+ def domain_whitelist_raw=(values)
+ self.domain_whitelist = []
+ self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
+ self.domain_whitelist.reject! { |d| d.empty? }
+ self.domain_whitelist
+ end
+
+ def domain_blacklist_raw=(values)
+ self.domain_blacklist = []
+ self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR)
+ self.domain_blacklist.reject! { |d| d.empty? }
+ self.domain_blacklist
+ end
+
+ def domain_blacklist_file=(file)
+ self.domain_blacklist_raw = file.read
+ end
+
+ def repository_storages
+ Array(read_attribute(:repository_storages))
+ end
+
+ def commit_email_hostname
+ super.presence || self.class.default_commit_email_hostname
+ end
+
+ def default_project_visibility=(level)
+ super(Gitlab::VisibilityLevel.level_value(level))
+ end
+
+ def default_snippet_visibility=(level)
+ super(Gitlab::VisibilityLevel.level_value(level))
+ end
+
+ def default_group_visibility=(level)
+ super(Gitlab::VisibilityLevel.level_value(level))
+ end
+
+ def restricted_visibility_levels=(levels)
+ super(levels&.map { |level| Gitlab::VisibilityLevel.level_value(level) })
+ end
+
+ def strip_sentry_values
+ sentry_dsn.strip! if sentry_dsn.present?
+ clientside_sentry_dsn.strip! if clientside_sentry_dsn.present?
+ end
+
+ def performance_bar_allowed_group
+ Group.find_by_id(performance_bar_allowed_group_id)
+ end
+
+ # Return true if the Performance Bar is enabled for a given group
+ def performance_bar_enabled
+ performance_bar_allowed_group_id.present?
+ end
+
+ # Choose one of the available repository storage options. Currently all have
+ # equal weighting.
+ def pick_repository_storage
+ repository_storages.sample
+ end
+
+ def runners_registration_token
+ ensure_runners_registration_token!
+ end
+
+ def health_check_access_token
+ ensure_health_check_access_token!
+ end
+
+ def usage_ping_can_be_configured?
+ Settings.gitlab.usage_ping_enabled
+ end
+
+ def usage_ping_enabled
+ usage_ping_can_be_configured? && super
+ end
+
+ def allowed_key_types
+ SUPPORTED_KEY_TYPES.select do |type|
+ key_restriction_for(type) != FORBIDDEN_KEY_VALUE
+ end
+ end
+
+ def key_restriction_for(type)
+ attr_name = "#{type}_key_restriction"
+
+ has_attribute?(attr_name) ? public_send(attr_name) : FORBIDDEN_KEY_VALUE # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def allow_signup?
+ signup_enabled? && password_authentication_enabled_for_web?
+ end
+
+ def password_authentication_enabled?
+ password_authentication_enabled_for_web? || password_authentication_enabled_for_git?
+ end
+
+ def user_default_internal_regex_enabled?
+ user_default_external? && user_default_internal_regex.present?
+ end
+
+ def user_default_internal_regex_instance
+ Regexp.new(user_default_internal_regex, Regexp::IGNORECASE)
+ end
+
+ delegate :terms, to: :latest_terms, allow_nil: true
+ def latest_terms
+ @latest_terms ||= ApplicationSetting::Term.latest
+ end
+
+ def reset_memoized_terms
+ @latest_terms = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ latest_terms
+ end
+
+ def archive_builds_older_than
+ archive_builds_in_seconds.seconds.ago if archive_builds_in_seconds
+ end
+
+ private
+
+ def ensure_uuid!
+ return if uuid?
+
+ self.uuid = SecureRandom.uuid
+ end
+
+ def check_repository_storages
+ invalid = repository_storages - Gitlab.config.repositories.storages.keys
+ errors.add(:repository_storages, "can't include: #{invalid.join(", ")}") unless
+ invalid.empty?
+ end
+
+ def terms_exist
+ return unless enforce_terms?
+
+ errors.add(:terms, "You need to set terms to be enforced") unless terms.present?
+ end
+
+ def expire_performance_bar_allowed_user_ids_cache
+ Gitlab::PerformanceBar.expire_allowed_user_ids_cache
+ end
+end
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 8508c88d406..6ef2914ac11 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AuditEvent < ActiveRecord::Base
+class AuditEvent < ApplicationRecord
serialize :details, Hash # rubocop:disable Cop/ActiveRecordSerialize
belongs_to :user, foreign_key: :author_id
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb
index ddc516ccb60..e26162f6151 100644
--- a/app/models/award_emoji.rb
+++ b/app/models/award_emoji.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AwardEmoji < ActiveRecord::Base
+class AwardEmoji < ApplicationRecord
DOWNVOTE_NAME = "thumbsdown".freeze
UPVOTE_NAME = "thumbsup".freeze
diff --git a/app/models/badge.rb b/app/models/badge.rb
index f016654206b..a244ed473de 100644
--- a/app/models/badge.rb
+++ b/app/models/badge.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Badge < ActiveRecord::Base
+class Badge < ApplicationRecord
include FromUnion
# This structure sets the placeholders that the urls
diff --git a/app/models/board.rb b/app/models/board.rb
index 758a71d6903..e08db764f65 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Board < ActiveRecord::Base
+class Board < ApplicationRecord
belongs_to :group
belongs_to :project
diff --git a/app/models/board_group_recent_visit.rb b/app/models/board_group_recent_visit.rb
index f5b75270595..2f1cd830791 100644
--- a/app/models/board_group_recent_visit.rb
+++ b/app/models/board_group_recent_visit.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# Tracks which boards in a specific group a user has visited
-class BoardGroupRecentVisit < ActiveRecord::Base
+class BoardGroupRecentVisit < ApplicationRecord
belongs_to :user
belongs_to :group
belongs_to :board
diff --git a/app/models/board_project_recent_visit.rb b/app/models/board_project_recent_visit.rb
index 2a1b14b3ae0..236d88e909c 100644
--- a/app/models/board_project_recent_visit.rb
+++ b/app/models/board_project_recent_visit.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# Tracks which boards in a specific project a user has visited
-class BoardProjectRecentVisit < ActiveRecord::Base
+class BoardProjectRecentVisit < ApplicationRecord
belongs_to :user
belongs_to :project
belongs_to :board
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 2d237383e60..18fe2a9624f 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-class BroadcastMessage < ActiveRecord::Base
+class BroadcastMessage < ApplicationRecord
include CacheMarkdownField
include Sortable
- cache_markdown_field :message, pipeline: :broadcast_message
+ cache_markdown_field :message, pipeline: :broadcast_message, whitelisted: true
validates :message, presence: true
validates :starts_at, presence: true
diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb
index 03b0af53046..0041595baba 100644
--- a/app/models/chat_name.rb
+++ b/app/models/chat_name.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ChatName < ActiveRecord::Base
+class ChatName < ApplicationRecord
LAST_USED_AT_INTERVAL = 1.hour
belongs_to :service
diff --git a/app/models/chat_team.rb b/app/models/chat_team.rb
index 4e724f9adf7..52b5a7b4a91 100644
--- a/app/models/chat_team.rb
+++ b/app/models/chat_team.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ChatTeam < ActiveRecord::Base
+class ChatTeam < ApplicationRecord
validates :team_id, presence: true
validates :namespace, uniqueness: true
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index a629db82c19..1bd517641ac 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -26,7 +26,8 @@ module Ci
belongs_to :erased_by, class_name: 'User'
RUNNER_FEATURES = {
- upload_multiple_artifacts: -> (build) { build.publishes_artifacts_reports? }
+ upload_multiple_artifacts: -> (build) { build.publishes_artifacts_reports? },
+ refspecs: -> (build) { build.merge_request_ref? }
}.freeze
has_one :deployment, as: :deployable, class_name: 'Deployment'
@@ -47,7 +48,8 @@ module Ci
delegate :terminal_specification, to: :runner_session, allow_nil: true
delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true
- delegate :merge_request_event?, to: :pipeline
+ delegate :merge_request_event?, :merge_request_ref?,
+ :legacy_detached_merge_request_pipeline?, to: :pipeline
##
# Since Gitlab 11.5, deployments records started being created right after
@@ -172,6 +174,10 @@ module Ci
end
state_machine :status do
+ event :enqueue do
+ transition [:created, :skipped, :manual, :scheduled] => :preparing, if: :any_unmet_prerequisites?
+ end
+
event :actionize do
transition created: :manual
end
@@ -185,8 +191,12 @@ module Ci
end
event :enqueue_scheduled do
+ transition scheduled: :preparing, if: ->(build) do
+ build.scheduled_at&.past? && build.any_unmet_prerequisites?
+ end
+
transition scheduled: :pending, if: ->(build) do
- build.scheduled_at && build.scheduled_at < Time.now
+ build.scheduled_at&.past? && !build.any_unmet_prerequisites?
end
end
@@ -204,6 +214,12 @@ module Ci
end
end
+ after_transition any => [:preparing] do |build|
+ build.run_after_commit do
+ Ci::BuildPrepareWorker.perform_async(id)
+ end
+ end
+
after_transition any => [:pending] do |build|
build.run_after_commit do
BuildQueueWorker.perform_async(id)
@@ -355,6 +371,16 @@ module Ci
!retried?
end
+ def any_unmet_prerequisites?
+ return false unless Feature.enabled?(:ci_preparing_state, default_enabled: true)
+
+ prerequisites.present?
+ end
+
+ def prerequisites
+ Gitlab::Ci::Build::Prerequisite::Factory.new(self).unmet
+ end
+
def expanded_environment_name
return unless has_environment?
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index cd8eb774cf5..f281cbd1d6f 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -3,7 +3,7 @@
module Ci
# The purpose of this class is to store Build related data that can be disposed.
# Data that should be persisted forever, should be stored with Ci::Build model.
- class BuildMetadata < ActiveRecord::Base
+ class BuildMetadata < ApplicationRecord
extend Gitlab::Ci::Model
include Presentable
include ChronicDurationAttribute
diff --git a/app/models/ci/build_runner_session.rb b/app/models/ci/build_runner_session.rb
index 457d7eeab6a..061eff090f5 100644
--- a/app/models/ci/build_runner_session.rb
+++ b/app/models/ci/build_runner_session.rb
@@ -3,7 +3,7 @@
module Ci
# The purpose of this class is to store Build related runner session.
# Data will be removed after transitioning from running to any state.
- class BuildRunnerSession < ActiveRecord::Base
+ class BuildRunnerSession < ApplicationRecord
extend Gitlab::Ci::Model
self.table_name = 'ci_builds_runner_session'
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 75017f224a0..0a7a0e0772b 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class BuildTraceChunk < ActiveRecord::Base
+ class BuildTraceChunk < ApplicationRecord
include FastDestroyAll
include ::Gitlab::ExclusiveLeaseHelpers
extend Gitlab::Ci::Model
diff --git a/app/models/ci/build_trace_section.rb b/app/models/ci/build_trace_section.rb
index a4bee59c83b..8be42eb48d6 100644
--- a/app/models/ci/build_trace_section.rb
+++ b/app/models/ci/build_trace_section.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class BuildTraceSection < ActiveRecord::Base
+ class BuildTraceSection < ApplicationRecord
extend Gitlab::Ci::Model
belongs_to :build, class_name: 'Ci::Build'
diff --git a/app/models/ci/build_trace_section_name.rb b/app/models/ci/build_trace_section_name.rb
index cbdf3c4b673..c065cfea14e 100644
--- a/app/models/ci/build_trace_section_name.rb
+++ b/app/models/ci/build_trace_section_name.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class BuildTraceSectionName < ActiveRecord::Base
+ class BuildTraceSectionName < ApplicationRecord
extend Gitlab::Ci::Model
belongs_to :project
diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb
index 323ff560564..0e50265c7ba 100644
--- a/app/models/ci/group_variable.rb
+++ b/app/models/ci/group_variable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class GroupVariable < ActiveRecord::Base
+ class GroupVariable < ApplicationRecord
extend Gitlab::Ci::Model
include HasVariable
include Presentable
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 789bb293811..99512a7c1dd 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class JobArtifact < ActiveRecord::Base
+ class JobArtifact < ApplicationRecord
include AfterCommitQueue
include ObjectStorage::BackgroundMove
extend Gitlab::Ci::Model
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index adffdc0355e..abac16a138d 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class Pipeline < ActiveRecord::Base
+ class Pipeline < ApplicationRecord
extend Gitlab::Ci::Model
include HasStatus
include Importable
@@ -82,10 +82,14 @@ module Ci
state_machine :status, initial: :created do
event :enqueue do
- transition [:created, :skipped, :scheduled] => :pending
+ transition [:created, :preparing, :skipped, :scheduled] => :pending
transition [:success, :failed, :canceled] => :running
end
+ event :prepare do
+ transition any - [:preparing] => :preparing
+ end
+
event :run do
transition any - [:running] => :running
end
@@ -118,7 +122,7 @@ module Ci
# Do not add any operations to this state_machine
# Create a separate worker for each new operation
- before_transition [:created, :pending] => :running do |pipeline|
+ before_transition [:created, :preparing, :pending] => :running do |pipeline|
pipeline.started_at = Time.now
end
@@ -141,7 +145,7 @@ module Ci
end
end
- after_transition [:created, :pending] => :running do |pipeline|
+ after_transition [:created, :preparing, :pending] => :running do |pipeline|
pipeline.run_after_commit { PipelineMetricsWorker.perform_async(pipeline.id) }
end
@@ -149,7 +153,7 @@ module Ci
pipeline.run_after_commit { PipelineMetricsWorker.perform_async(pipeline.id) }
end
- after_transition [:created, :pending, :running] => :success do |pipeline|
+ after_transition [:created, :preparing, :pending, :running] => :success do |pipeline|
pipeline.run_after_commit { PipelineSuccessWorker.perform_async(pipeline.id) }
end
@@ -180,7 +184,7 @@ module Ci
scope :sort_by_merge_request_pipelines, -> do
sql = 'CASE ci_pipelines.source WHEN (?) THEN 0 ELSE 1 END, ci_pipelines.id DESC'
- query = ActiveRecord::Base.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
+ query = ApplicationRecord.send(:sanitize_sql_array, [sql, sources[:merge_request_event]]) # rubocop:disable GitlabSecurity/PublicSend
order(query)
end
@@ -461,9 +465,9 @@ module Ci
end
def latest?
- return false unless ref && commit.present?
+ return false unless git_ref && commit.present?
- project.commit(ref) == commit
+ project.commit(git_ref) == commit
end
def retried
@@ -597,6 +601,7 @@ module Ci
retry_optimistic_lock(self) do
case latest_builds_status.to_s
when 'created' then nil
+ when 'preparing' then prepare
when 'pending' then enqueue
when 'running' then run
when 'success' then succeed
@@ -733,6 +738,10 @@ module Ci
triggered_by_merge_request? && target_sha.nil?
end
+ def legacy_detached_merge_request_pipeline?
+ detached_merge_request_pipeline? && !merge_request_ref?
+ end
+
def merge_request_pipeline?
triggered_by_merge_request? && target_sha.present?
end
@@ -741,6 +750,14 @@ module Ci
triggered_by_merge_request? && target_sha == merge_request.target_branch_sha
end
+ def merge_request_ref?
+ MergeRequest.merge_request_ref?(ref)
+ end
+
+ def matches_sha_or_source_sha?(sha)
+ self.sha == sha || self.source_sha == sha
+ end
+
private
def ci_yaml_from_repo
@@ -772,16 +789,18 @@ module Ci
end
def git_ref
- if merge_request_event?
- ##
- # In the future, we're going to change this ref to
- # merge request's merged reference, such as "refs/merge-requests/:iid/merge".
- # In order to do that, we have to update GitLab-Runner's source pulling
- # logic.
- # See https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1092
- Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
- else
- super
+ strong_memoize(:git_ref) do
+ if merge_request_event?
+ ##
+ # In the future, we're going to change this ref to
+ # merge request's merged reference, such as "refs/merge-requests/:iid/merge".
+ # In order to do that, we have to update GitLab-Runner's source pulling
+ # logic.
+ # See https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1092
+ Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
+ else
+ super
+ end
end
end
diff --git a/app/models/ci/pipeline_chat_data.rb b/app/models/ci/pipeline_chat_data.rb
index 8d37500fec5..65466a8c6f8 100644
--- a/app/models/ci/pipeline_chat_data.rb
+++ b/app/models/ci/pipeline_chat_data.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class PipelineChatData < ActiveRecord::Base
+ class PipelineChatData < ApplicationRecord
self.table_name = 'ci_pipeline_chat_data'
belongs_to :chat_name
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 1c1f203bdb2..1454b2dfb39 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class PipelineSchedule < ActiveRecord::Base
+ class PipelineSchedule < ApplicationRecord
extend Gitlab::Ci::Model
include Importable
include IgnorableColumn
diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb
index fbb9987cab2..be6e5e76c31 100644
--- a/app/models/ci/pipeline_schedule_variable.rb
+++ b/app/models/ci/pipeline_schedule_variable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class PipelineScheduleVariable < ActiveRecord::Base
+ class PipelineScheduleVariable < ApplicationRecord
extend Gitlab::Ci::Model
include HasVariable
diff --git a/app/models/ci/pipeline_variable.rb b/app/models/ci/pipeline_variable.rb
index 08514d6af4e..51a6272e1ff 100644
--- a/app/models/ci/pipeline_variable.rb
+++ b/app/models/ci/pipeline_variable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class PipelineVariable < ActiveRecord::Base
+ class PipelineVariable < ApplicationRecord
extend Gitlab::Ci::Model
include HasVariable
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index ce26ee168ef..07d00503861 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class Runner < ActiveRecord::Base
+ class Runner < ApplicationRecord
extend Gitlab::Ci::Model
include Gitlab::SQL::Pattern
include IgnorableColumn
@@ -10,7 +10,7 @@ module Ci
include FromUnion
include TokenAuthenticatable
- add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption) ? :optional : :required }
+ add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
enum access_level: {
not_protected: 0,
diff --git a/app/models/ci/runner_namespace.rb b/app/models/ci/runner_namespace.rb
index 22b80b98551..6903e8a21a1 100644
--- a/app/models/ci/runner_namespace.rb
+++ b/app/models/ci/runner_namespace.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class RunnerNamespace < ActiveRecord::Base
+ class RunnerNamespace < ApplicationRecord
extend Gitlab::Ci::Model
belongs_to :runner, inverse_of: :runner_namespaces, validate: true
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 1a718d24141..f5bd50dc5a3 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class RunnerProject < ActiveRecord::Base
+ class RunnerProject < ApplicationRecord
extend Gitlab::Ci::Model
belongs_to :runner, inverse_of: :runner_projects
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 0389945191e..b25b0369666 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class Stage < ActiveRecord::Base
+ class Stage < ApplicationRecord
extend Gitlab::Ci::Model
include Importable
include HasStatus
@@ -39,10 +39,14 @@ module Ci
state_machine :status, initial: :created do
event :enqueue do
- transition created: :pending
+ transition [:created, :preparing] => :pending
transition [:success, :failed, :canceled, :skipped] => :running
end
+ event :prepare do
+ transition any - [:preparing] => :preparing
+ end
+
event :run do
transition any - [:running] => :running
end
@@ -76,6 +80,7 @@ module Ci
retry_optimistic_lock(self) do
case statuses.latest.status
when 'created' then nil
+ when 'preparing' then prepare
when 'pending' then enqueue
when 'running' then run
when 'success' then succeed
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 637148c4ce4..8927bb9bc18 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class Trigger < ActiveRecord::Base
+ class Trigger < ApplicationRecord
extend Gitlab::Ci::Model
include IgnorableColumn
include Presentable
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index 0b52c690e93..5daf3dd192d 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class TriggerRequest < ActiveRecord::Base
+ class TriggerRequest < ApplicationRecord
extend Gitlab::Ci::Model
belongs_to :trigger
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index 64836ea4fa4..a77bbef0fca 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Ci
- class Variable < ActiveRecord::Base
+ class Variable < ApplicationRecord
extend Gitlab::Ci::Model
include HasVariable
include Presentable
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index c758577815a..ac0e7eb03bc 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -2,7 +2,7 @@
module Clusters
module Applications
- class CertManager < ActiveRecord::Base
+ class CertManager < ApplicationRecord
VERSION = 'v0.5.2'.freeze
self.table_name = 'clusters_applications_cert_managers'
diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb
index 423071ec024..71aff00077d 100644
--- a/app/models/clusters/applications/helm.rb
+++ b/app/models/clusters/applications/helm.rb
@@ -4,7 +4,7 @@ require 'openssl'
module Clusters
module Applications
- class Helm < ActiveRecord::Base
+ class Helm < ApplicationRecord
self.table_name = 'clusters_applications_helm'
attr_encrypted :ca_key,
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 567f1a2267f..376d54aab2c 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -2,7 +2,7 @@
module Clusters
module Applications
- class Ingress < ActiveRecord::Base
+ class Ingress < ApplicationRecord
VERSION = '1.1.2'.freeze
self.table_name = 'clusters_applications_ingress'
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 7efcc175f9f..f86ff3551a1 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -2,7 +2,7 @@
module Clusters
module Applications
- class Jupyter < ActiveRecord::Base
+ class Jupyter < ApplicationRecord
VERSION = '0.9-174bbd5'.freeze
self.table_name = 'clusters_applications_jupyter'
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 347c3c8c37f..f7e54833296 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -2,8 +2,8 @@
module Clusters
module Applications
- class Knative < ActiveRecord::Base
- VERSION = '0.2.2'.freeze
+ class Knative < ApplicationRecord
+ VERSION = '0.3.0'.freeze
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze
FETCH_IP_ADDRESS_DELAY = 30.seconds
@@ -86,7 +86,7 @@ module Clusters
end
def ingress_service
- cluster.kubeclient.get_service('knative-ingressgateway', 'istio-system')
+ cluster.kubeclient.get_service('istio-ingressgateway', 'istio-system')
end
def services_for(ns: namespace)
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index fa7ce363531..954c29da196 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -2,7 +2,7 @@
module Clusters
module Applications
- class Prometheus < ActiveRecord::Base
+ class Prometheus < ApplicationRecord
include PrometheusAdapter
VERSION = '6.7.3'
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 941551dadaa..8cb81bfcbe4 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -2,8 +2,8 @@
module Clusters
module Applications
- class Runner < ActiveRecord::Base
- VERSION = '0.2.0'.freeze
+ class Runner < ApplicationRecord
+ VERSION = '0.3.0'.freeze
self.table_name = 'clusters_applications_runners'
@@ -13,7 +13,7 @@ module Clusters
include ::Clusters::Concerns::ApplicationData
belongs_to :runner, class_name: 'Ci::Runner', foreign_key: :runner_id
- delegate :project, to: :cluster
+ delegate :project, :group, to: :cluster
default_value_for :version, VERSION
@@ -55,12 +55,17 @@ module Clusters
end
def runner_create_params
- {
+ attributes = {
name: 'kubernetes-cluster',
- runner_type: :project_type,
- tag_list: %w(kubernetes cluster),
- projects: [project]
+ runner_type: cluster.cluster_type,
+ tag_list: %w[kubernetes cluster]
}
+
+ if cluster.group_type?
+ attributes.merge(groups: [group])
+ elsif cluster.project_type?
+ attributes.merge(projects: [project])
+ end
end
def gitlab_url
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 5156c7d7514..4262c03498d 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -1,22 +1,24 @@
# frozen_string_literal: true
module Clusters
- class Cluster < ActiveRecord::Base
+ class Cluster < ApplicationRecord
include Presentable
include Gitlab::Utils::StrongMemoize
include FromUnion
self.table_name = 'clusters'
+ PROJECT_ONLY_APPLICATIONS = {
+ Applications::Jupyter.application_name => Applications::Jupyter,
+ Applications::Knative.application_name => Applications::Knative,
+ Applications::Prometheus.application_name => Applications::Prometheus
+ }.freeze
APPLICATIONS = {
Applications::Helm.application_name => Applications::Helm,
Applications::Ingress.application_name => Applications::Ingress,
Applications::CertManager.application_name => Applications::CertManager,
- Applications::Prometheus.application_name => Applications::Prometheus,
- Applications::Runner.application_name => Applications::Runner,
- Applications::Jupyter.application_name => Applications::Jupyter,
- Applications::Knative.application_name => Applications::Knative
- }.freeze
+ Applications::Runner.application_name => Applications::Runner
+ }.merge(PROJECT_ONLY_APPLICATIONS).freeze
DEFAULT_ENVIRONMENT = '*'.freeze
KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'.freeze
@@ -70,6 +72,7 @@ module Clusters
delegate :external_hostname, to: :application_ingress, prefix: true, allow_nil: true
alias_attribute :base_domain, :domain
+ alias_attribute :provided_by_user?, :user?
enum cluster_type: {
instance_type: 1,
@@ -149,10 +152,6 @@ module Clusters
return platform_kubernetes if kubernetes?
end
- def managed?
- !user?
- end
-
def all_projects
if project_type?
projects
diff --git a/app/models/clusters/group.rb b/app/models/clusters/group.rb
index 2b08a9e47f0..27f39b53579 100644
--- a/app/models/clusters/group.rb
+++ b/app/models/clusters/group.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Clusters
- class Group < ActiveRecord::Base
+ class Group < ApplicationRecord
self.table_name = 'cluster_groups'
belongs_to :cluster, class_name: 'Clusters::Cluster'
diff --git a/app/models/clusters/kubernetes_namespace.rb b/app/models/clusters/kubernetes_namespace.rb
index 7fc75e00cd0..b0c4900546e 100644
--- a/app/models/clusters/kubernetes_namespace.rb
+++ b/app/models/clusters/kubernetes_namespace.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Clusters
- class KubernetesNamespace < ActiveRecord::Base
+ class KubernetesNamespace < ApplicationRecord
include Gitlab::Kubernetes
self.table_name = 'clusters_kubernetes_namespaces'
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index fb2221b601f..2ae141190a8 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -2,7 +2,7 @@
module Clusters
module Platforms
- class Kubernetes < ActiveRecord::Base
+ class Kubernetes < ApplicationRecord
include Gitlab::Kubernetes
include ReactiveCaching
include EnumWithNil
@@ -54,7 +54,7 @@ module Clusters
delegate :project, to: :cluster, allow_nil: true
delegate :enabled?, to: :cluster, allow_nil: true
- delegate :managed?, to: :cluster, allow_nil: true
+ delegate :provided_by_user?, to: :cluster, allow_nil: true
delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
delegate :kubernetes_namespace, to: :cluster
@@ -110,7 +110,7 @@ module Clusters
# short time later
def terminals(environment)
with_reactive_cache do |data|
- pods = filter_by_label(data[:pods], app: environment.slug)
+ pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }.compact
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
end
@@ -219,7 +219,7 @@ module Clusters
end
def prevent_modification
- return unless managed?
+ return if provided_by_user?
if api_url_changed? || token_changed? || ca_pem_changed?
errors.add(:base, _('Cannot modify managed Kubernetes cluster'))
diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb
index 15092b1c9d2..d2b68b3f117 100644
--- a/app/models/clusters/project.rb
+++ b/app/models/clusters/project.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Clusters
- class Project < ActiveRecord::Base
+ class Project < ApplicationRecord
self.table_name = 'cluster_projects'
belongs_to :cluster, class_name: 'Clusters::Cluster'
diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb
index 16b59cd9d14..390748bf252 100644
--- a/app/models/clusters/providers/gcp.rb
+++ b/app/models/clusters/providers/gcp.rb
@@ -2,7 +2,7 @@
module Clusters
module Providers
- class Gcp < ActiveRecord::Base
+ class Gcp < ApplicationRecord
self.table_name = 'cluster_providers_gcp'
belongs_to :cluster, inverse_of: :provider_gcp, class_name: 'Clusters::Cluster'
diff --git a/app/models/commit_collection.rb b/app/models/commit_collection.rb
index 42ec5b5e664..e8df46e1cc3 100644
--- a/app/models/commit_collection.rb
+++ b/app/models/commit_collection.rb
@@ -28,10 +28,43 @@ class CommitCollection
def without_merge_commits
strong_memoize(:without_merge_commits) do
- commits.reject(&:merge_commit?)
+ # `#enrich!` the collection to ensure all commits contain
+ # the necessary parent data
+ enrich!.commits.reject(&:merge_commit?)
end
end
+ def unenriched
+ commits.reject(&:gitaly_commit?)
+ end
+
+ def fully_enriched?
+ unenriched.empty?
+ end
+
+ # Batch load any commits that are not backed by full gitaly data, and
+ # replace them in the collection.
+ def enrich!
+ # A project is needed in order to fetch data from gitaly. Projects
+ # can be absent from commits in certain rare situations (like when
+ # viewing a MR of a deleted fork). In these cases, assume that the
+ # enriched data is not needed.
+ return self if project.blank? || fully_enriched?
+
+ # Batch load full Commits from the repository
+ # and map to a Hash of id => Commit
+ replacements = Hash[unenriched.map do |c|
+ [c.id, Commit.lazy(project, c.id)]
+ end.compact]
+
+ # Replace the commits, keeping the same order
+ @commits = @commits.map do |c|
+ replacements.fetch(c.id, c)
+ end
+
+ self
+ end
+
# Sets the pipeline status for every commit.
#
# Setting this status ahead of time removes the need for running a query for
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 7f6562b63e5..f97dc38dab7 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CommitStatus < ActiveRecord::Base
+class CommitStatus < ApplicationRecord
include HasStatus
include Importable
include AfterCommitQueue
@@ -66,7 +66,10 @@ class CommitStatus < ActiveRecord::Base
end
event :enqueue do
- transition [:created, :skipped, :manual, :scheduled] => :pending
+ # A CommitStatus will never have prerequisites, but this event
+ # is shared by Ci::Build, which cannot progress unless prerequisites
+ # are satisfied.
+ transition [:created, :preparing, :skipped, :manual, :scheduled] => :pending, unless: :any_unmet_prerequisites?
end
event :run do
@@ -74,26 +77,26 @@ class CommitStatus < ActiveRecord::Base
end
event :skip do
- transition [:created, :pending] => :skipped
+ transition [:created, :preparing, :pending] => :skipped
end
event :drop do
- transition [:created, :pending, :running, :scheduled] => :failed
+ transition [:created, :preparing, :pending, :running, :scheduled] => :failed
end
event :success do
- transition [:created, :pending, :running] => :success
+ transition [:created, :preparing, :pending, :running] => :success
end
event :cancel do
- transition [:created, :pending, :running, :manual, :scheduled] => :canceled
+ transition [:created, :preparing, :pending, :running, :manual, :scheduled] => :canceled
end
- before_transition [:created, :skipped, :manual, :scheduled] => :pending do |commit_status|
+ before_transition [:created, :preparing, :skipped, :manual, :scheduled] => :pending do |commit_status|
commit_status.queued_at = Time.now
end
- before_transition [:created, :pending] => :running do |commit_status|
+ before_transition [:created, :preparing, :pending] => :running do |commit_status|
commit_status.started_at = Time.now
end
@@ -180,6 +183,10 @@ class CommitStatus < ActiveRecord::Base
false
end
+ def any_unmet_prerequisites?
+ false
+ end
+
def auto_canceled?
canceled? && auto_canceled_by_id?
end
diff --git a/app/models/commit_status_enums.rb b/app/models/commit_status_enums.rb
index 152105d9429..45e08fa18fe 100644
--- a/app/models/commit_status_enums.rb
+++ b/app/models/commit_status_enums.rb
@@ -14,7 +14,8 @@ module CommitStatusEnums
runner_unsupported: 6,
stale_schedule: 7,
job_execution_timeout: 8,
- archived_failure: 9
+ archived_failure: 9,
+ unmet_prerequisites: 10
}
end
end
diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb
index 4e15b60ccd1..ab3d9e923c0 100644
--- a/app/models/concerns/atomic_internal_id.rb
+++ b/app/models/concerns/atomic_internal_id.rb
@@ -7,7 +7,7 @@
#
# For example, let's generate internal ids for Issue per Project:
# ```
-# class Issue < ActiveRecord::Base
+# class Issue < ApplicationRecord
# has_internal_id :iid, scope: :project, init: ->(s) { s.project.issues.maximum(:iid) }
# end
# ```
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 1a8570b80c3..28ea51d6769 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -7,6 +7,7 @@
# cache_markdown_field :foo
# cache_markdown_field :bar
# cache_markdown_field :baz, pipeline: :single_line
+# cache_markdown_field :baz, whitelisted: true
#
# Corresponding foo_html, bar_html and baz_html fields should exist.
module CacheMarkdownField
@@ -14,7 +15,7 @@ module CacheMarkdownField
# Increment this number every time the renderer changes its output
CACHE_COMMONMARK_VERSION_START = 10
- CACHE_COMMONMARK_VERSION = 14
+ CACHE_COMMONMARK_VERSION = 15
# changes to these attributes cause the cache to be invalidates
INVALIDATED_BY = %w[author project].freeze
@@ -37,7 +38,15 @@ module CacheMarkdownField
end
def html_fields
- markdown_fields.map {|field| html_field(field) }
+ markdown_fields.map { |field| html_field(field) }
+ end
+
+ def html_fields_whitelisted
+ markdown_fields.each_with_object([]) do |field, fields|
+ if @data[field].fetch(:whitelisted, false)
+ fields << html_field(field)
+ end
+ end
end
end
@@ -149,13 +158,18 @@ module CacheMarkdownField
alias_method :attributes_before_markdown_cache, :attributes
def attributes
attrs = attributes_before_markdown_cache
+ html_fields = cached_markdown_fields.html_fields
+ whitelisted = cached_markdown_fields.html_fields_whitelisted
+ exclude_fields = html_fields - whitelisted
- attrs.delete('cached_markdown_version')
-
- cached_markdown_fields.html_fields.each do |field|
+ exclude_fields.each do |field|
attrs.delete(field)
end
+ if whitelisted.empty?
+ attrs.delete('cached_markdown_version')
+ end
+
attrs
end
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 0d2be4c61ab..8882f48c281 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -5,14 +5,14 @@ module HasStatus
DEFAULT_STATUS = 'created'.freeze
BLOCKED_STATUS = %w[manual scheduled].freeze
- AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual scheduled].freeze
+ AVAILABLE_STATUSES = %w[created preparing pending running success failed canceled skipped manual scheduled].freeze
STARTED_STATUSES = %w[running success failed skipped manual scheduled].freeze
- ACTIVE_STATUSES = %w[pending running].freeze
+ ACTIVE_STATUSES = %w[preparing pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
- ORDERED_STATUSES = %w[failed pending running manual scheduled canceled success skipped created].freeze
+ ORDERED_STATUSES = %w[failed preparing pending running manual scheduled canceled success skipped created].freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7,
- scheduled: 8 }.freeze
+ scheduled: 8, preparing: 9 }.freeze
UnknownStatusError = Class.new(StandardError)
@@ -26,6 +26,7 @@ module HasStatus
success = scope_relevant.success.select('count(*)').to_sql
manual = scope_relevant.manual.select('count(*)').to_sql
scheduled = scope_relevant.scheduled.select('count(*)').to_sql
+ preparing = scope_relevant.preparing.select('count(*)').to_sql
pending = scope_relevant.pending.select('count(*)').to_sql
running = scope_relevant.running.select('count(*)').to_sql
skipped = scope_relevant.skipped.select('count(*)').to_sql
@@ -37,12 +38,14 @@ module HasStatus
WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{builds})=(#{success}) THEN 'success'
WHEN (#{builds})=(#{created}) THEN 'created'
+ WHEN (#{builds})=(#{preparing}) THEN 'preparing'
WHEN (#{builds})=(#{success})+(#{skipped}) THEN 'success'
WHEN (#{builds})=(#{success})+(#{skipped})+(#{canceled}) THEN 'canceled'
WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
WHEN (#{running})+(#{pending})>0 THEN 'running'
WHEN (#{manual})>0 THEN 'manual'
WHEN (#{scheduled})>0 THEN 'scheduled'
+ WHEN (#{preparing})>0 THEN 'preparing'
WHEN (#{created})>0 THEN 'running'
ELSE 'failed'
END)"
@@ -70,6 +73,7 @@ module HasStatus
state_machine :status, initial: :created do
state :created, value: 'created'
+ state :preparing, value: 'preparing'
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
@@ -81,6 +85,7 @@ module HasStatus
end
scope :created, -> { where(status: 'created') }
+ scope :preparing, -> { where(status: 'preparing') }
scope :relevant, -> { where(status: AVAILABLE_STATUSES - ['created']) }
scope :running, -> { where(status: 'running') }
scope :pending, -> { where(status: 'pending') }
@@ -90,14 +95,14 @@ module HasStatus
scope :skipped, -> { where(status: 'skipped') }
scope :manual, -> { where(status: 'manual') }
scope :scheduled, -> { where(status: 'scheduled') }
- scope :alive, -> { where(status: [:created, :pending, :running]) }
+ scope :alive, -> { where(status: [:created, :preparing, :pending, :running]) }
scope :created_or_pending, -> { where(status: [:created, :pending]) }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
scope :finished, -> { where(status: [:success, :failed, :canceled]) }
scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) }
scope :cancelable, -> do
- where(status: [:running, :pending, :created, :scheduled])
+ where(status: [:running, :preparing, :pending, :created, :scheduled])
end
end
diff --git a/app/models/concerns/ignorable_column.rb b/app/models/concerns/ignorable_column.rb
index 5c1f7dfcd2a..3bec44dc79b 100644
--- a/app/models/concerns/ignorable_column.rb
+++ b/app/models/concerns/ignorable_column.rb
@@ -5,7 +5,7 @@
#
# Example:
#
-# class User < ActiveRecord::Base
+# class User < ApplicationRecord
# include IgnorableColumn
#
# ignore_column :updated_at
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 614c3242874..b140fca9b83 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -7,7 +7,7 @@
#
# Usage:
#
-# class Issue < ActiveRecord::Base
+# class Issue < ApplicationRecord
# include Participable
#
# # ...
diff --git a/app/models/concerns/reactive_caching.rb b/app/models/concerns/reactive_caching.rb
index d2ead7130e5..1ab3b3ddc46 100644
--- a/app/models/concerns/reactive_caching.rb
+++ b/app/models/concerns/reactive_caching.rb
@@ -7,7 +7,7 @@
#
# Example of use:
#
-# class Foo < ActiveRecord::Base
+# class Foo < ApplicationRecord
# include ReactiveCaching
#
# self.reactive_cache_key = ->(thing) { ["foo", thing.id] }
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index a479bef993c..70ac873a030 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -39,7 +39,7 @@ module ShaAttribute
end
def database_exists?
- ActiveRecord::Base.connection
+ ApplicationRecord.connection
true
rescue
diff --git a/app/models/concerns/strip_attribute.rb b/app/models/concerns/strip_attribute.rb
index c9f5ba7793d..8f6a6244dd3 100644
--- a/app/models/concerns/strip_attribute.rb
+++ b/app/models/concerns/strip_attribute.rb
@@ -6,7 +6,7 @@
#
# Usage:
#
-# class Milestone < ActiveRecord::Base
+# class Milestone < ApplicationRecord
# strip_attributes :title
# end
#
diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb
index f5bb559ceda..8c769be0489 100644
--- a/app/models/concerns/token_authenticatable.rb
+++ b/app/models/concerns/token_authenticatable.rb
@@ -26,34 +26,41 @@ module TokenAuthenticatable
end
end
- define_method(token_field) do
+ mod = token_authenticatable_module
+
+ mod.define_method(token_field) do
strategy.get_token(self)
end
- define_method("set_#{token_field}") do |token|
+ mod.define_method("set_#{token_field}") do |token|
strategy.set_token(self, token)
end
- define_method("ensure_#{token_field}") do
+ mod.define_method("ensure_#{token_field}") do
strategy.ensure_token(self)
end
# Returns a token, but only saves when the database is in read & write mode
- define_method("ensure_#{token_field}!") do
+ mod.define_method("ensure_#{token_field}!") do
strategy.ensure_token!(self)
end
# Resets the token, but only saves when the database is in read & write mode
- define_method("reset_#{token_field}!") do
+ mod.define_method("reset_#{token_field}!") do
strategy.reset_token!(self)
end
- define_method("#{token_field}_matches?") do |other_token|
+ mod.define_method("#{token_field}_matches?") do |other_token|
token = read_attribute(token_field)
token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare(other_token, token)
end
end
+ def token_authenticatable_module
+ @token_authenticatable_module ||=
+ const_set(:TokenAuthenticatable, Module.new).tap(&method(:include))
+ end
+
def token_authenticatable_fields
@token_authenticatable_fields ||= []
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index cf057d774cf..39e12ac2b06 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ContainerRepository < ActiveRecord::Base
+class ContainerRepository < ApplicationRecord
include Gitlab::Utils::StrongMemoize
belongs_to :project
diff --git a/app/models/conversational_development_index/metric.rb b/app/models/conversational_development_index/metric.rb
index c54537572d6..b91123be87e 100644
--- a/app/models/conversational_development_index/metric.rb
+++ b/app/models/conversational_development_index/metric.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module ConversationalDevelopmentIndex
- class Metric < ActiveRecord::Base
+ class Metric < ApplicationRecord
include Presentable
self.table_name = 'conversational_development_index_metrics'
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index 71fd02fac86..15906ed8e06 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class DeployKeysProject < ActiveRecord::Base
+class DeployKeysProject < ApplicationRecord
belongs_to :project
belongs_to :deploy_key, inverse_of: :deploy_keys_projects
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index e3524305346..b0e570f52ba 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class DeployToken < ActiveRecord::Base
+class DeployToken < ApplicationRecord
include Expirable
include TokenAuthenticatable
include PolicyActor
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 811e623b7f7..d847a0a11e4 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Deployment < ActiveRecord::Base
+class Deployment < ApplicationRecord
include AtomicInternalId
include IidRoutes
include AfterCommitQueue
@@ -78,6 +78,10 @@ class Deployment < ActiveRecord::Base
Commit.truncate_sha(sha)
end
+ def cluster
+ project.deployment_platform(environment: environment.name)&.cluster
+ end
+
def last?
self == environment.last_deployment
end
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 805092e527a..feabea9b8ba 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -77,8 +77,8 @@ class DiffNote < Note
def supports_suggestion?
return false unless noteable.supports_suggestion? && on_text?
# We don't want to trigger side-effects of `diff_file` call.
- return false unless file = fetch_diff_file
- return false unless line = file.line_for_position(self.original_position)
+ return false unless file = latest_diff_file
+ return false unless line = file.line_for_position(self.position)
line&.suggestible?
end
@@ -88,7 +88,7 @@ class DiffNote < Note
end
def banzai_render_context(field)
- super.merge(suggestions_filter_enabled: supports_suggestion?)
+ super.merge(project: project, suggestions_filter_enabled: supports_suggestion?)
end
private
diff --git a/app/models/email.rb b/app/models/email.rb
index 7c33c5c7e64..0ddaa049c3b 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Email < ActiveRecord::Base
+class Email < ApplicationRecord
include Sortable
include Gitlab::SQL::Pattern
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 3d909cc8e5c..25373c7a1f7 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Environment < ActiveRecord::Base
+class Environment < ApplicationRecord
include Gitlab::Utils::StrongMemoize
# Used to generate random suffixes for the slug
LETTERS = 'a'..'z'
diff --git a/app/models/epic.rb b/app/models/epic.rb
index ccd10593434..3693db1de33 100644
--- a/app/models/epic.rb
+++ b/app/models/epic.rb
@@ -2,7 +2,7 @@
# Placeholder class for model that is implemented in EE
# It reserves '&' as a reference prefix, but the table does not exists in CE
-class Epic < ActiveRecord::Base
+class Epic < ApplicationRecord
def self.link_reference_pattern
nil
end
diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb
index 1e2bd3bda7f..70954bf8b05 100644
--- a/app/models/error_tracking/project_error_tracking_setting.rb
+++ b/app/models/error_tracking/project_error_tracking_setting.rb
@@ -1,10 +1,13 @@
# frozen_string_literal: true
module ErrorTracking
- class ProjectErrorTrackingSetting < ActiveRecord::Base
+ class ProjectErrorTrackingSetting < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include ReactiveCaching
+ SENTRY_API_ERROR_TYPE_MISSING_KEYS = 'missing_keys_in_sentry_response'
+ SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE = 'non_20x_response_from_sentry'
+
API_URL_PATH_REGEXP = %r{
\A
(?<prefix>/api/0/projects/+)
@@ -90,7 +93,9 @@ module ErrorTracking
{ issues: sentry_client.list_issues(**opts.symbolize_keys) }
end
rescue Sentry::Client::Error => e
- { error: e.message }
+ { error: e.message, error_type: SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE }
+ rescue Sentry::Client::MissingKeysError => e
+ { error: e.message, error_type: SENTRY_API_ERROR_TYPE_MISSING_KEYS }
end
# http://HOST/api/0/projects/ORG/PROJECT
diff --git a/app/models/event.rb b/app/models/event.rb
index 6a35bca72c5..593acf5edfe 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Event < ActiveRecord::Base
+class Event < ApplicationRecord
include Sortable
include IgnorableColumn
include FromUnion
diff --git a/app/models/fork_network.rb b/app/models/fork_network.rb
index 1b9bf93cbbc..0323a8d222a 100644
--- a/app/models/fork_network.rb
+++ b/app/models/fork_network.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ForkNetwork < ActiveRecord::Base
+class ForkNetwork < ApplicationRecord
belongs_to :root_project, class_name: 'Project'
has_many :fork_network_members
has_many :projects, through: :fork_network_members
diff --git a/app/models/fork_network_member.rb b/app/models/fork_network_member.rb
index 36c66f21b0b..f18c306cf91 100644
--- a/app/models/fork_network_member.rb
+++ b/app/models/fork_network_member.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ForkNetworkMember < ActiveRecord::Base
+class ForkNetworkMember < ApplicationRecord
belongs_to :fork_network
belongs_to :project
belongs_to :forked_from_project, class_name: 'Project'
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index 077afffd358..116beac5c2a 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class GpgKey < ActiveRecord::Base
+class GpgKey < ApplicationRecord
KEY_PREFIX = '-----BEGIN PGP PUBLIC KEY BLOCK-----'.freeze
KEY_SUFFIX = '-----END PGP PUBLIC KEY BLOCK-----'.freeze
diff --git a/app/models/gpg_key_subkey.rb b/app/models/gpg_key_subkey.rb
index 440b588bc78..110bf451136 100644
--- a/app/models/gpg_key_subkey.rb
+++ b/app/models/gpg_key_subkey.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class GpgKeySubkey < ActiveRecord::Base
+class GpgKeySubkey < ApplicationRecord
include ShaAttribute
sha_attribute :keyid
diff --git a/app/models/group.rb b/app/models/group.rb
index 495bfe04499..c77586c4cdc 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -56,7 +56,7 @@ class Group < Namespace
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
- add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption) ? :optional : :required }
+ add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
after_create :post_create_hook
after_destroy :post_destroy_hook
diff --git a/app/models/group_custom_attribute.rb b/app/models/group_custom_attribute.rb
index 22f14885657..5ac6e5f2550 100644
--- a/app/models/group_custom_attribute.rb
+++ b/app/models/group_custom_attribute.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class GroupCustomAttribute < ActiveRecord::Base
+class GroupCustomAttribute < ApplicationRecord
belongs_to :group
validates :group, :key, :value, presence: true
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 1a8662db9fb..daf7ff4b771 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class WebHook < ActiveRecord::Base
+class WebHook < ApplicationRecord
include Sortable
attr_encrypted :token,
diff --git a/app/models/hooks/web_hook_log.rb b/app/models/hooks/web_hook_log.rb
index 2d9f7594e8c..cfb1f3ec63b 100644
--- a/app/models/hooks/web_hook_log.rb
+++ b/app/models/hooks/web_hook_log.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class WebHookLog < ActiveRecord::Base
+class WebHookLog < ApplicationRecord
belongs_to :web_hook
serialize :request_headers, Hash # rubocop:disable Cop/ActiveRecordSerialize
diff --git a/app/models/identity.rb b/app/models/identity.rb
index acdde4f296b..8322b9bf35f 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Identity < ActiveRecord::Base
+class Identity < ApplicationRecord
include Sortable
include CaseSensitivity
diff --git a/app/models/identity/uniqueness_scopes.rb b/app/models/identity/uniqueness_scopes.rb
index 674b735903f..ce68371ae87 100644
--- a/app/models/identity/uniqueness_scopes.rb
+++ b/app/models/identity/uniqueness_scopes.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Identity < ActiveRecord::Base
+class Identity < ApplicationRecord
# This module and method are defined in a separate file to allow EE to
# redefine the `scopes` method before it is used in the `Identity` model.
module UniquenessScopes
diff --git a/app/models/import_export_upload.rb b/app/models/import_export_upload.rb
index f0cc5aafcd4..60f5491849a 100644
--- a/app/models/import_export_upload.rb
+++ b/app/models/import_export_upload.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ImportExportUpload < ActiveRecord::Base
+class ImportExportUpload < ApplicationRecord
include WithUploads
include ObjectStorage::BackgroundMove
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index e75c6eb2331..3f2d368a3f2 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -15,7 +15,7 @@
# In order to leverage InternalId for other usages, the idea is to
# * Add `usage` value to enum
# * (Optionally) add columns to `internal_ids` if needed for scope.
-class InternalId < ActiveRecord::Base
+class InternalId < ApplicationRecord
belongs_to :project
belongs_to :namespace
diff --git a/app/models/issue.rb b/app/models/issue.rb
index deab53d25e7..97c6dcc4745 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -2,7 +2,7 @@
require 'carrierwave/orm/activerecord'
-class Issue < ActiveRecord::Base
+class Issue < ApplicationRecord
include AtomicInternalId
include IidRoutes
include Issuable
diff --git a/app/models/issue/metrics.rb b/app/models/issue/metrics.rb
index 0f5ee957ec9..8010cbc3d78 100644
--- a/app/models/issue/metrics.rb
+++ b/app/models/issue/metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Issue::Metrics < ActiveRecord::Base
+class Issue::Metrics < ApplicationRecord
belongs_to :issue
def record!
diff --git a/app/models/issue_assignee.rb b/app/models/issue_assignee.rb
index 400c0256945..fbd9be1fb43 100644
--- a/app/models/issue_assignee.rb
+++ b/app/models/issue_assignee.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class IssueAssignee < ActiveRecord::Base
+class IssueAssignee < ApplicationRecord
belongs_to :issue
belongs_to :assignee, class_name: "User", foreign_key: :user_id
end
diff --git a/app/models/key.rb b/app/models/key.rb
index 8f93418b88b..b097be8cc89 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -2,7 +2,7 @@
require 'digest/md5'
-class Key < ActiveRecord::Base
+class Key < ApplicationRecord
include AfterCommitQueue
include Sortable
diff --git a/app/models/label.rb b/app/models/label.rb
index 96bdb7f17c5..024daeb4fae 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Label < ActiveRecord::Base
+class Label < ApplicationRecord
include CacheMarkdownField
include Referable
include Subscribable
diff --git a/app/models/label_link.rb b/app/models/label_link.rb
index 1d93a55e8e9..ffc0afd8e85 100644
--- a/app/models/label_link.rb
+++ b/app/models/label_link.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class LabelLink < ActiveRecord::Base
+class LabelLink < ApplicationRecord
include Importable
belongs_to :target, polymorphic: true, inverse_of: :label_links # rubocop:disable Cop/PolymorphicAssociations
diff --git a/app/models/label_priority.rb b/app/models/label_priority.rb
index 8ed8bb7577f..8f8f36efbfe 100644
--- a/app/models/label_priority.rb
+++ b/app/models/label_priority.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class LabelPriority < ActiveRecord::Base
+class LabelPriority < ApplicationRecord
belongs_to :project
belongs_to :label
diff --git a/app/models/lfs_file_lock.rb b/app/models/lfs_file_lock.rb
index 431d37e12e9..624b1d02e1a 100644
--- a/app/models/lfs_file_lock.rb
+++ b/app/models/lfs_file_lock.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class LfsFileLock < ActiveRecord::Base
+class LfsFileLock < ApplicationRecord
belongs_to :project
belongs_to :user
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 69c563545bb..e1aac691a64 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class LfsObject < ActiveRecord::Base
+class LfsObject < ApplicationRecord
include AfterCommitQueue
include ObjectStorage::BackgroundMove
diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb
index 353602800d7..f9afb18c1d7 100644
--- a/app/models/lfs_objects_project.rb
+++ b/app/models/lfs_objects_project.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class LfsObjectsProject < ActiveRecord::Base
+class LfsObjectsProject < ApplicationRecord
belongs_to :project
belongs_to :lfs_object
diff --git a/app/models/list.rb b/app/models/list.rb
index 682af761ba0..17b1a8510cf 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class List < ActiveRecord::Base
+class List < ApplicationRecord
belongs_to :board
belongs_to :label
diff --git a/app/models/member.rb b/app/models/member.rb
index 5dbc0c2eec9..8a06bff51b5 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Member < ActiveRecord::Base
+class Member < ApplicationRecord
include AfterCommitQueue
include Sortable
include Importable
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 2c9e1ba1d80..510f856087d 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -14,6 +14,8 @@ class GroupMember < Member
scope :in_groups, ->(groups) { where(source_id: groups.select(:id)) }
+ scope :count_users_by_group_id, -> { joins(:user).group(:source_id).count }
+
after_create :update_two_factor_requirement, unless: :invite?
after_destroy :update_two_factor_requirement, unless: :invite?
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index ea9c29daafc..a5fd66ca64a 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequest < ActiveRecord::Base
+class MergeRequest < ApplicationRecord
include AtomicInternalId
include IidRoutes
include Issuable
@@ -66,7 +66,10 @@ class MergeRequest < ActiveRecord::Base
has_many :cached_closes_issues, through: :merge_requests_closing_issues, source: :issue
has_many :merge_request_pipelines, foreign_key: 'merge_request_id', class_name: 'Ci::Pipeline'
+ has_many :suggestions, through: :notes
+ has_many :merge_request_assignees
+ # Will be deprecated at https://gitlab.com/gitlab-org/gitlab-ce/issues/59457
belongs_to :assignee, class_name: "User"
serialize :merge_params, Hash # rubocop:disable Cop/ActiveRecordSerialize
@@ -76,6 +79,10 @@ class MergeRequest < ActiveRecord::Base
after_update :reload_diff_if_branch_changed
after_save :ensure_metrics
+ # Required until the codebase starts using this relation for single or multiple assignees.
+ # TODO: Remove at gitlab-ee#2004 implementation.
+ after_save :refresh_merge_request_assignees, if: :assignee_id_changed?
+
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
attr_accessor :allow_broken
@@ -232,7 +239,7 @@ class MergeRequest < ActiveRecord::Base
# branch head commit, for example checking if a merge request can be merged.
# For more information check: https://gitlab.com/gitlab-org/gitlab-ce/issues/40004
def actual_head_pipeline
- head_pipeline&.sha == diff_head_sha ? head_pipeline : nil
+ head_pipeline&.matches_sha_or_source_sha?(diff_head_sha) ? head_pipeline : nil
end
def merge_pipeline
@@ -671,6 +678,15 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff || create_merge_request_diff
end
+ def refresh_merge_request_assignees
+ transaction do
+ # Using it instead relation.delete_all in order to avoid adding a
+ # dependent: :delete_all (we already have foreign key cascade deletion).
+ MergeRequestAssignee.where(merge_request_id: self).delete_all
+ merge_request_assignees.create(user_id: assignee_id) if assignee_id
+ end
+ end
+
def create_merge_request_diff
fetch_ref!
@@ -1109,6 +1125,10 @@ class MergeRequest < ActiveRecord::Base
"refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/merge"
end
+ def self.merge_request_ref?(ref)
+ ref.start_with?("refs/#{Repository::REF_MERGE_REQUEST}/")
+ end
+
def in_locked_state
begin
lock_mr
diff --git a/app/models/merge_request/metrics.rb b/app/models/merge_request/metrics.rb
index 65e94a97b0a..05f8e18a2c1 100644
--- a/app/models/merge_request/metrics.rb
+++ b/app/models/merge_request/metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequest::Metrics < ActiveRecord::Base
+class MergeRequest::Metrics < ApplicationRecord
belongs_to :merge_request
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :pipeline_id
belongs_to :latest_closed_by, class_name: 'User'
diff --git a/app/models/merge_request_assignee.rb b/app/models/merge_request_assignee.rb
new file mode 100644
index 00000000000..f0e6be51b7f
--- /dev/null
+++ b/app/models/merge_request_assignee.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class MergeRequestAssignee < ApplicationRecord
+ belongs_to :merge_request
+ belongs_to :assignee, class_name: "User", foreign_key: :user_id
+end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 98db1bf7de7..ac8d3b98266 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestDiff < ActiveRecord::Base
+class MergeRequestDiff < ApplicationRecord
include Sortable
include Importable
include ManualInverseAssociation
@@ -12,6 +12,10 @@ class MergeRequestDiff < ActiveRecord::Base
# Don't display more than 100 commits at once
COMMITS_SAFE_SIZE = 100
+ # Applies to closed or merged MRs when determining whether to migrate their
+ # diffs to external storage
+ EXTERNAL_DIFF_CUTOFF = 7.days.freeze
+
belongs_to :merge_request
manual_inverse_association :merge_request, :merge_request_diff
@@ -48,6 +52,81 @@ class MergeRequestDiff < ActiveRecord::Base
end
scope :recent, -> { order(id: :desc).limit(100) }
+ scope :files_in_database, -> { where(stored_externally: [false, nil]) }
+
+ scope :not_latest_diffs, -> do
+ merge_requests = MergeRequest.arel_table
+ mr_diffs = arel_table
+
+ join_condition = merge_requests[:id].eq(mr_diffs[:merge_request_id])
+ .and(mr_diffs[:id].not_eq(merge_requests[:latest_merge_request_diff_id]))
+
+ arel_join = mr_diffs.join(merge_requests).on(join_condition)
+ joins(arel_join.join_sources)
+ end
+
+ scope :old_merged_diffs, -> (before) do
+ merge_requests = MergeRequest.arel_table
+ mr_metrics = MergeRequest::Metrics.arel_table
+ mr_diffs = arel_table
+
+ mr_join = mr_diffs
+ .join(merge_requests)
+ .on(mr_diffs[:merge_request_id].eq(merge_requests[:id]))
+
+ metrics_join_condition = mr_diffs[:merge_request_id]
+ .eq(mr_metrics[:merge_request_id])
+ .and(mr_metrics[:merged_at].not_eq(nil))
+
+ metrics_join = mr_diffs.join(mr_metrics).on(metrics_join_condition)
+
+ condition = MergeRequest.arel_table[:state].eq(:merged)
+ .and(MergeRequest::Metrics.arel_table[:merged_at].lteq(before))
+ .and(MergeRequest::Metrics.arel_table[:merged_at].not_eq(nil))
+
+ joins(metrics_join.join_sources, mr_join.join_sources).where(condition)
+ end
+
+ scope :old_closed_diffs, -> (before) do
+ condition = MergeRequest.arel_table[:state].eq(:closed)
+ .and(MergeRequest::Metrics.arel_table[:latest_closed_at].lteq(before))
+
+ joins(merge_request: :metrics).where(condition)
+ end
+
+ def self.ids_for_external_storage_migration(limit:)
+ # No point doing any work unless the feature is enabled
+ return [] unless Gitlab.config.external_diffs.enabled
+
+ case Gitlab.config.external_diffs.when
+ when 'always'
+ files_in_database.limit(limit).pluck(:id)
+ when 'outdated'
+ # Outdated is too complex to be a single SQL query, so split into three
+ before = EXTERNAL_DIFF_CUTOFF.ago
+
+ ids = files_in_database
+ .old_merged_diffs(before)
+ .limit(limit)
+ .pluck(:id)
+
+ return ids if ids.size >= limit
+
+ ids += files_in_database
+ .old_closed_diffs(before)
+ .limit(limit - ids.size)
+ .pluck(:id)
+
+ return ids if ids.size >= limit
+
+ ids + files_in_database
+ .not_latest_diffs
+ .limit(limit - ids.size)
+ .pluck(:id)
+ else
+ []
+ end
+ end
mount_uploader :external_diff, ExternalDiffUploader
@@ -55,7 +134,7 @@ class MergeRequestDiff < ActiveRecord::Base
# It allows you to override variables like head_commit_sha before getting diff.
after_create :save_git_content, unless: :importing?
- after_save :update_external_diff_store, if: :external_diff_changed?
+ after_save :update_external_diff_store, if: -> { !importing? && external_diff_changed? }
def self.find_by_diff_refs(diff_refs)
find_by(start_commit_sha: diff_refs.start_sha, head_commit_sha: diff_refs.head_sha, base_commit_sha: diff_refs.base_sha)
@@ -294,6 +373,23 @@ class MergeRequestDiff < ActiveRecord::Base
end
end
+ # Transactionally migrate the current merge_request_diff_files entries to
+ # external storage. If external storage isn't an option for this diff, the
+ # method is a no-op.
+ def migrate_files_to_external_storage!
+ return if stored_externally? || !use_external_diff? || merge_request_diff_files.count == 0
+
+ rows = build_merge_request_diff_files(merge_request_diff_files)
+
+ transaction do
+ MergeRequestDiffFile.where(merge_request_diff_id: id).delete_all
+ create_merge_request_diff_files(rows)
+ save!
+ end
+
+ merge_request_diff_files.reload
+ end
+
private
def encode_in_base64?(diff_text)
@@ -301,20 +397,7 @@ class MergeRequestDiff < ActiveRecord::Base
diff_text.include?("\0")
end
- def create_merge_request_diff_files(diffs)
- rows =
- if has_attribute?(:external_diff) && Gitlab.config.external_diffs.enabled
- build_external_merge_request_diff_files(diffs)
- else
- build_merge_request_diff_files(diffs)
- end
-
- # Faster inserts
- Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
- end
-
- def build_external_merge_request_diff_files(diffs)
- rows = build_merge_request_diff_files(diffs)
+ def build_external_merge_request_diff_files(rows)
tempfile = build_external_diff_tempfile(rows)
self.external_diff = tempfile
@@ -325,16 +408,21 @@ class MergeRequestDiff < ActiveRecord::Base
tempfile&.unlink
end
+ def create_merge_request_diff_files(rows)
+ rows = build_external_merge_request_diff_files(rows) if use_external_diff?
+
+ # Faster inserts
+ Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
+ end
+
def build_external_diff_tempfile(rows)
Tempfile.open(external_diff.filename) do |file|
- rows.inject(0) do |offset, row|
+ rows.each do |row|
data = row.delete(:diff)
- row[:external_diff_offset] = offset
- row[:external_diff_size] = data.size
+ row[:external_diff_offset] = file.pos
+ row[:external_diff_size] = data.bytesize
file.write(data)
-
- offset + data.size
end
file
@@ -361,6 +449,47 @@ class MergeRequestDiff < ActiveRecord::Base
end
end
+ def use_external_diff?
+ return false unless has_attribute?(:external_diff)
+ return false unless Gitlab.config.external_diffs.enabled
+
+ case Gitlab.config.external_diffs.when
+ when 'always'
+ true
+ when 'outdated'
+ outdated_by_merge? || outdated_by_closure? || old_version?
+ else
+ false # Disable external diffs if misconfigured
+ end
+ end
+
+ def outdated_by_merge?
+ return false unless merge_request&.metrics&.merged_at
+
+ merge_request.merged? && merge_request.metrics.merged_at < EXTERNAL_DIFF_CUTOFF.ago
+ end
+
+ def outdated_by_closure?
+ return false unless merge_request&.metrics&.latest_closed_at
+
+ merge_request.closed? && merge_request.metrics.latest_closed_at < EXTERNAL_DIFF_CUTOFF.ago
+ end
+
+ # We can't rely on `merge_request.latest_merge_request_diff_id` because that
+ # may have been changed in `save_git_content` without being reflected in
+ # the association's instance. This query is always subject to races, but
+ # the worst case is that we *don't* make a diff external when we could. The
+ # background worker will make it external at a later date.
+ def old_version?
+ latest_id = MergeRequest
+ .where(id: merge_request_id)
+ .limit(1)
+ .pluck(:latest_merge_request_diff_id)
+ .first
+
+ self.id != latest_id
+ end
+
def load_diffs(options)
# Ensure all diff files operate on the same external diff file instance if
# present. This reduces file open/close overhead.
@@ -394,7 +523,8 @@ class MergeRequestDiff < ActiveRecord::Base
if diff_collection.any?
new_attributes[:state] = :collected
- create_merge_request_diff_files(diff_collection)
+ rows = build_merge_request_diff_files(diff_collection)
+ create_merge_request_diff_files(rows)
end
# Set our state to 'overflow' to make the #empty? and #collected?
diff --git a/app/models/merge_request_diff_commit.rb b/app/models/merge_request_diff_commit.rb
index 4ad3690512d..b897bbc8cf5 100644
--- a/app/models/merge_request_diff_commit.rb
+++ b/app/models/merge_request_diff_commit.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestDiffCommit < ActiveRecord::Base
+class MergeRequestDiffCommit < ApplicationRecord
include ShaAttribute
belongs_to :merge_request_diff
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index 16ec4ed470f..01ee82ae398 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestDiffFile < ActiveRecord::Base
+class MergeRequestDiffFile < ApplicationRecord
include Gitlab::EncodingHelper
include DiffFile
diff --git a/app/models/merge_requests_closing_issues.rb b/app/models/merge_requests_closing_issues.rb
index 242b65bedc0..61af50841ee 100644
--- a/app/models/merge_requests_closing_issues.rb
+++ b/app/models/merge_requests_closing_issues.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestsClosingIssues < ActiveRecord::Base
+class MergeRequestsClosingIssues < ApplicationRecord
belongs_to :merge_request
belongs_to :issue
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index d6f94cad1fb..b4aad9e512e 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Milestone < ActiveRecord::Base
+class Milestone < ApplicationRecord
# Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned.
MilestoneStruct = Struct.new(:title, :name, :id)
@@ -37,6 +37,7 @@ class Milestone < ActiveRecord::Base
scope :active, -> { with_state(:active) }
scope :closed, -> { with_state(:closed) }
scope :for_projects, -> { where(group: nil).includes(:project) }
+ scope :started, -> { active.where('milestones.start_date <= CURRENT_DATE') }
scope :for_projects_and_groups, -> (projects, groups) do
projects = projects.compact if projects.is_a? Array
diff --git a/app/models/note.rb b/app/models/note.rb
index 2c9980b1a0d..081d6f91230 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -3,7 +3,7 @@
# A note on the root of an issue, merge request, commit, or snippet.
#
# A note of this type is never resolvable.
-class Note < ActiveRecord::Base
+class Note < ApplicationRecord
extend ActiveModel::Naming
include Participable
include Mentionable
diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb
index e369122003e..9afb94c869a 100644
--- a/app/models/note_diff_file.rb
+++ b/app/models/note_diff_file.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class NoteDiffFile < ActiveRecord::Base
+class NoteDiffFile < ApplicationRecord
include DiffFile
scope :for_commit_or_unresolved, -> do
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index e82eaf4e069..61af5c09ae4 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class NotificationSetting < ActiveRecord::Base
+class NotificationSetting < ApplicationRecord
include IgnorableColumn
ignore_column :events
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 7a33ade826b..82901ceec01 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PagesDomain < ActiveRecord::Base
+class PagesDomain < ApplicationRecord
VERIFICATION_KEY = 'gitlab-pages-verification-code'.freeze
VERIFICATION_THRESHOLD = 3.days.freeze
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index ed78a46eaf3..570112b63b7 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PersonalAccessToken < ActiveRecord::Base
+class PersonalAccessToken < ApplicationRecord
include Expirable
include IgnorableColumn
include TokenAuthenticatable
diff --git a/app/models/pool_repository.rb b/app/models/pool_repository.rb
index 4635fc72dc7..35c718365b4 100644
--- a/app/models/pool_repository.rb
+++ b/app/models/pool_repository.rb
@@ -3,7 +3,7 @@
# The PoolRepository model is the database equivalent of an ObjectPool for Gitaly
# That is; PoolRepository is the record in the database, ObjectPool is the
# repository on disk
-class PoolRepository < ActiveRecord::Base
+class PoolRepository < ApplicationRecord
include Shardable
include AfterCommitQueue
diff --git a/app/models/postgresql/replication_slot.rb b/app/models/postgresql/replication_slot.rb
index e264fe88e47..74ccf23cf69 100644
--- a/app/models/postgresql/replication_slot.rb
+++ b/app/models/postgresql/replication_slot.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Postgresql
- class ReplicationSlot < ActiveRecord::Base
+ class ReplicationSlot < ApplicationRecord
self.table_name = 'pg_replication_slots'
# Returns true if there are any replication slots in use.
diff --git a/app/models/programming_language.rb b/app/models/programming_language.rb
index 5f0f313b7f9..375fbe9b5a9 100644
--- a/app/models/programming_language.rb
+++ b/app/models/programming_language.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProgrammingLanguage < ActiveRecord::Base
+class ProgrammingLanguage < ApplicationRecord
validates :name, presence: true
validates :color, allow_blank: false, color: true
diff --git a/app/models/project.rb b/app/models/project.rb
index a3d55d390f4..82c2f9090c8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2,7 +2,7 @@
require 'carrierwave/orm/activerecord'
-class Project < ActiveRecord::Base
+class Project < ApplicationRecord
include Gitlab::ConfigHelper
include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel
@@ -84,7 +84,7 @@ class Project < ActiveRecord::Base
default_value_for :snippets_enabled, gitlab_config_features.snippets
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
- add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:projects_tokens_optional_encryption) ? :optional : :required }
+ add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:projects_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
before_validation :mark_remote_mirrors_for_removal, if: -> { RemoteMirror.table_exists? }
@@ -459,14 +459,41 @@ class Project < ActiveRecord::Base
# Returns a collection of projects that is either public or visible to the
# logged in user.
- def self.public_or_visible_to_user(user = nil)
- if user
- where('EXISTS (?) OR projects.visibility_level IN (?)',
- user.authorizations_for_projects,
- Gitlab::VisibilityLevel.levels_for_user(user))
- else
- public_to_user
- end
+ #
+ # requested_visiblity_levels: Normally all projects that are visible
+ # to the user (e.g. internal and public) are queried, but this
+ # parameter allows the caller to narrow the search space to optimize
+ # database queries. For instance, a caller may only want to see
+ # internal projects. Instead of querying for internal and public
+ # projects and throwing away public projects, this parameter allows
+ # the query to be targeted for only internal projects.
+ def self.public_or_visible_to_user(user = nil, requested_visibility_levels = [])
+ return public_to_user unless user
+
+ visible_levels = Gitlab::VisibilityLevel.levels_for_user(user)
+ include_private = true
+ requested_visibility_levels = Array(requested_visibility_levels)
+
+ if requested_visibility_levels.present?
+ visible_levels &= requested_visibility_levels
+ include_private = requested_visibility_levels.include?(Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ public_or_internal_rel =
+ if visible_levels.present?
+ where('projects.visibility_level IN (?)', visible_levels)
+ else
+ Project.none
+ end
+
+ private_rel =
+ if include_private
+ where('EXISTS (?)', user.authorizations_for_projects)
+ else
+ Project.none
+ end
+
+ public_or_internal_rel.or(private_rel)
end
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
@@ -1384,6 +1411,7 @@ class Project < ActiveRecord::Base
repository.raw_repository.write_ref('HEAD', "refs/heads/#{branch}")
repository.copy_gitattributes(branch)
repository.after_change_head
+ ProjectCacheWorker.perform_async(self.id, [], [:commit_count])
reload_default_branch
else
errors.add(:base, "Could not change HEAD: branch '#{branch}' does not exist")
@@ -2002,12 +2030,8 @@ class Project < ActiveRecord::Base
@storage = nil if storage_version_changed?
end
- def gl_repository(is_wiki:)
- Gitlab::GlRepository.gl_repository(self, is_wiki)
- end
-
- def reference_counter(wiki: false)
- Gitlab::ReferenceCounter.new(gl_repository(is_wiki: wiki))
+ def reference_counter(type: Gitlab::GlRepository::PROJECT)
+ Gitlab::ReferenceCounter.new(type.identifier_for_subject(self))
end
def badges
@@ -2151,7 +2175,7 @@ class Project < ActiveRecord::Base
end
def wiki_reference_count
- reference_counter(wiki: true).value
+ reference_counter(type: Gitlab::GlRepository::WIKI).value
end
def check_repository_absence!
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 2c590008db2..f95d3ab54e2 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectAuthorization < ActiveRecord::Base
+class ProjectAuthorization < ApplicationRecord
include FromUnion
belongs_to :user
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index e353a6443c4..f972c40f317 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectAutoDevops < ActiveRecord::Base
+class ProjectAutoDevops < ApplicationRecord
belongs_to :project
enum deploy_strategy: {
diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb
index 1dad235cc2b..1414164b703 100644
--- a/app/models/project_ci_cd_setting.rb
+++ b/app/models/project_ci_cd_setting.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectCiCdSetting < ActiveRecord::Base
+class ProjectCiCdSetting < ApplicationRecord
belongs_to :project, inverse_of: :ci_cd_settings
# The version of the schema that first introduced this model/table.
diff --git a/app/models/project_custom_attribute.rb b/app/models/project_custom_attribute.rb
index 4e767cb3b26..b0da586988a 100644
--- a/app/models/project_custom_attribute.rb
+++ b/app/models/project_custom_attribute.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectCustomAttribute < ActiveRecord::Base
+class ProjectCustomAttribute < ApplicationRecord
belongs_to :project
validates :project, :key, :value, presence: true
diff --git a/app/models/project_daily_statistic.rb b/app/models/project_daily_statistic.rb
index ff115dd010f..5ee11ab186e 100644
--- a/app/models/project_daily_statistic.rb
+++ b/app/models/project_daily_statistic.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectDailyStatistic < ActiveRecord::Base
+class ProjectDailyStatistic < ApplicationRecord
belongs_to :project
scope :of_project, -> (project) { where(project: project) }
diff --git a/app/models/project_deploy_token.rb b/app/models/project_deploy_token.rb
index 719c492a1ff..a55667496fb 100644
--- a/app/models/project_deploy_token.rb
+++ b/app/models/project_deploy_token.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectDeployToken < ActiveRecord::Base
+class ProjectDeployToken < ApplicationRecord
belongs_to :project
belongs_to :deploy_token, inverse_of: :project_deploy_tokens
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index e6787236c4e..0542581c6e0 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectFeature < ActiveRecord::Base
+class ProjectFeature < ApplicationRecord
# == Project features permissions
#
# Grants access level to project tools
diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb
index bc3759142ae..58b555c3581 100644
--- a/app/models/project_group_link.rb
+++ b/app/models/project_group_link.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectGroupLink < ActiveRecord::Base
+class ProjectGroupLink < ApplicationRecord
include Expirable
GUEST = 10
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index aa0c121fe99..580e8dfd833 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -2,7 +2,7 @@
require 'carrierwave/orm/activerecord'
-class ProjectImportData < ActiveRecord::Base
+class ProjectImportData < ApplicationRecord
belongs_to :project, inverse_of: :import_data
attr_encrypted :credentials,
key: Settings.attr_encrypted_db_key_base,
diff --git a/app/models/project_import_state.rb b/app/models/project_import_state.rb
index 488f0cb5971..1605345efd5 100644
--- a/app/models/project_import_state.rb
+++ b/app/models/project_import_state.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectImportState < ActiveRecord::Base
+class ProjectImportState < ApplicationRecord
include AfterCommitQueue
self.table_name = "project_mirror_data"
diff --git a/app/models/project_repository.rb b/app/models/project_repository.rb
index 38913f3f2f5..092efabd73f 100644
--- a/app/models/project_repository.rb
+++ b/app/models/project_repository.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectRepository < ActiveRecord::Base
+class ProjectRepository < ApplicationRecord
include Shardable
belongs_to :project, inverse_of: :project_repository
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index 4cf3a7f3d84..f650dbd3726 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -131,8 +131,8 @@ class KubernetesService < DeploymentService
# short time later
def terminals(environment)
with_reactive_cache do |data|
- pods = filter_by_label(data[:pods], app: environment.slug)
- terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }
+ pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
+ terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }.compact
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
end
end
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index 781a197d56f..c020e72908c 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProjectStatistics < ActiveRecord::Base
+class ProjectStatistics < ApplicationRecord
belongs_to :project
belongs_to :namespace
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index c43bd45a62f..268706a6aea 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -59,7 +59,7 @@ class ProjectWiki
# Returns the Gitlab::Git::Wiki object.
def wiki
@wiki ||= begin
- gl_repository = Gitlab::GlRepository.gl_repository(project, true)
+ gl_repository = Gitlab::GlRepository::WIKI.identifier_for_subject(project)
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path)
create_repo!(raw_repository) unless raw_repository.exists?
@@ -151,7 +151,7 @@ class ProjectWiki
end
def repository
- @repository ||= Repository.new(full_path, @project, disk_path: disk_path, is_wiki: true)
+ @repository ||= Repository.new(full_path, @project, disk_path: disk_path, repo_type: Gitlab::GlRepository::WIKI)
end
def default_branch
@@ -183,7 +183,7 @@ class ProjectWiki
end
def commit_details(action, message = nil, title = nil)
- commit_message = message || default_message(action, title)
+ commit_message = message.presence || default_message(action, title)
git_user = Gitlab::Git::User.from_gitlab(@user)
Gitlab::Git::Wiki::CommitDetails.new(@user.id,
diff --git a/app/models/prometheus_metric.rb b/app/models/prometheus_metric.rb
index 5594594a48d..62090444f79 100644
--- a/app/models/prometheus_metric.rb
+++ b/app/models/prometheus_metric.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PrometheusMetric < ActiveRecord::Base
+class PrometheusMetric < ApplicationRecord
belongs_to :project, validate: true, inverse_of: :prometheus_metrics
enum group: {
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 597431be65a..ee0c94c20af 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProtectedBranch < ActiveRecord::Base
+class ProtectedBranch < ApplicationRecord
include ProtectedRef
protected_ref_access_levels :merge, :push
diff --git a/app/models/protected_branch/merge_access_level.rb b/app/models/protected_branch/merge_access_level.rb
index b0d5c64e931..de240e40316 100644
--- a/app/models/protected_branch/merge_access_level.rb
+++ b/app/models/protected_branch/merge_access_level.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base
+class ProtectedBranch::MergeAccessLevel < ApplicationRecord
include ProtectedBranchAccess
end
diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb
index b2a88229853..bde1d29ad7f 100644
--- a/app/models/protected_branch/push_access_level.rb
+++ b/app/models/protected_branch/push_access_level.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class ProtectedBranch::PushAccessLevel < ActiveRecord::Base
+class ProtectedBranch::PushAccessLevel < ApplicationRecord
include ProtectedBranchAccess
end
diff --git a/app/models/protected_tag.rb b/app/models/protected_tag.rb
index d28ebabfe49..6b507429e57 100644
--- a/app/models/protected_tag.rb
+++ b/app/models/protected_tag.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProtectedTag < ActiveRecord::Base
+class ProtectedTag < ApplicationRecord
include ProtectedRef
validates :name, uniqueness: { scope: :project_id }
diff --git a/app/models/protected_tag/create_access_level.rb b/app/models/protected_tag/create_access_level.rb
index b06e55fb5dd..9fcfa7646a2 100644
--- a/app/models/protected_tag/create_access_level.rb
+++ b/app/models/protected_tag/create_access_level.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ProtectedTag::CreateAccessLevel < ActiveRecord::Base
+class ProtectedTag::CreateAccessLevel < ApplicationRecord
include ProtectedTagAccess
def check_access(user)
diff --git a/app/models/push_event_payload.rb b/app/models/push_event_payload.rb
index c7769edf055..537859ec7b7 100644
--- a/app/models/push_event_payload.rb
+++ b/app/models/push_event_payload.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PushEventPayload < ActiveRecord::Base
+class PushEventPayload < ApplicationRecord
include ShaAttribute
belongs_to :event, inverse_of: :push_event_payload
diff --git a/app/models/redirect_route.rb b/app/models/redirect_route.rb
index c6bd4bb6dfa..2e4769364c6 100644
--- a/app/models/redirect_route.rb
+++ b/app/models/redirect_route.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RedirectRoute < ActiveRecord::Base
+class RedirectRoute < ApplicationRecord
belongs_to :source, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
validates :source, presence: true
diff --git a/app/models/release.rb b/app/models/release.rb
index 0dae5c90394..746fc31a038 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Release < ActiveRecord::Base
+class Release < ApplicationRecord
include CacheMarkdownField
include Gitlab::Utils::StrongMemoize
diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb
index 6c507c47752..36ec33d3e3e 100644
--- a/app/models/releases/link.rb
+++ b/app/models/releases/link.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Releases
- class Link < ActiveRecord::Base
+ class Link < ApplicationRecord
self.table_name = 'release_links'
belongs_to :release
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 5eba7ddd75c..5610cfe0f24 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RemoteMirror < ActiveRecord::Base
+class RemoteMirror < ApplicationRecord
include AfterCommitQueue
include MirrorAuthentication
diff --git a/app/models/repository.rb b/app/models/repository.rb
index ff355295862..574ce12b309 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -19,7 +19,7 @@ class Repository
include Gitlab::RepositoryCacheAdapter
- attr_accessor :full_path, :disk_path, :project, :is_wiki
+ attr_accessor :full_path, :disk_path, :project, :repo_type
delegate :ref_name_for_sha, to: :raw_repository
delegate :bundle_to_disk, to: :raw_repository
@@ -60,12 +60,12 @@ class Repository
xcode_config: :xcode_project?
}.freeze
- def initialize(full_path, project, disk_path: nil, is_wiki: false)
+ def initialize(full_path, project, disk_path: nil, repo_type: Gitlab::GlRepository::PROJECT)
@full_path = full_path
@disk_path = disk_path || full_path
@project = project
@commit_cache = {}
- @is_wiki = is_wiki
+ @repo_type = repo_type
end
def ==(other)
@@ -1112,7 +1112,7 @@ class Repository
def initialize_raw_repository
Gitlab::Git::Repository.new(project.repository_storage,
disk_path + '.git',
- Gitlab::GlRepository.gl_repository(project, is_wiki),
+ repo_type.identifier_for_subject(project),
project.full_path)
end
end
diff --git a/app/models/repository_language.rb b/app/models/repository_language.rb
index b18142a2ac4..e6867f905e2 100644
--- a/app/models/repository_language.rb
+++ b/app/models/repository_language.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RepositoryLanguage < ActiveRecord::Base
+class RepositoryLanguage < ApplicationRecord
belongs_to :project
belongs_to :programming_language
diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb
index 3fd96b9dc18..f2c7cb6a65d 100644
--- a/app/models/resource_label_event.rb
+++ b/app/models/resource_label_event.rb
@@ -2,7 +2,7 @@
# This model is not used yet, it will be used for:
# https://gitlab.com/gitlab-org/gitlab-ce/issues/48483
-class ResourceLabelEvent < ActiveRecord::Base
+class ResourceLabelEvent < ApplicationRecord
include Importable
include Gitlab::Utils::StrongMemoize
include CacheMarkdownField
diff --git a/app/models/route.rb b/app/models/route.rb
index 4b23dfa5778..7e3db54d4fe 100644
--- a/app/models/route.rb
+++ b/app/models/route.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Route < ActiveRecord::Base
+class Route < ApplicationRecord
include CaseSensitivity
belongs_to :source, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 6caab24143b..0427d5b9ca7 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class SentNotification < ActiveRecord::Base
+class SentNotification < ApplicationRecord
serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
belongs_to :project
diff --git a/app/models/service.rb b/app/models/service.rb
index da523bfa426..c6d5eb353dc 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -2,7 +2,7 @@
# To add new service you should build a class inherited from Service
# and implement a set of methods
-class Service < ActiveRecord::Base
+class Service < ApplicationRecord
include Sortable
include Importable
include ProjectServicesLoggable
diff --git a/app/models/shard.rb b/app/models/shard.rb
index e39d4232486..335a279c6aa 100644
--- a/app/models/shard.rb
+++ b/app/models/shard.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Shard < ActiveRecord::Base
+class Shard < ApplicationRecord
# Store shard names from the configuration file in the database. This is not a
# list of active shards - we just want to assign an immutable, unique ID to
# every shard name for easy indexing / referencing.
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index f23ddd64fe3..f4fdac2558c 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Snippet < ActiveRecord::Base
+class Snippet < ApplicationRecord
include Gitlab::VisibilityLevel
include Redactable
include CacheMarkdownField
diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb
index ef3f974b959..5b9ece8373f 100644
--- a/app/models/spam_log.rb
+++ b/app/models/spam_log.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class SpamLog < ActiveRecord::Base
+class SpamLog < ApplicationRecord
belongs_to :user
validates :user, presence: true
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
index 0f6ee0ddf7e..24a2b8b5167 100644
--- a/app/models/subscription.rb
+++ b/app/models/subscription.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Subscription < ActiveRecord::Base
+class Subscription < ApplicationRecord
belongs_to :user
belongs_to :project
belongs_to :subscribable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
diff --git a/app/models/suggestion.rb b/app/models/suggestion.rb
index 09034646bff..22e2f11230d 100644
--- a/app/models/suggestion.rb
+++ b/app/models/suggestion.rb
@@ -1,11 +1,19 @@
# frozen_string_literal: true
class Suggestion < ApplicationRecord
+ include Suggestible
+
belongs_to :note, inverse_of: :suggestions
validates :note, presence: true
validates :commit_id, presence: true, if: :applied?
- delegate :original_position, :position, :noteable, to: :note
+ delegate :position, :noteable, to: :note
+
+ scope :active, -> { where(outdated: false) }
+
+ def diff_file
+ note.latest_diff_file
+ end
def project
noteable.source_project
@@ -19,37 +27,37 @@ class Suggestion < ApplicationRecord
position.file_path
end
- # For now, suggestions only serve as a way to send patches that
- # will change a single line (being able to apply multiple in the same place),
- # which explains `from_line` and `to_line` being the same line.
- # We'll iterate on that in https://gitlab.com/gitlab-org/gitlab-ce/issues/53310
- # when allowing multi-line suggestions.
- def from_line
- position.new_line
- end
- alias_method :to_line, :from_line
-
- def from_original_line
- original_position.new_line
- end
- alias_method :to_original_line, :from_original_line
-
# `from_line_index` and `to_line_index` represents diff/blob line numbers in
# index-like way (N-1).
def from_line_index
from_line - 1
end
- alias_method :to_line_index, :from_line_index
- def appliable?
- return false unless note.supports_suggestion?
+ def to_line_index
+ to_line - 1
+ end
+ def appliable?(cached: true)
!applied? &&
noteable.opened? &&
+ !outdated?(cached: cached) &&
+ note.supports_suggestion? &&
different_content? &&
note.active?
end
+ # Overwrites outdated column
+ def outdated?(cached: true)
+ return super() if cached
+ return true unless diff_file
+
+ from_content != fetch_from_content
+ end
+
+ def target_line
+ position.new_line
+ end
+
private
def different_content?
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index d555ebe5322..55da37c9545 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class SystemNoteMetadata < ActiveRecord::Base
+class SystemNoteMetadata < ApplicationRecord
# These notes's action text might contain a reference that is external.
# We should always force a deep validation upon references that are found
# in this note type.
diff --git a/app/models/term_agreement.rb b/app/models/term_agreement.rb
index 9b3c8ac68bd..a4a9dc10282 100644
--- a/app/models/term_agreement.rb
+++ b/app/models/term_agreement.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class TermAgreement < ActiveRecord::Base
+class TermAgreement < ApplicationRecord
belongs_to :term, class_name: 'ApplicationSetting::Term'
belongs_to :user
diff --git a/app/models/timelog.rb b/app/models/timelog.rb
index e04c644a53a..048134fbf04 100644
--- a/app/models/timelog.rb
+++ b/app/models/timelog.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Timelog < ActiveRecord::Base
+class Timelog < ApplicationRecord
validates :time_spent, :user, presence: true
validate :issuable_id_is_present
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 2b0dee875a3..5dcc3e9945a 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Todo < ActiveRecord::Base
+class Todo < ApplicationRecord
include Sortable
include FromUnion
diff --git a/app/models/trending_project.rb b/app/models/trending_project.rb
index 7b22e8cb760..810dee672b2 100644
--- a/app/models/trending_project.rb
+++ b/app/models/trending_project.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class TrendingProject < ActiveRecord::Base
+class TrendingProject < ApplicationRecord
belongs_to :project
# The number of months to include in the trending calculation.
diff --git a/app/models/u2f_registration.rb b/app/models/u2f_registration.rb
index 37598173fd1..b4645462314 100644
--- a/app/models/u2f_registration.rb
+++ b/app/models/u2f_registration.rb
@@ -2,7 +2,7 @@
# Registration information for U2F (universal 2nd factor) devices, like Yubikeys
-class U2fRegistration < ActiveRecord::Base
+class U2fRegistration < ApplicationRecord
belongs_to :user
def self.register(user, app_id, params, challenges)
diff --git a/app/models/upload.rb b/app/models/upload.rb
index 20860f14b83..9bffdcdb2e7 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Upload < ActiveRecord::Base
+class Upload < ApplicationRecord
# Upper limit for foreground checksum processing
CHECKSUM_THRESHOLD = 100.megabytes
diff --git a/app/models/user.rb b/app/models/user.rb
index 0ebfb9a0ccb..e0c518a9b75 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -432,7 +432,7 @@ class User < ApplicationRecord
fuzzy_arel_match(:name, query, lower_exact_match: true)
.or(fuzzy_arel_match(:username, query, lower_exact_match: true))
.or(arel_table[:email].eq(query))
- ).reorder(order % { query: ActiveRecord::Base.connection.quote(query) }, :name)
+ ).reorder(order % { query: ApplicationRecord.connection.quote(query) }, :name)
end
# Limits the result set to users _not_ in the given query/list of IDs.
@@ -917,6 +917,10 @@ class User < ApplicationRecord
DeployKey.unscoped.in_projects(authorized_projects.pluck(:id)).distinct(:id)
end
+ def highest_role
+ members.maximum(:access_level) || Gitlab::Access::NO_ACCESS
+ end
+
def accessible_deploy_keys
@accessible_deploy_keys ||= begin
key_ids = project_deploy_keys.pluck(:id)
diff --git a/app/models/user_agent_detail.rb b/app/models/user_agent_detail.rb
index e2b2e7f1df9..fea1fce3c8d 100644
--- a/app/models/user_agent_detail.rb
+++ b/app/models/user_agent_detail.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserAgentDetail < ActiveRecord::Base
+class UserAgentDetail < ApplicationRecord
belongs_to :subject, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
validates :user_agent, :ip_address, :subject_id, :subject_type, presence: true
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index 76e7bc06b4e..027ee44c6a9 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserCallout < ActiveRecord::Base
+class UserCallout < ApplicationRecord
belongs_to :user
# We use `UserCalloutEnums.feature_names` here so that EE can more easily
diff --git a/app/models/user_custom_attribute.rb b/app/models/user_custom_attribute.rb
index e0ffe8ebbfd..727975c3f6e 100644
--- a/app/models/user_custom_attribute.rb
+++ b/app/models/user_custom_attribute.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserCustomAttribute < ActiveRecord::Base
+class UserCustomAttribute < ApplicationRecord
belongs_to :user
validates :user_id, :key, :value, presence: true
diff --git a/app/models/user_interacted_project.rb b/app/models/user_interacted_project.rb
index 5fc59b274f5..f6f72f4b77a 100644
--- a/app/models/user_interacted_project.rb
+++ b/app/models/user_interacted_project.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserInteractedProject < ActiveRecord::Base
+class UserInteractedProject < ApplicationRecord
belongs_to :user
belongs_to :project
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 32d0407800f..282b192167f 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserPreference < ActiveRecord::Base
+class UserPreference < ApplicationRecord
# We could use enums, but Rails 4 doesn't support multiple
# enum options with same name for multiple fields, also it creates
# extra methods that aren't really needed here.
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 2bbb0c59ac1..6ced4f56823 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserStatus < ActiveRecord::Base
+class UserStatus < ApplicationRecord
include CacheMarkdownField
self.primary_key = :user_id
diff --git a/app/models/user_synced_attributes_metadata.rb b/app/models/user_synced_attributes_metadata.rb
index 7115262942d..5aacf11b1cb 100644
--- a/app/models/user_synced_attributes_metadata.rb
+++ b/app/models/user_synced_attributes_metadata.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UserSyncedAttributesMetadata < ActiveRecord::Base
+class UserSyncedAttributesMetadata < ApplicationRecord
belongs_to :user
validates :user, presence: true
diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb
index bdaf58ae1c1..9be6bd2e6f3 100644
--- a/app/models/users_star_project.rb
+++ b/app/models/users_star_project.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class UsersStarProject < ActiveRecord::Base
+class UsersStarProject < ApplicationRecord
belongs_to :project, counter_cache: :star_count, touch: true
belongs_to :user