Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-14 03:09:07 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-14 03:09:07 +0300
commite144369009f3404072f7e0f969f7cded93195a01 (patch)
treed7a354e2c3c69a7ad65dc81aba8fe2ba59b0a26f /app/models
parentd466ee5042520ad078fe050cb078d81dc2ebe196 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/models')
-rw-r--r--app/models/concerns/issuable.rb1
-rw-r--r--app/models/concerns/mentionable.rb17
-rw-r--r--app/models/deployment.rb1
-rw-r--r--app/models/environment.rb39
-rw-r--r--app/models/issue.rb2
-rw-r--r--app/models/merge_request.rb6
-rw-r--r--app/models/note.rb5
-rw-r--r--app/models/snippet.rb4
8 files changed, 69 insertions, 6 deletions
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index f3e03ed22d7..78d815e5858 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -91,6 +91,7 @@ module Issuable
validate :description_max_length_for_new_records_is_valid, on: :update
before_validation :truncate_description_on_import!
+ after_save :store_mentions!, if: :any_mentionable_attributes_changed?
scope :authored, ->(user) { where(author_id: user) }
scope :recent, -> { reorder(id: :desc) }
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index b43b91699ab..d157404f7bc 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -99,18 +99,23 @@ module Mentionable
# threw the `ActiveRecord::RecordNotUnique` exception in first place.
self.class.safe_ensure_unique(retries: 1) do
user_mention = model_user_mention
+
+ # this may happen due to notes polymorphism, so noteable_id may point to a record that no longer exists
+ # as we cannot have FK on noteable_id
+ break if user_mention.blank?
+
user_mention.mentioned_users_ids = references[:mentioned_users_ids]
user_mention.mentioned_groups_ids = references[:mentioned_groups_ids]
user_mention.mentioned_projects_ids = references[:mentioned_projects_ids]
if user_mention.has_mentions?
user_mention.save!
- elsif user_mention.persisted?
+ else
user_mention.destroy!
end
-
- true
end
+
+ true
end
def referenced_users
@@ -218,6 +223,12 @@ module Mentionable
source.select { |key, val| mentionable.include?(key) }
end
+ def any_mentionable_attributes_changed?
+ self.class.mentionable_attrs.any? do |attr|
+ saved_changes.key?(attr.first)
+ end
+ end
+
# Determine whether or not a cross-reference Note has already been created between this Mentionable and
# the specified target.
def cross_reference_exists?(target)
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 0c679a3075b..5450357fe1b 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -39,6 +39,7 @@ class Deployment < ApplicationRecord
scope :for_status, -> (status) { where(status: status) }
scope :visible, -> { where(status: %i[running success failed canceled]) }
+ scope :stoppable, -> { where.not(on_stop: nil).where.not(deployable_id: nil).success }
state_machine :status, initial: :created do
event :run do
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 973f1243e6b..4635b05fcc7 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -61,6 +61,7 @@ class Environment < ApplicationRecord
scope :in_review_folder, -> { where(environment_type: "review") }
scope :for_name, -> (name) { where(name: name) }
scope :preload_cluster, -> { preload(last_deployment: :cluster) }
+ scope :auto_stoppable, -> (limit) { available.where('auto_stop_at < ?', Time.zone.now).limit(limit) }
##
# Search environments which have names like the given query.
@@ -107,6 +108,44 @@ class Environment < ApplicationRecord
find_or_create_by(name: name)
end
+ class << self
+ ##
+ # This method returns stop actions (jobs) for multiple environments within one
+ # query. It's useful to avoid N+1 problem.
+ #
+ # NOTE: The count of environments should be small~medium (e.g. < 5000)
+ def stop_actions
+ cte = cte_for_deployments_with_stop_action
+ ci_builds = Ci::Build.arel_table
+
+ inner_join_stop_actions = ci_builds.join(cte.table).on(
+ ci_builds[:project_id].eq(cte.table[:project_id])
+ .and(ci_builds[:ref].eq(cte.table[:ref]))
+ .and(ci_builds[:name].eq(cte.table[:on_stop]))
+ ).join_sources
+
+ pipeline_ids = ci_builds.join(cte.table).on(
+ ci_builds[:id].eq(cte.table[:deployable_id])
+ ).project(:commit_id)
+
+ Ci::Build.joins(inner_join_stop_actions)
+ .with(cte.to_arel)
+ .where(ci_builds[:commit_id].in(pipeline_ids))
+ .where(status: HasStatus::BLOCKED_STATUS)
+ .preload_project_and_pipeline_project
+ .preload(:user, :metadata, :deployment)
+ end
+
+ private
+
+ def cte_for_deployments_with_stop_action
+ Gitlab::SQL::CTE.new(:deployments_with_stop_action,
+ Deployment.where(environment_id: select(:id))
+ .distinct_on_environment
+ .stoppable)
+ end
+ end
+
def clear_prometheus_reactive_cache!(query_name)
cluster_prometheus_adapter&.clear_prometheus_reactive_cache!(query_name, self)
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 684108b1a7a..d01aa78a2c1 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -45,7 +45,7 @@ class Issue < ApplicationRecord
has_many :issue_assignees
has_many :assignees, class_name: "User", through: :issue_assignees
has_many :zoom_meetings
- has_many :user_mentions, class_name: "IssueUserMention"
+ has_many :user_mentions, class_name: "IssueUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_one :sentry_issue
accepts_nested_attributes_for :sentry_issue
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index b8f51b58fd3..14aa6ac066e 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -77,7 +77,7 @@ class MergeRequest < ApplicationRecord
has_many :merge_request_assignees
has_many :assignees, class_name: "User", through: :merge_request_assignees
- has_many :user_mentions, class_name: "MergeRequestUserMention"
+ has_many :user_mentions, class_name: "MergeRequestUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :deployment_merge_requests
@@ -840,6 +840,10 @@ class MergeRequest < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
+ def diffable_merge_ref?
+ Feature.enabled?(:diff_compare_with_head, target_project) && can_be_merged? && merge_ref_head.present?
+ end
+
# Returns boolean indicating the merge_status should be rechecked in order to
# switch to either can_be_merged or cannot_be_merged.
def recheck_merge_status?
diff --git a/app/models/note.rb b/app/models/note.rb
index 8af650e27aa..97e84bb79f6 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -157,6 +157,7 @@ class Note < ApplicationRecord
after_save :expire_etag_cache, unless: :importing?
after_save :touch_noteable, unless: :importing?
after_destroy :expire_etag_cache
+ after_save :store_mentions!, if: :any_mentionable_attributes_changed?
class << self
def model_name
@@ -498,6 +499,8 @@ class Note < ApplicationRecord
end
def user_mentions
+ return Note.none unless noteable.present?
+
noteable.user_mentions.where(note: self)
end
@@ -506,6 +509,8 @@ class Note < ApplicationRecord
# Using this method followed by a call to `save` may result in ActiveRecord::RecordNotUnique exception
# in a multithreaded environment. Make sure to use it within a `safe_ensure_unique` block.
def model_user_mention
+ return if user_mentions.is_a?(ActiveRecord::NullRelation)
+
user_mentions.first_or_initialize
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index e2b72dfde7a..4ba8e6a94e6 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -41,7 +41,7 @@ class Snippet < ApplicationRecord
belongs_to :project
has_many :notes, as: :noteable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :user_mentions, class_name: "SnippetUserMention"
+ has_many :user_mentions, class_name: "SnippetUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_one :snippet_repository, inverse_of: :snippet
delegate :name, :email, to: :author, prefix: true, allow_nil: true
@@ -66,6 +66,8 @@ class Snippet < ApplicationRecord
validates :visibility_level, inclusion: { in: Gitlab::VisibilityLevel.values }
+ after_save :store_mentions!, if: :any_mentionable_attributes_changed?
+
# Scopes
scope :are_internal, -> { where(visibility_level: Snippet::INTERNAL) }
scope :are_private, -> { where(visibility_level: Snippet::PRIVATE) }