diff options
author | Pawel Chojnacki <pawel@chojnacki.ws> | 2018-03-06 16:08:11 +0100 |
---|---|---|
committer | Pawel Chojnacki <pawel@chojnacki.ws> | 2018-03-06 16:08:11 +0100 |
commit | 4ff8db0d2e8371dfdae2ddef8a8595c1ef80c3d4 (patch) | |
tree | 3ff849c51603151baaf85ee0436d9c2f3e47915d /app/models | |
parent | 60f5250893626620920d2f108df3b3e98d974f0e (diff) | |
parent | 5e8138aa54492dd3ace42d889ba01f82e8e19c83 (diff) | |
download | gitlab-ce-4ff8db0d2e8371dfdae2ddef8a8595c1ef80c3d4.tar.gz |
Merge remote-tracking branch 'upstream/master' into 5029-support-cluster-metrics-ce5029-support-cluster-metrics-ce
# Conflicts:
# spec/models/clusters/applications/prometheus_spec.rb
Diffstat (limited to 'app/models')
42 files changed, 347 insertions, 134 deletions
diff --git a/app/models/badge.rb b/app/models/badge.rb new file mode 100644 index 00000000000..f7e10c2ebfc --- /dev/null +++ b/app/models/badge.rb @@ -0,0 +1,51 @@ +class Badge < ActiveRecord::Base + # This structure sets the placeholders that the urls + # can have. This hash also sets which action to ask when + # the placeholder is found. + PLACEHOLDERS = { + 'project_path' => :full_path, + 'project_id' => :id, + 'default_branch' => :default_branch, + 'commit_sha' => ->(project) { project.commit&.sha } + }.freeze + + # This regex is built dynamically using the keys from the PLACEHOLDER struct. + # So, we can easily add new placeholder just by modifying the PLACEHOLDER hash. + # This regex will build the new PLACEHOLDER_REGEX with the new information + PLACEHOLDERS_REGEX = /(#{PLACEHOLDERS.keys.join('|')})/.freeze + + default_scope { order_created_at_asc } + + scope :order_created_at_asc, -> { reorder(created_at: :asc) } + + validates :link_url, :image_url, url_placeholder: { protocols: %w(http https), placeholder_regex: PLACEHOLDERS_REGEX } + validates :type, presence: true + + def rendered_link_url(project = nil) + build_rendered_url(link_url, project) + end + + def rendered_image_url(project = nil) + build_rendered_url(image_url, project) + end + + private + + def build_rendered_url(url, project = nil) + return url unless valid? && project + + Gitlab::StringPlaceholderReplacer.replace_string_placeholders(url, PLACEHOLDERS_REGEX) do |arg| + replace_placeholder_action(PLACEHOLDERS[arg], project) + end + end + + # The action param represents the :symbol or Proc to call in order + # to retrieve the return value from the project. + # This method checks if it is a Proc and use the call method, and if it is + # a symbol just send the action + def replace_placeholder_action(action, project) + return unless project + + action.is_a?(Proc) ? action.call(project) : project.public_send(action) # rubocop:disable GitlabSecurity/PublicSend + end +end diff --git a/app/models/badges/group_badge.rb b/app/models/badges/group_badge.rb new file mode 100644 index 00000000000..f4b2bdecdcc --- /dev/null +++ b/app/models/badges/group_badge.rb @@ -0,0 +1,5 @@ +class GroupBadge < Badge + belongs_to :group + + validates :group, presence: true +end diff --git a/app/models/badges/project_badge.rb b/app/models/badges/project_badge.rb new file mode 100644 index 00000000000..3945b376052 --- /dev/null +++ b/app/models/badges/project_badge.rb @@ -0,0 +1,15 @@ +class ProjectBadge < Badge + belongs_to :project + + validates :project, presence: true + + def rendered_link_url(project = nil) + project ||= self.project + super + end + + def rendered_image_url(project = nil) + project ||= self.project + super + end +end diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb index f321db75eeb..fbd0f123341 100644 --- a/app/models/chat_name.rb +++ b/app/models/chat_name.rb @@ -1,4 +1,6 @@ class ChatName < ActiveRecord::Base + LAST_USED_AT_INTERVAL = 1.hour + belongs_to :service belongs_to :user @@ -9,4 +11,23 @@ class ChatName < ActiveRecord::Base validates :user_id, uniqueness: { scope: [:service_id] } validates :chat_id, uniqueness: { scope: [:service_id, :team_id] } + + # Updates the "last_used_timestamp" but only if it wasn't already updated + # recently. + # + # The throttling this method uses is put in place to ensure that high chat + # traffic doesn't result in many UPDATE queries being performed. + def update_last_used_at + return unless update_last_used_at? + + obtained = Gitlab::ExclusiveLease + .new("chat_name/last_used_at/#{id}", timeout: LAST_USED_AT_INTERVAL.to_i) + .try_obtain + + touch(:last_used_at) if obtained + end + + def update_last_used_at? + last_used_at.nil? || last_used_at > LAST_USED_AT_INTERVAL.ago + end end diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb index afeae69ba39..1dd0e050ba9 100644 --- a/app/models/ci/group_variable.rb +++ b/app/models/ci/group_variable.rb @@ -6,7 +6,10 @@ module Ci belongs_to :group - validates :key, uniqueness: { scope: :group_id } + validates :key, uniqueness: { + scope: :group_id, + message: "(%{value}) has already been taken" + } scope :unprotected, -> { where(protected: false) } end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 13c784bea0d..609620a62bb 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -49,7 +49,7 @@ module Ci ref_protected: 1 } - cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at + cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at, :ip_address # Searches for runners matching the given query. # @@ -157,7 +157,7 @@ module Ci end def update_cached_info(values) - values = values&.slice(:version, :revision, :platform, :architecture) || {} + values = values&.slice(:version, :revision, :platform, :architecture, :ip_address) || {} values[:contacted_at] = Time.now cache_attributes(values) diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 67d3ec81b6f..7c71291de84 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -6,7 +6,10 @@ module Ci belongs_to :project - validates :key, uniqueness: { scope: [:project_id, :environment_scope] } + validates :key, uniqueness: { + scope: [:project_id, :environment_scope], + message: "(%{value}) has already been taken" + } scope :unprotected, -> { where(protected: false) } end diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 193bb48e54d..58de3448577 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -15,7 +15,7 @@ module Clusters end def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, install_helm: true) + Gitlab::Kubernetes::Helm::InitCommand.new(name) end end end diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index aa5cf97756f..27fc3b85465 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -5,6 +5,8 @@ module Clusters include ::Clusters::Concerns::ApplicationCore include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData + include AfterCommitQueue default_value_for :ingress_type, :nginx default_value_for :version, :nginx @@ -13,16 +15,34 @@ module Clusters nginx: 1 } + FETCH_IP_ADDRESS_DELAY = 30.seconds + + state_machine :status do + before_transition any => [:installed] do |application| + application.run_after_commit do + ClusterWaitForIngressIpAddressWorker.perform_in( + FETCH_IP_ADDRESS_DELAY, application.name, application.id) + end + end + end + def chart 'stable/nginx-ingress' end - def chart_values_file - "#{Rails.root}/vendor/#{name}/values.yaml" + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values + ) end - def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart, chart_values_file: chart_values_file) + def schedule_status_update + return unless installed? + return if external_ip + + ClusterWaitForIngressIpAddressWorker.perform_async(name, id) end end end diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index ba63d0f3c64..7b25d8c4089 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -9,6 +9,7 @@ module Clusters include ::Clusters::Concerns::ApplicationCore include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData default_value_for :version, VERSION @@ -32,12 +33,12 @@ module Clusters 80 end - def chart_values_file - "#{Rails.root}/vendor/#{name}/values.yaml" - end - def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart, chart_values_file: chart_values_file) + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values + ) end def prometheus_client diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb new file mode 100644 index 00000000000..16efe90fa27 --- /dev/null +++ b/app/models/clusters/applications/runner.rb @@ -0,0 +1,69 @@ +module Clusters + module Applications + class Runner < ActiveRecord::Base + VERSION = '0.1.13'.freeze + + self.table_name = 'clusters_applications_runners' + + include ::Clusters::Concerns::ApplicationCore + include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData + + belongs_to :runner, class_name: 'Ci::Runner', foreign_key: :runner_id + delegate :project, to: :cluster + + default_value_for :version, VERSION + + def chart + "#{name}/gitlab-runner" + end + + def repository + 'https://charts.gitlab.io' + end + + def values + content_values.to_yaml + end + + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values, + repository: repository + ) + end + + private + + def ensure_runner + runner || create_and_assign_runner + end + + def create_and_assign_runner + transaction do + project.runners.create!(name: 'kubernetes-cluster', tag_list: %w(kubernetes cluster)).tap do |runner| + update!(runner_id: runner.id) + end + end + end + + def gitlab_url + Gitlab::Routing.url_helpers.root_url(only_path: false) + end + + def specification + { + "gitlabUrl" => gitlab_url, + "runnerToken" => ensure_runner.token, + "runners" => { "privileged" => privileged } + } + end + + def content_values + YAML.load_file(chart_values_file).deep_merge!(specification) + end + end + end +end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 5ecbd4cbceb..49eb069016a 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -7,7 +7,8 @@ module Clusters APPLICATIONS = { Applications::Helm.application_name => Applications::Helm, Applications::Ingress.application_name => Applications::Ingress, - Applications::Prometheus.application_name => Applications::Prometheus + Applications::Prometheus.application_name => Applications::Prometheus, + Applications::Runner.application_name => Applications::Runner }.freeze belongs_to :user @@ -23,6 +24,7 @@ module Clusters has_one :application_helm, class_name: 'Clusters::Applications::Helm' has_one :application_ingress, class_name: 'Clusters::Applications::Ingress' has_one :application_prometheus, class_name: 'Clusters::Applications::Prometheus' + has_one :application_runner, class_name: 'Clusters::Applications::Runner' accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true @@ -65,7 +67,8 @@ module Clusters [ application_helm || build_application_helm, application_ingress || build_application_ingress, - application_prometheus || build_application_prometheus + application_prometheus || build_application_prometheus, + application_runner || build_application_runner ] end diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb index a98fa85a5ff..623b836c0ed 100644 --- a/app/models/clusters/concerns/application_core.rb +++ b/app/models/clusters/concerns/application_core.rb @@ -23,6 +23,11 @@ module Clusters def name self.class.application_name end + + def schedule_status_update + # Override if you need extra data synchronized + # from K8s after installation + end end end end diff --git a/app/models/clusters/concerns/application_data.rb b/app/models/clusters/concerns/application_data.rb new file mode 100644 index 00000000000..96ac757e99e --- /dev/null +++ b/app/models/clusters/concerns/application_data.rb @@ -0,0 +1,23 @@ +module Clusters + module Concerns + module ApplicationData + extend ActiveSupport::Concern + + included do + def repository + nil + end + + def values + File.read(chart_values_file) + end + + private + + def chart_values_file + "#{Rails.root}/vendor/#{name}/values.yaml" + end + end + end + end +end diff --git a/app/models/commit.rb b/app/models/commit.rb index add5fcf0e79..b9106309142 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -19,6 +19,7 @@ class Commit attr_accessor :project, :author attr_accessor :redacted_description_html attr_accessor :redacted_title_html + attr_reader :gpg_commit DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines] @@ -110,6 +111,7 @@ class Commit @raw = raw_commit @project = project @statuses = {} + @gpg_commit = Gitlab::Gpg::Commit.new(self) if project end def id @@ -452,8 +454,4 @@ class Commit def merged_merge_request_no_cache(user) MergeRequestsFinder.new(user, project_id: project.id).find_by(merge_commit_sha: id) if merge_commit? end - - def gpg_commit - @gpg_commit ||= Gitlab::Gpg::Commit.new(self) - end end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 3469d5d795c..9fb5b7efec6 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -141,7 +141,7 @@ class CommitStatus < ActiveRecord::Base end def group_name - name.to_s.gsub(%r{\d+[\s:/\\]+\d+\s*}, '').strip + name.to_s.gsub(%r{\d+[\.\s:/\\]+\d+\s*}, '').strip end def failed_but_allowed? diff --git a/app/models/concerns/access_requestable.rb b/app/models/concerns/access_requestable.rb index 62bc6b809f4..d502e7e54c6 100644 --- a/app/models/concerns/access_requestable.rb +++ b/app/models/concerns/access_requestable.rb @@ -8,6 +8,6 @@ module AccessRequestable extend ActiveSupport::Concern def request_access(user) - Members::RequestAccessService.new(self, user).execute + Members::RequestAccessService.new(user).execute(self) end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 7049f340c9d..4560bc23193 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -19,6 +19,7 @@ module Issuable include AfterCommitQueue include Sortable include CreatedAtFilterable + include UpdatedAtFilterable # This object is used to gather issuable meta data for displaying # upvotes, downvotes, notes and closing merge requests count for issues and merge requests diff --git a/app/models/concerns/updated_at_filterable.rb b/app/models/concerns/updated_at_filterable.rb new file mode 100644 index 00000000000..edb423b7828 --- /dev/null +++ b/app/models/concerns/updated_at_filterable.rb @@ -0,0 +1,12 @@ +module UpdatedAtFilterable + extend ActiveSupport::Concern + + included do + scope :updated_before, ->(date) { where(scoped_table[:updated_at].lteq(date)) } + scope :updated_after, ->(date) { where(scoped_table[:updated_at].gteq(date)) } + + def self.scoped_table + arel_table.alias(table_name) + end + end +end diff --git a/app/models/cycle_analytics.rb b/app/models/cycle_analytics.rb index d2e626c22e8..b34d1382d43 100644 --- a/app/models/cycle_analytics.rb +++ b/app/models/cycle_analytics.rb @@ -6,6 +6,12 @@ class CycleAnalytics @options = options end + def all_medians_per_stage + STAGES.each_with_object({}) do |stage_name, medians_per_stage| + medians_per_stage[stage_name] = self[stage_name].median + end + end + def summary @summary ||= ::Gitlab::CycleAnalytics::StageSummary.new(@project, from: @options[:from], diff --git a/app/models/event.rb b/app/models/event.rb index 75538ba196c..be0fc7efa9a 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -158,7 +158,7 @@ class Event < ActiveRecord::Base def project_name if project - project.name_with_namespace + project.full_name else "(deleted project)" end diff --git a/app/models/group.rb b/app/models/group.rb index 75bf013ecd2..201505c3d3c 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -31,6 +31,8 @@ class Group < Namespace has_many :uploads, as: :model, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent + has_many :badges, class_name: 'GroupBadge' + accepts_nested_attributes_for :variables, allow_destroy: true validate :visibility_level_allowed_by_projects diff --git a/app/models/identity.rb b/app/models/identity.rb index 2b433e9b988..1011b9f1109 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -17,12 +17,12 @@ class Identity < ActiveRecord::Base end def ldap? - Gitlab::OAuth::Provider.ldap_provider?(provider) + Gitlab::Auth::OAuth::Provider.ldap_provider?(provider) end def self.normalize_uid(provider, uid) - if Gitlab::OAuth::Provider.ldap_provider?(provider) - Gitlab::LDAP::Person.normalize_dn(uid) + if Gitlab::Auth::OAuth::Provider.ldap_provider?(provider) + Gitlab::Auth::LDAP::Person.normalize_dn(uid) else uid.to_s end diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index fc586fa216e..b444812a4cf 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -15,4 +15,8 @@ class LfsObject < ActiveRecord::Base .where(lfs_objects_projects: { id: nil }) .destroy_all end + + def self.calculate_oid(path) + Digest::SHA256.file(path).hexdigest + end end diff --git a/app/models/member.rb b/app/models/member.rb index 2d17795e62d..408e8b2d704 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -128,7 +128,7 @@ class Member < ActiveRecord::Base find_by(invite_token: invite_token) end - def add_user(source, user, access_level, existing_members: nil, current_user: nil, expires_at: nil) + def add_user(source, user, access_level, existing_members: nil, current_user: nil, expires_at: nil, ldap: false) # `user` can be either a User object, User ID or an email to be invited member = retrieve_member(source, user, existing_members) access_level = retrieve_access_level(access_level) @@ -143,11 +143,13 @@ class Member < ActiveRecord::Base if member.request? ::Members::ApproveAccessRequestService.new( - source, current_user, - id: member.id, access_level: access_level - ).execute + ).execute( + member, + skip_authorization: ldap, + skip_log_audit_event: ldap + ) else member.save end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index c1c27ccf3e5..06aa67c600f 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -197,10 +197,6 @@ class MergeRequestDiff < ActiveRecord::Base CompareService.new(project, head_commit_sha).execute(project, sha, straight: true) end - def commits_count - super || merge_request_diff_commits.size - end - private def create_merge_request_diff_files(diffs) diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb index 9357e55b419..22d48c9e661 100644 --- a/app/models/network/commit.rb +++ b/app/models/network/commit.rb @@ -24,12 +24,7 @@ module Network end def parents(map) - @commit.parents.map do |p| - if map.include?(p.id) - map[p.id] - end - end - .compact + map.values_at(*@commit.parent_ids).compact end end end diff --git a/app/models/note.rb b/app/models/note.rb index cac60845a49..d7a67ec277c 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -133,6 +133,7 @@ class Note < ActiveRecord::Base def find_discussion(discussion_id) notes = where(discussion_id: discussion_id).fresh.to_a + return if notes.empty? Discussion.build(notes) diff --git a/app/models/project.rb b/app/models/project.rb index ba278a49688..a11b1e4f554 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -221,6 +221,8 @@ class Project < ActiveRecord::Base has_one :auto_devops, class_name: 'ProjectAutoDevops' has_many :custom_attributes, class_name: 'ProjectCustomAttribute' + has_many :project_badges, class_name: 'ProjectBadge' + accepts_nested_attributes_for :variables, allow_destroy: true accepts_nested_attributes_for :project_feature, update_only: true accepts_nested_attributes_for :import_data @@ -317,42 +319,13 @@ class Project < ActiveRecord::Base # Returns a collection of projects that is either public or visible to the # logged in user. - # - # A caller may pass in a block to modify individual parts of - # the query, e.g. to apply .with_feature_available_for_user on top of it. - # This is useful for performance as we can stick those additional filters - # at the bottom of e.g. the UNION. - # - # Optionally, turning `use_where_in` off leads to returning a - # relation using #from instead of #where. This can perform much better - # but leads to trouble when used in conjunction with AR's #merge method. - def self.public_or_visible_to_user(user = nil, use_where_in: true, &block) - # If we don't get a block passed, use identity to avoid if/else repetitions - block = ->(part) { part } unless block_given? - - return block.call(public_to_user) unless user - - # If the user is allowed to see all projects, - # we can shortcut and just return. - return block.call(all) if user.full_private_access? - - authorized = user - .project_authorizations - .select(1) - .where('project_authorizations.project_id = projects.id') - authorized_projects = block.call(where('EXISTS (?)', authorized)) - - levels = Gitlab::VisibilityLevel.levels_for_user(user) - visible_projects = block.call(where(visibility_level: levels)) - - # We use a UNION here instead of OR clauses since this results in better - # performance. - union = Gitlab::SQL::Union.new([authorized_projects.select('projects.id'), visible_projects.select('projects.id')]) - - if use_where_in - where("projects.id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection + 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 - from("(#{union.to_sql}) AS #{table_name}") + public_to_user end end @@ -371,14 +344,11 @@ class Project < ActiveRecord::Base elsif user column = ProjectFeature.quoted_access_level_column(feature) - authorized = user.project_authorizations.select(1) - .where('project_authorizations.project_id = projects.id') - with_project_feature .where("#{column} IN (?) OR (#{column} = ? AND EXISTS (?))", visible, ProjectFeature::PRIVATE, - authorized) + user.authorizations_for_projects) else with_feature_access_level(feature, visible) end @@ -1798,6 +1768,17 @@ class Project < ActiveRecord::Base .set(import_jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION) end + def badges + return project_badges unless group + + group_badges_rel = GroupBadge.where(group: group.self_and_ancestors) + + union = Gitlab::SQL::Union.new([project_badges.select(:id), + group_badges_rel.select(:id)]) + + Badge.where("id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection + end + private def storage diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 109258d1eb7..4f289e6e215 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -68,7 +68,7 @@ http://app.asana.com/-/account_api' end user = data[:user_name] - project_name = project.name_with_namespace + project_name = project.full_name data[:commits].each do |commit| push_msg = "#{user} pushed to branch #{branch} of #{project_name} ( #{commit[:url]} ):" diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index c3f5b310619..8d7a4fceb08 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -86,7 +86,7 @@ class CampfireService < Service after = push[:after] message = "" - message << "[#{project.name_with_namespace}] " + message << "[#{project.full_name}] " message << "#{push[:user_name]} " if Gitlab::Git.blank_ref?(before) diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index 818cfb01b14..dab0ea1a681 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -99,7 +99,7 @@ class ChatNotificationService < Service def get_message(object_kind, data) case object_kind when "push", "tag_push" - ChatMessage::PushMessage.new(data) + ChatMessage::PushMessage.new(data) if notify_for_ref?(data) when "issue" ChatMessage::IssueMessage.new(data) unless update?(data) when "merge_request" @@ -129,7 +129,7 @@ class ChatNotificationService < Service end def project_name - project.name_with_namespace.gsub(/\s/, '') + project.full_name.gsub(/\s/, '') end def project_url @@ -145,10 +145,16 @@ class ChatNotificationService < Service end def notify_for_ref?(data) - return true if data[:object_attributes][:tag] + return true if data.dig(:object_attributes, :tag) return true unless notify_only_default_branch? - data[:object_attributes][:ref] == project.default_branch + ref = if data[:ref] + Gitlab::Git.ref_name(data[:ref]) + else + data.dig(:object_attributes, :ref) + end + + ref == project.default_branch end def notify_for_pipeline?(data) diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index bfe7ac29c18..f31c3f02af2 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -120,7 +120,7 @@ class HipchatService < Service 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.name_with_namespace.gsub!(/\s/, '')}</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| @@ -274,7 +274,7 @@ class HipchatService < Service end def project_name - project.name_with_namespace.gsub(/\s/, '') + project.full_name.gsub(/\s/, '') end def project_url diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 436a870b0c4..e5035c81df0 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -1,5 +1,7 @@ class JiraService < IssueTrackerService include Gitlab::Routing + include ApplicationHelper + include ActionView::Helpers::AssetUrlHelper validates :url, url: true, presence: true, if: :activated? validates :api_url, url: true, allow_blank: true @@ -268,7 +270,9 @@ class JiraService < IssueTrackerService url: url, title: title, status: status, - icon: { title: 'GitLab', url16x16: 'https://gitlab.com/favicon.ico' } + icon: { + title: 'GitLab', url16x16: asset_url('favicon.ico', host: gitlab_config.url) + } } } end diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb index 4d2037286a2..227d430083d 100644 --- a/app/models/project_services/mattermost_slash_commands_service.rb +++ b/app/models/project_services/mattermost_slash_commands_service.rb @@ -37,7 +37,7 @@ class MattermostSlashCommandsService < SlashCommandsService private def command(params) - pretty_project_name = project.name_with_namespace + pretty_project_name = project.full_name params.merge( auto_complete: true, diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index aa7bd4c3c84..e3a1ca2d45f 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -88,10 +88,10 @@ class PushoverService < Service user: user_key, device: device, priority: priority, - title: "#{project.name_with_namespace}", + title: "#{project.full_name}", message: message, url: data[:project][:web_url], - url_title: "See project #{project.name_with_namespace}" + url_title: "See project #{project.full_name}" } # Sound parameter MUST NOT be sent to API if not selected diff --git a/app/models/project_services/slash_commands_service.rb b/app/models/project_services/slash_commands_service.rb index eb4da68bb7e..37ea45109ae 100644 --- a/app/models/project_services/slash_commands_service.rb +++ b/app/models/project_services/slash_commands_service.rb @@ -30,10 +30,10 @@ class SlashCommandsService < Service def trigger(params) return unless valid_token?(params[:token]) - user = find_chat_user(params) + chat_user = find_chat_user(params) - if user - Gitlab::SlashCommands::Command.new(project, user, params).execute + if chat_user&.user + Gitlab::SlashCommands::Command.new(project, chat_user, params).execute else url = authorize_chat_name_url(params) Gitlab::SlashCommands::Presenters::Access.new(url).authorize diff --git a/app/models/repository.rb b/app/models/repository.rb index 299a3f32a85..1a14afb951a 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -139,7 +139,7 @@ class Repository end end - def commits(ref, path: nil, limit: nil, offset: nil, skip_merges: false, after: nil, before: nil) + def commits(ref = nil, path: nil, limit: nil, offset: nil, skip_merges: false, after: nil, before: nil, all: nil) options = { repo: raw_repository, ref: ref, @@ -149,7 +149,8 @@ class Repository after: after, before: before, follow: Array(path).length == 1, - skip_merges: skip_merges + skip_merges: skip_merges, + all: all } commits = Gitlab::Git::Commit.where(options) @@ -252,7 +253,7 @@ class Repository # branches or tags, but we want to keep some of these commits around, for # example if they have comments or CI builds. def keep_around(sha) - return unless sha && commit_by(oid: sha) + return unless sha.present? && commit_by(oid: sha) return if kept_around?(sha) @@ -589,15 +590,7 @@ class Repository def license_key return unless exists? - # The licensee gem creates a Rugged object from the path: - # https://github.com/benbalter/licensee/blob/v8.7.0/lib/licensee/projects/git_project.rb - begin - Licensee.license(path).try(:key) - # Normally we would rescue Rugged::Error, but that is banned by lint-rugged - # and we need to migrate this endpoint to Gitaly: - # https://gitlab.com/gitlab-org/gitaly/issues/1026 - rescue - end + raw_repository.license_short_name end cache_method :license_key diff --git a/app/models/todo.rb b/app/models/todo.rb index bb5965e20eb..8afacd188e0 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -32,8 +32,6 @@ class Todo < ActiveRecord::Base validates :target_id, presence: true, unless: :for_commit? validates :commit_id, presence: true, if: :for_commit? - default_scope { reorder(id: :desc) } - scope :pending, -> { with_state(:pending) } scope :done, -> { with_state(:done) } @@ -53,10 +51,14 @@ class Todo < ActiveRecord::Base # milestones, but still show something if the user has a URL with that # selected. def sort(method) - case method.to_s - when 'priority', 'label_priority' then order_by_labels_priority - else order_by(method) - end + sorted = + case method.to_s + when 'priority', 'label_priority' then order_by_labels_priority + else order_by(method) + end + + # Break ties with the ID column for pagination + sorted.order(id: :desc) end # Order by priority depending on which issue/merge request the Todo belongs to diff --git a/app/models/tree.rb b/app/models/tree.rb index c89b8eca9be..4c1856b67a8 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -9,10 +9,9 @@ class Tree @repository = repository @sha = sha @path = path - @recursive = recursive git_repo = @repository.raw_repository - @entries = get_entries(git_repo, @sha, @path, recursive: @recursive) + @entries = Gitlab::Git::Tree.where(git_repo, @sha, @path, recursive) end def readme @@ -58,21 +57,4 @@ class Tree def sorted_entries trees + blobs + submodules end - - private - - def get_entries(git_repo, sha, path, recursive: false) - current_path_entries = Gitlab::Git::Tree.where(git_repo, sha, path) - ordered_entries = [] - - current_path_entries.each do |entry| - ordered_entries << entry - - if recursive && entry.dir? - ordered_entries.concat(get_entries(git_repo, sha, entry.path, recursive: true)) - end - end - - ordered_entries - end end diff --git a/app/models/user.rb b/app/models/user.rb index 8610ca27b7f..9c60adf0c90 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -431,7 +431,7 @@ class User < ActiveRecord::Base end def self.non_internal - where(Hash[internal_attributes.zip([[false, nil]] * internal_attributes.size)]) + where(internal_attributes.map { |attr| "#{attr} IS NOT TRUE" }.join(" AND ")) end # @@ -601,6 +601,15 @@ class User < ActiveRecord::Base authorized_projects(min_access_level).exists?({ id: project.id }) end + # Typically used in conjunction with projects table to get projects + # a user has been given access to. + # + # Example use: + # `Project.where('EXISTS(?)', user.authorizations_for_projects)` + def authorizations_for_projects + project_authorizations.select(1).where('project_authorizations.project_id = projects.id') + end + # Returns the projects this user has reporter (or greater) access to, limited # to at most the given projects. # @@ -728,7 +737,7 @@ class User < ActiveRecord::Base def ldap_user? if identities.loaded? - identities.find { |identity| Gitlab::OAuth::Provider.ldap_provider?(identity.provider) && !identity.extern_uid.nil? } + identities.find { |identity| Gitlab::Auth::OAuth::Provider.ldap_provider?(identity.provider) && !identity.extern_uid.nil? } else identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"]) end diff --git a/app/models/user_synced_attributes_metadata.rb b/app/models/user_synced_attributes_metadata.rb index 548b99b69d9..688432a9d67 100644 --- a/app/models/user_synced_attributes_metadata.rb +++ b/app/models/user_synced_attributes_metadata.rb @@ -26,6 +26,6 @@ class UserSyncedAttributesMetadata < ActiveRecord::Base private def sync_profile_from_provider? - Gitlab::OAuth::Provider.sync_profile_from_provider?(provider) + Gitlab::Auth::OAuth::Provider.sync_profile_from_provider?(provider) end end |