diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/board.rb | 4 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 13 | ||||
-rw-r--r-- | app/models/clusters/applications/prometheus.rb | 5 | ||||
-rw-r--r-- | app/models/clusters/cluster.rb | 2 | ||||
-rw-r--r-- | app/models/clusters/platforms/kubernetes.rb | 1 | ||||
-rw-r--r-- | app/models/commit_collection.rb | 4 | ||||
-rw-r--r-- | app/models/concerns/reactive_caching.rb | 2 | ||||
-rw-r--r-- | app/models/concerns/with_uploads.rb | 34 | ||||
-rw-r--r-- | app/models/discussion.rb | 2 | ||||
-rw-r--r-- | app/models/individual_note_discussion.rb | 8 | ||||
-rw-r--r-- | app/models/merge_request.rb | 8 | ||||
-rw-r--r-- | app/models/merge_request_diff.rb | 3 | ||||
-rw-r--r-- | app/models/personal_access_token.rb | 5 | ||||
-rw-r--r-- | app/models/project.rb | 5 | ||||
-rw-r--r-- | app/models/project_services/deployment_service.rb | 2 | ||||
-rw-r--r-- | app/models/project_services/hipchat_service.rb | 311 | ||||
-rw-r--r-- | app/models/releases/link.rb | 2 | ||||
-rw-r--r-- | app/models/repository.rb | 9 | ||||
-rw-r--r-- | app/models/service.rb | 1 | ||||
-rw-r--r-- | app/models/user.rb | 5 |
20 files changed, 55 insertions, 371 deletions
diff --git a/app/models/board.rb b/app/models/board.rb index a137863456c..758a71d6903 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -21,6 +21,10 @@ class Board < ActiveRecord::Base group_id.present? end + def project_board? + project_id.present? + end + def backlog_list lists.merge(List.backlog).take end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index acef5d2e643..f0ae516a2f8 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -315,7 +315,7 @@ module Ci def ordered_stages return legacy_stages unless complete? - if Feature.enabled?('ci_pipeline_persisted_stages') + if Feature.enabled?('ci_pipeline_persisted_stages', default_enabled: true) stages else legacy_stages @@ -687,9 +687,18 @@ module Ci end end + # Returns the modified paths. + # + # The returned value is + # * Array: List of modified paths that should be evaluated + # * nil: Modified path can not be evaluated def modified_paths strong_memoize(:modified_paths) do - push_details.modified_paths + if merge_request? + merge_request.modified_paths + elsif branch_updated? + push_details.modified_paths + end end end diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index 52c440ffb2f..fa7ce363531 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -6,7 +6,6 @@ module Clusters include PrometheusAdapter VERSION = '6.7.3' - READY_STATUS = [:installed, :updating, :updated, :update_errored].freeze self.table_name = 'clusters_applications_prometheus' @@ -25,10 +24,6 @@ module Clusters end end - def ready? - READY_STATUS.include?(status_name) - end - def chart 'stable/prometheus' end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 8df293664ce..be3e6a05e1e 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -50,7 +50,7 @@ module Clusters validates :name, cluster_name: true validates :cluster_type, presence: true - validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true, require_valid_tld: true } + validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true } validate :restrict_modification, on: :update validate :no_groups, unless: :group_type? diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index c8969351ed9..46d0898014e 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -43,6 +43,7 @@ module Clusters # We expect to be `active?` only when enabled and cluster is created (the api_url is assigned) validates :api_url, url: true, presence: true validates :token, presence: true + validates :ca_cert, certificate: true, allow_blank: true, if: :ca_cert_changed? validate :prevent_modification, on: :update diff --git a/app/models/commit_collection.rb b/app/models/commit_collection.rb index 42ec5b5e664..a9a2e9c81eb 100644 --- a/app/models/commit_collection.rb +++ b/app/models/commit_collection.rb @@ -20,8 +20,8 @@ class CommitCollection commits.each(&block) end - def committers - emails = without_merge_commits.map(&:committer_email).uniq + def authors + emails = without_merge_commits.map(&:author_email).uniq User.by_any_email(emails) end diff --git a/app/models/concerns/reactive_caching.rb b/app/models/concerns/reactive_caching.rb index d3572875fb3..de77ca3e963 100644 --- a/app/models/concerns/reactive_caching.rb +++ b/app/models/concerns/reactive_caching.rb @@ -76,7 +76,7 @@ module ReactiveCaching begin data = Rails.cache.read(full_reactive_cache_key(*args)) - yield data if data.present? + yield data unless data.nil? rescue InvalidateReactiveCache refresh_reactive_cache!(*args) nil diff --git a/app/models/concerns/with_uploads.rb b/app/models/concerns/with_uploads.rb index d79c0eae77e..6c6febd186c 100644 --- a/app/models/concerns/with_uploads.rb +++ b/app/models/concerns/with_uploads.rb @@ -27,40 +27,14 @@ module WithUploads included do has_many :uploads, as: :model - has_many :file_uploads, -> { where(uploader: FILE_UPLOADERS) }, class_name: 'Upload', as: :model + has_many :file_uploads, -> { where(uploader: FILE_UPLOADERS) }, + class_name: 'Upload', as: :model, + dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent - # TODO: when feature flag is removed, we can use just dependent: destroy - # option on :file_uploads - before_destroy :remove_file_uploads - - use_fast_destroy :file_uploads, if: :fast_destroy_enabled? + use_fast_destroy :file_uploads end def retrieve_upload(_identifier, paths) uploads.find_by(path: paths) end - - private - - # mounted uploads are deleted in carrierwave's after_commit hook, - # but FileUploaders which are not mounted must be deleted explicitly and - # it can not be done in after_commit because FileUploader requires loads - # associated model on destroy (which is already deleted in after_commit) - def remove_file_uploads - fast_destroy_enabled? ? delete_uploads : destroy_uploads - end - - def delete_uploads - file_uploads.delete_all(:delete_all) - end - - def destroy_uploads - file_uploads.find_each do |upload| - upload.destroy - end - end - - def fast_destroy_enabled? - Feature.enabled?(:fast_destroy_uploads, self) - end end diff --git a/app/models/discussion.rb b/app/models/discussion.rb index f2678e0597d..32529ebf71d 100644 --- a/app/models/discussion.rb +++ b/app/models/discussion.rb @@ -17,8 +17,6 @@ class Discussion :for_commit?, :for_merge_request?, - :save, - to: :first_note def project_id diff --git a/app/models/individual_note_discussion.rb b/app/models/individual_note_discussion.rb index aab0ff93468..b4a661ae5b4 100644 --- a/app/models/individual_note_discussion.rb +++ b/app/models/individual_note_discussion.rb @@ -17,8 +17,12 @@ class IndividualNoteDiscussion < Discussion noteable.supports_replying_to_individual_notes? && Feature.enabled?(:reply_to_individual_notes) end - def convert_to_discussion! - first_note.becomes!(Discussion.note_class).to_discussion + def convert_to_discussion!(save: false) + first_note.becomes!(Discussion.note_class).to_discussion.tap do + # Save needs to be called on first_note instead of the transformed note + # because of https://gitlab.com/gitlab-org/gitlab-ce/issues/57324 + first_note.save if save + end end def reply_attributes diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 2035bffd829..75fca96ce0a 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -286,12 +286,12 @@ class MergeRequest < ActiveRecord::Base work_in_progress?(title) ? title : "WIP: #{title}" end - def committers - @committers ||= commits.committers + def commit_authors + @commit_authors ||= commits.authors end def authors - User.from_union([committers, User.where(id: self.author_id)]) + User.from_union([commit_authors, User.where(id: self.author_id)]) end # Verifies if title has changed not taking into account WIP prefix @@ -1322,7 +1322,7 @@ class MergeRequest < ActiveRecord::Base def base_pipeline @base_pipeline ||= project.ci_pipelines .order(id: :desc) - .find_by(sha: diff_base_sha) + .find_by(sha: diff_base_sha, ref: target_branch) end def discussions_rendered_on_frontend? diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 712347e76ed..e286a4e57f2 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -12,9 +12,6 @@ class MergeRequestDiff < ActiveRecord::Base # Don't display more than 100 commits at once COMMITS_SAFE_SIZE = 100 - ignore_column :st_commits, - :st_diffs - belongs_to :merge_request manual_inverse_association :merge_request, :merge_request_diff diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index 73a58f2420e..ed78a46eaf3 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -2,8 +2,11 @@ class PersonalAccessToken < ActiveRecord::Base include Expirable + include IgnorableColumn include TokenAuthenticatable - add_authentication_token_field :token, digest: true, fallback: true + + add_authentication_token_field :token, digest: true + ignore_column :token REDIS_EXPIRY_TIME = 3.minutes diff --git a/app/models/project.rb b/app/models/project.rb index 8f746f6e094..c72d3a3b725 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -147,7 +147,6 @@ class Project < ActiveRecord::Base has_one :pipelines_email_service has_one :irker_service has_one :pivotaltracker_service - has_one :hipchat_service has_one :flowdock_service has_one :assembla_service has_one :asana_service @@ -2074,6 +2073,10 @@ class Project < ActiveRecord::Base pool_repository&.link_repository(repository) end + def has_pool_repository? + pool_repository.present? + end + private def merge_requests_allowing_collaboration(source_branch = nil) diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb index 6dae4f3a4a6..80aa2101509 100644 --- a/app/models/project_services/deployment_service.rb +++ b/app/models/project_services/deployment_service.rb @@ -11,7 +11,7 @@ class DeploymentService < Service %w() end - def predefined_variables + def predefined_variables(project:) [] end diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb deleted file mode 100644 index a69b7b4c4b6..00000000000 --- a/app/models/project_services/hipchat_service.rb +++ /dev/null @@ -1,311 +0,0 @@ -# frozen_string_literal: true - -class HipchatService < Service - include ActionView::Helpers::SanitizeHelper - - MAX_COMMITS = 3 - HIPCHAT_ALLOWED_TAGS = %w[ - a b i strong em br img pre code - table th tr td caption colgroup col thead tbody tfoot - ul ol li dl dt dd - ].freeze - - prop_accessor :token, :room, :server, :color, :api_version - boolean_accessor :notify_only_broken_pipelines, :notify - validates :token, presence: true, if: :activated? - - def initialize_properties - if properties.nil? - self.properties = {} - self.notify_only_broken_pipelines = true - end - end - - def title - 'HipChat' - end - - def description - 'Private group chat and IM' - end - - def self.to_param - 'hipchat' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: 'Room token', required: true }, - { type: 'text', name: 'room', placeholder: 'Room name or ID' }, - { type: 'checkbox', name: 'notify' }, - { type: 'select', name: 'color', choices: %w(yellow red green purple gray random) }, - { type: 'text', name: 'api_version', - placeholder: 'Leave blank for default (v2)' }, - { type: 'text', name: 'server', - placeholder: 'Leave blank for default. https://hipchat.example.com' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' } - ] - end - - def self.supported_events - %w(push issue confidential_issue merge_request note confidential_note tag_push pipeline) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - message = create_message(data) - return unless message.present? - - gate[room].send('GitLab', message, message_options(data)) # rubocop:disable GitlabSecurity/PublicSend - end - - def test(data) - begin - result = execute(data) - rescue StandardError => error - return { success: false, result: error } - end - - { success: true, result: result } - end - - private - - def gate - options = { api_version: api_version.present? ? api_version : 'v2' } - options[:server_url] = server unless server.blank? - @gate ||= HipChat::Client.new(token, options) - end - - def message_options(data = nil) - { notify: notify.present? && Gitlab::Utils.to_boolean(notify), color: message_color(data) } - end - - def create_message(data) - object_kind = data[:object_kind] - - case object_kind - when "push", "tag_push" - create_push_message(data) - when "issue" - create_issue_message(data) unless update?(data) - when "merge_request" - create_merge_request_message(data) unless update?(data) - when "note" - create_note_message(data) - when "pipeline" - create_pipeline_message(data) if should_pipeline_be_notified?(data) - end - end - - def render_line(text) - markdown(text.lines.first.chomp, pipeline: :single_line) if text - end - - def create_push_message(push) - ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch' - ref = Gitlab::Git.ref_name(push[:ref]) - - before = push[:before] - after = push[:after] - - message = [] - message << "#{push[:user_name]} " - - if Gitlab::Git.blank_ref?(before) - message << "pushed new #{ref_type} <a href=\""\ - "#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"\ - " to #{project_link}\n" - elsif Gitlab::Git.blank_ref?(after) - message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n" - else - message << "pushed to #{ref_type} <a href=\""\ - "#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> " - message << "of <a href=\"#{project.web_url}\">#{project.full_name.gsub!(/\s/, '')}</a> " - message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)" - - push[:commits].take(MAX_COMMITS).each do |commit| - message << "<br /> - #{render_line(commit[:message])} (<a href=\"#{commit[:url]}\">#{commit[:id][0..5]}</a>)" - end - - if push[:commits].count > MAX_COMMITS - message << "<br />... #{push[:commits].count - MAX_COMMITS} more commits" - end - end - - message.join - end - - def markdown(text, options = {}) - return "" unless text - - context = { - project: project, - pipeline: :email - } - - Banzai.render(text, context) - - context.merge!(options) - - html = Banzai.render_and_post_process(text, context) - sanitized_html = sanitize(html, tags: HIPCHAT_ALLOWED_TAGS, attributes: %w[href title alt]) - - sanitized_html.truncate(200, separator: ' ', omission: '...') - end - - def create_issue_message(data) - user_name = data[:user][:name] - - obj_attr = data[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - title = render_line(obj_attr[:title]) - state = obj_attr[:state] - issue_iid = obj_attr[:iid] - issue_url = obj_attr[:url] - description = obj_attr[:description] - - issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>" - - message = ["#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"] - message << "<pre>#{markdown(description)}</pre>" - - message.join - end - - def create_merge_request_message(data) - user_name = data[:user][:name] - - obj_attr = data[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - merge_request_id = obj_attr[:iid] - state = obj_attr[:state] - description = obj_attr[:description] - title = render_line(obj_attr[:title]) - - merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}" - merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>" - message = ["#{user_name} #{state} #{merge_request_link} in " \ - "#{project_link}: <b>#{title}</b>"] - - message << "<pre>#{markdown(description)}</pre>" - message.join - end - - def format_title(title) - "<b>#{render_line(title)}</b>" - end - - def create_note_message(data) - data = HashWithIndifferentAccess.new(data) - user_name = data[:user][:name] - - obj_attr = HashWithIndifferentAccess.new(data[:object_attributes]) - note = obj_attr[:note] - note_url = obj_attr[:url] - noteable_type = obj_attr[:noteable_type] - commit_id = nil - - case noteable_type - when "Commit" - commit_attr = HashWithIndifferentAccess.new(data[:commit]) - commit_id = commit_attr[:id] - subject_desc = commit_id - subject_desc = Commit.truncate_sha(subject_desc) - subject_type = "commit" - title = format_title(commit_attr[:message]) - when "Issue" - subj_attr = HashWithIndifferentAccess.new(data[:issue]) - subject_id = subj_attr[:iid] - subject_desc = "##{subject_id}" - subject_type = "issue" - title = format_title(subj_attr[:title]) - when "MergeRequest" - subj_attr = HashWithIndifferentAccess.new(data[:merge_request]) - subject_id = subj_attr[:iid] - subject_desc = "!#{subject_id}" - subject_type = "merge request" - title = format_title(subj_attr[:title]) - when "Snippet" - subj_attr = HashWithIndifferentAccess.new(data[:snippet]) - subject_id = subj_attr[:id] - subject_desc = "##{subject_id}" - subject_type = "snippet" - title = format_title(subj_attr[:title]) - end - - subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>" - message = ["#{user_name} commented on #{subject_html} in #{project_link}: "] - message << title - - message << "<pre>#{markdown(note, ref: commit_id)}</pre>" - message.join - end - - def create_pipeline_message(data) - pipeline_attributes = data[:object_attributes] - pipeline_id = pipeline_attributes[:id] - ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch' - ref = pipeline_attributes[:ref] - user_name = (data[:user] && data[:user][:name]) || 'API' - status = pipeline_attributes[:status] - duration = pipeline_attributes[:duration] - - branch_link = "<a href=\"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>" - pipeline_url = "<a href=\"#{project_url}/pipelines/#{pipeline_id}\">##{pipeline_id}</a>" - - "#{project_link}: Pipeline #{pipeline_url} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)" - end - - def message_color(data) - pipeline_status_color(data) || color || 'yellow' - end - - def pipeline_status_color(data) - return unless data && data[:object_kind] == 'pipeline' - - case data[:object_attributes][:status] - when 'success' - 'green' - else - 'red' - end - end - - def project_name - project.full_name.gsub(/\s/, '') - end - - def project_url - project.web_url - end - - def project_link - "<a href=\"#{project_url}\">#{project_name}</a>" - end - - def update?(data) - data[:object_attributes][:action] == 'update' - end - - def humanized_status(status) - case status - when 'success' - 'passed' - else - status - end - end - - def should_pipeline_be_notified?(data) - case data[:object_attributes][:status] - when 'success' - !notify_only_broken_pipelines? - when 'failed' - true - else - false - end - end -end diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb index 6f639e5a7b2..6c507c47752 100644 --- a/app/models/releases/link.rb +++ b/app/models/releases/link.rb @@ -6,7 +6,7 @@ module Releases belongs_to :release - validates :url, presence: true, url: true, uniqueness: { scope: :release } + validates :url, presence: true, url: { protocols: %w(http https ftp) }, uniqueness: { scope: :release } validates :name, presence: true, uniqueness: { scope: :release } scope :sorted, -> { order(created_at: :desc) } diff --git a/app/models/repository.rb b/app/models/repository.rb index 7c50b4488e5..ed55a6e572b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -288,13 +288,16 @@ class Repository # Rugged seems to throw a `ReferenceError` when given branch_names rather # than SHA-1 hashes number_commits_behind, number_commits_ahead = - raw_repository.count_commits_between( + raw_repository.diverging_commit_count( @root_ref_hash, branch.dereferenced_target.sha, - left_right: true, max_count: MAX_DIVERGING_COUNT) - { behind: number_commits_behind, ahead: number_commits_ahead } + if number_commits_behind + number_commits_ahead >= MAX_DIVERGING_COUNT + { distance: MAX_DIVERGING_COUNT } + else + { behind: number_commits_behind, ahead: number_commits_ahead } + end end end diff --git a/app/models/service.rb b/app/models/service.rb index 9dcb0aab0a3..3461e0bfe70 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -255,7 +255,6 @@ class Service < ActiveRecord::Base external_wiki flowdock hangouts_chat - hipchat irker jira kubernetes diff --git a/app/models/user.rb b/app/models/user.rb index 24101eda0b1..fd32d838e53 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -275,6 +275,7 @@ class User < ApplicationRecord scope :confirmed, -> { where.not(confirmed_at: nil) } scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) } scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) } + scope :with_emails, -> { preload(:emails) } # Limits the users to those that have TODOs, optionally in the given state. # @@ -1167,6 +1168,10 @@ class User < ApplicationRecord Gitlab::ObjectHierarchy.new(owned_or_maintainers_groups).base_and_descendants end + def manageable_groups_with_routes + manageable_groups.eager_load(:route).order('routes.path') + end + def namespaces namespace_ids = groups.pluck(:id) namespace_ids.push(namespace.id) |