diff options
Diffstat (limited to 'app/models')
35 files changed, 256 insertions, 46 deletions
diff --git a/app/models/active_session.rb b/app/models/active_session.rb index 0d9c6a4a1f0..1e01f1d17e6 100644 --- a/app/models/active_session.rb +++ b/app/models/active_session.rb @@ -5,7 +5,8 @@ class ActiveSession attr_accessor :created_at, :updated_at, :session_id, :ip_address, - :browser, :os, :device_name, :device_type + :browser, :os, :device_name, :device_type, + :is_impersonated def current?(session) return false if session_id.nil? || session.id.nil? @@ -31,7 +32,8 @@ class ActiveSession device_type: client.device_type, created_at: user.current_sign_in_at || timestamp, updated_at: timestamp, - session_id: session_id + session_id: session_id, + is_impersonated: request.session[:impersonator_id].present? ) redis.pipelined do diff --git a/app/models/appearance.rb b/app/models/appearance.rb index ff1ecfda684..b9ad676ca47 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -8,12 +8,19 @@ class Appearance < ActiveRecord::Base cache_markdown_field :description cache_markdown_field :new_project_guidelines + cache_markdown_field :header_message, pipeline: :broadcast_message + cache_markdown_field :footer_message, pipeline: :broadcast_message validates :logo, file_size: { maximum: 1.megabyte } validates :header_logo, file_size: { maximum: 1.megabyte } + validates :message_background_color, allow_blank: true, color: true + validates :message_font_color, allow_blank: true, color: true validate :single_appearance_row, on: :create + default_value_for :message_background_color, '#E75E40' + default_value_for :message_font_color, '#FFFFFF' + mount_uploader :logo, AttachmentUploader mount_uploader :header_logo, AttachmentUploader mount_uploader :favicon, FaviconUploader @@ -41,6 +48,14 @@ class Appearance < ActiveRecord::Base logo_system_path(favicon, 'favicon') end + def show_header? + header_message.present? + end + + def show_footer? + footer_message.present? + end + private def logo_system_path(logo, mount_type) 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/build.rb b/app/models/ci/build.rb index 6b2b7e77180..c902e49ee6d 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -46,6 +46,7 @@ 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?, to: :pipeline ## # Since Gitlab 11.5, deployments records started being created right after @@ -441,11 +442,13 @@ module Ci # All variables, including persisted environment variables. # def variables - Gitlab::Ci::Variables::Collection.new - .concat(persisted_variables) - .concat(scoped_variables) - .concat(persisted_environment_variables) - .to_runner_variables + strong_memoize(:variables) do + Gitlab::Ci::Variables::Collection.new + .concat(persisted_variables) + .concat(scoped_variables) + .concat(persisted_environment_variables) + .to_runner_variables + end end ## diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb index da08214963f..33e61cd2111 100644 --- a/app/models/ci/build_trace_chunk.rb +++ b/app/models/ci/build_trace_chunk.rb @@ -18,7 +18,7 @@ module Ci FailedToPersistDataError = Class.new(StandardError) # Note: The ordering of this enum is related to the precedence of persist store. - # The bottom item takes the higest precedence, and the top item takes the lowest precedence. + # The bottom item takes the highest precedence, and the top item takes the lowest precedence. enum data_store: { redis: 1, database: 2, diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 372f6d678f6..d4586219333 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -12,6 +12,10 @@ module Ci include AtomicInternalId include EnumWithNil include HasRef + include ShaAttribute + + sha_attribute :source_sha + sha_attribute :target_sha belongs_to :project, inverse_of: :all_pipelines belongs_to :user @@ -47,6 +51,8 @@ module Ci has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id' has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id' + has_one :chat_data, class_name: 'Ci::PipelineChatData' + accepts_nested_attributes_for :variables, reject_if: :persisted? delegate :id, to: :project, prefix: true @@ -189,6 +195,22 @@ module Ci .sort_by_merge_request_pipelines end + scope :triggered_by_merge_request, -> (merge_request) do + where(source: :merge_request, merge_request: merge_request) + end + + scope :detached_merge_request_pipelines, -> (merge_request) do + triggered_by_merge_request(merge_request).where(target_sha: nil) + end + + scope :merge_request_pipelines, -> (merge_request) do + triggered_by_merge_request(merge_request).where.not(target_sha: nil) + end + + scope :mergeable_merge_request_pipelines, -> (merge_request) do + triggered_by_merge_request(merge_request).where(target_sha: merge_request.target_branch_sha) + end + # Returns the pipelines in descending order (= newest first), optionally # limited to a number of references. # @@ -315,7 +337,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 @@ -622,6 +644,8 @@ module Ci variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s) if merge_request? && merge_request + variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s) + variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA', value: target_sha.to_s) variables.concat(merge_request.predefined_variables) end end @@ -650,9 +674,9 @@ module Ci def all_merge_requests @all_merge_requests ||= if merge_request? - project.merge_requests.where(id: merge_request_id) + MergeRequest.where(id: merge_request_id) else - project.merge_requests.where(source_branch: ref) + MergeRequest.where(source_project_id: project_id, source_branch: ref) end end @@ -706,6 +730,22 @@ module Ci ref == project.default_branch end + def triggered_by_merge_request? + merge_request? && merge_request_id.present? + end + + def detached_merge_request_pipeline? + triggered_by_merge_request? && target_sha.nil? + end + + def merge_request_pipeline? + triggered_by_merge_request? && target_sha.present? + end + + def mergeable_merge_request_pipeline? + triggered_by_merge_request? && target_sha == merge_request.target_branch_sha + end + private def ci_yaml_from_repo diff --git a/app/models/ci/pipeline_chat_data.rb b/app/models/ci/pipeline_chat_data.rb new file mode 100644 index 00000000000..8d37500fec5 --- /dev/null +++ b/app/models/ci/pipeline_chat_data.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Ci + class PipelineChatData < ActiveRecord::Base + self.table_name = 'ci_pipeline_chat_data' + + belongs_to :chat_name + + validates :pipeline_id, presence: true + validates :chat_name_id, presence: true + validates :response_url, presence: true + end +end diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb index 2994aaae4aa..4be4fdb1ff2 100644 --- a/app/models/ci/pipeline_enums.rb +++ b/app/models/ci/pipeline_enums.rb @@ -22,6 +22,7 @@ module Ci schedule: 4, api: 5, external: 6, + chat: 8, merge_request: 10 } end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 5aae31de6e2..d82e11bbb89 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -97,6 +97,7 @@ module Ci scope :order_contacted_at_asc, -> { order(contacted_at: :asc) } scope :order_created_at_desc, -> { order(created_at: :desc) } + scope :with_tags, -> { preload(:tags) } validate :tag_constraints validates :access_level, presence: true 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/applications/runner.rb b/app/models/clusters/applications/runner.rb index f17da0bb7b1..941551dadaa 100644 --- a/app/models/clusters/applications/runner.rb +++ b/app/models/clusters/applications/runner.rb @@ -3,7 +3,7 @@ module Clusters module Applications class Runner < ActiveRecord::Base - VERSION = '0.1.45'.freeze + VERSION = '0.2.0'.freeze self.table_name = 'clusters_applications_runners' diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 7025fc2cc02..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? @@ -99,7 +99,7 @@ module Clusters where('NOT EXISTS (?)', subquery) end - scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.installed) } + scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.available) } scope :preload_knative, -> { preload( diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index 5c0164831bc..1273ed83abe 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -6,7 +6,14 @@ module Clusters extend ActiveSupport::Concern included do - scope :installed, -> { where(status: self.state_machines[:status].states[:installed].value) } + scope :available, -> do + where( + status: [ + self.state_machines[:status].states[:installed].value, + self.state_machines[:status].states[:updated].value + ] + ) + end state_machine :status, initial: :not_installable do state :not_installable, value: -2 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/closed_at_filterable.rb b/app/models/concerns/closed_at_filterable.rb new file mode 100644 index 00000000000..239c2e47611 --- /dev/null +++ b/app/models/concerns/closed_at_filterable.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module ClosedAtFilterable + extend ActiveSupport::Concern + + included do + scope :closed_before, ->(date) { where(scoped_table[:closed_at].lteq(date)) } + scope :closed_after, ->(date) { where(scoped_table[:closed_at].gteq(date)) } + + def self.scoped_table + arel_table.alias(table_name) + end + end +end diff --git a/app/models/concerns/fast_destroy_all.rb b/app/models/concerns/fast_destroy_all.rb index 1e3afd641ed..f862031bce0 100644 --- a/app/models/concerns/fast_destroy_all.rb +++ b/app/models/concerns/fast_destroy_all.rb @@ -11,7 +11,7 @@ # it is difficult to accomplish it. # # This module defines a format to use `delete_all` and delete associated external data. -# Here is an exmaple +# Here is an example # # Situation # - `Project` has many `Ci::BuildTraceChunk` through `Ci::Build` diff --git a/app/models/concerns/iid_routes.rb b/app/models/concerns/iid_routes.rb index b7f99e845ca..3eeb29b6595 100644 --- a/app/models/concerns/iid_routes.rb +++ b/app/models/concerns/iid_routes.rb @@ -4,7 +4,7 @@ module IidRoutes ## # This automagically enforces all related routes to use `iid` instead of `id` # If you want to use `iid` for some routes and `id` for other routes, this module should not to be included, - # instead you should define `iid` or `id` explictly at each route generators. e.g. pipeline_path(project.id, pipeline.iid) + # instead you should define `iid` or `id` explicitly at each route generators. e.g. pipeline_path(project.id, pipeline.iid) def to_param iid.to_s end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 0a77fbeba08..429a63f83cc 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -23,6 +23,7 @@ module Issuable include Sortable include CreatedAtFilterable include UpdatedAtFilterable + include ClosedAtFilterable # 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/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/sha_attribute.rb b/app/models/concerns/sha_attribute.rb index e51b4e22c96..a479bef993c 100644 --- a/app/models/concerns/sha_attribute.rb +++ b/app/models/concerns/sha_attribute.rb @@ -16,6 +16,8 @@ module ShaAttribute # the column is the correct type. In production it should behave like any other attribute. # See https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5502 for more discussion def validate_binary_column_exists!(name) + return unless database_exists? + unless table_exists? warn "WARNING: sha_attribute #{name.inspect} is invalid since the table doesn't exist - you may need to run database migrations" return @@ -35,5 +37,13 @@ module ShaAttribute Gitlab::AppLogger.error "ShaAttribute initialization: #{error.message}" raise end + + def database_exists? + ActiveRecord::Base.connection + + true + rescue + false + end end end diff --git a/app/models/environment.rb b/app/models/environment.rb index 1fc088b12ae..87bdb52b58b 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -243,6 +243,10 @@ class Environment < ActiveRecord::Base self.environment_type || self.name end + def name_without_type + @name_without_type ||= name.delete_prefix("#{environment_type}/") + end + def deployment_platform strong_memoize(:deployment_platform) do project.deployment_platform(environment: self.name) diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 31084c54bdc..57283a78ea9 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -58,7 +58,7 @@ module ErrorTracking def list_sentry_issues(opts = {}) with_reactive_cache('list_issues', opts.stringify_keys) do |result| - { issues: result } + result end end @@ -69,8 +69,10 @@ module ErrorTracking def calculate_reactive_cache(request, opts) case request when 'list_issues' - sentry_client.list_issues(**opts.symbolize_keys) + { issues: sentry_client.list_issues(**opts.symbolize_keys) } end + rescue Sentry::Client::Error => e + { error: e.message } end # http://HOST/api/0/projects/ORG/PROJECT diff --git a/app/models/issue.rb b/app/models/issue.rb index 182c5d3d4b0..0b46e949052 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -66,6 +66,7 @@ class Issue < ActiveRecord::Base scope :preload_associations, -> { preload(:labels, project: :namespace) } scope :public_only, -> { where(confidential: false) } + scope :confidential_only, -> { where(confidential: true) } after_save :expire_etag_cache after_save :ensure_metrics, unless: :imported? diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 2035bffd829..ad4d5be48d4 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -71,7 +71,7 @@ class MergeRequest < ActiveRecord::Base serialize :merge_params, Hash # rubocop:disable Cop/ActiveRecordSerialize - after_create :ensure_merge_request_diff, unless: :importing? + after_create :ensure_merge_request_diff after_update :clear_memoized_shas after_update :reload_diff_if_branch_changed after_save :ensure_metrics @@ -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 @@ -764,6 +764,16 @@ class MergeRequest < ActiveRecord::Base true end + def mergeable_to_ref? + return false if merged? + return false if broken? + + # Given the `merge_ref_path` will have the same + # state the `target_branch` would have. Ideally + # we need to check if it can be merged to it. + project.repository.can_be_merged?(diff_head_sha, target_branch) + end + def ff_merge_possible? project.repository.ancestor?(target_branch_sha, diff_head_sha) end @@ -1077,6 +1087,10 @@ class MergeRequest < ActiveRecord::Base "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head" end + def merge_ref_path + "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/merge" + end + def in_locked_state begin lock_mr @@ -1322,7 +1336,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..351a662ae83 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 @@ -25,6 +22,8 @@ class MergeRequestDiff < ActiveRecord::Base has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) } + validates :base_commit_sha, :head_commit_sha, :start_commit_sha, sha: true + state_machine :state, initial: :empty do event :clean do transition any => :without_files diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 6da3bb7bfb7..ecbeb24ee0a 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -40,9 +40,12 @@ module Network # Get commits from repository # def collect_commits - find_commits(count_to_display_commit_in_center).map do |commit| - # Decorate with app/model/network/commit.rb - Network::Commit.new(commit) + # https://gitlab.com/gitlab-org/gitlab-ce/issues/58013 + Gitlab::GitalyClient.allow_n_plus_1_calls do + find_commits(count_to_display_commit_in_center).map do |commit| + # Decorate with app/model/network/commit.rb + Network::Commit.new(commit) + end end end diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 9f16eefe074..481c1d963c6 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -153,7 +153,7 @@ class NotificationRecipient user.global_notification_setting end - # Returns the notificaton_setting of the lowest group in hierarchy with non global level + # Returns the notification_setting of the lowest group in hierarchy with non global level def closest_non_global_group_notification_settting return unless @group return if indexed_group_notification_settings.empty? 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 c72d3a3b725..b016a65f0bb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -160,6 +160,7 @@ class Project < ActiveRecord::Base has_one :pushover_service has_one :jira_service has_one :redmine_service + has_one :youtrack_service has_one :custom_issue_tracker_service has_one :bugzilla_service has_one :gitlab_issue_tracker_service, inverse_of: :project @@ -248,10 +249,10 @@ class Project < ActiveRecord::Base has_many :container_repositories, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :commit_statuses - # The relation :all_pipelines is intented to be used when we want to get the + # The relation :all_pipelines is intended to be used when we want to get the # whole list of pipelines associated to the project has_many :all_pipelines, class_name: 'Ci::Pipeline', inverse_of: :project - # The relation :ci_pipelines is intented to be used when we want to get only + # The relation :ci_pipelines is intended to be used when we want to get only # those pipeline which are directly related to CI. There are # other pipelines, like webide ones, that we won't retrieve # if we use this relation. @@ -305,6 +306,7 @@ class Project < ActiveRecord::Base delegate :group_runners_enabled, :group_runners_enabled=, :group_runners_enabled?, to: :ci_cd_settings delegate :group_clusters_enabled?, to: :group, allow_nil: true delegate :root_ancestor, to: :namespace, allow_nil: true + delegate :last_pipeline, to: :commit, allow_nil: true # Validations validates :creator, presence: true, on: :create @@ -595,6 +597,14 @@ class Project < ActiveRecord::Base end end + def ci_pipelines + if builds_enabled? + super + else + super.external + end + end + # returns all ancestor-groups upto but excluding the given namespace # when no namespace is given, all ancestors upto the top are returned def ancestors_upto(top = nil, hierarchy_order: nil) @@ -1206,7 +1216,7 @@ class Project < ActiveRecord::Base "#{web_url}.git" end - # Is overriden in EE + # Is overridden in EE def lfs_http_url_to_repo(_) http_url_to_repo end @@ -1829,7 +1839,7 @@ class Project < ActiveRecord::Base # Set repository as writable again def set_repository_writable! with_lock do - update_column(repository_read_only, false) + update_column(:repository_read_only, false) end end @@ -1916,6 +1926,14 @@ class Project < ActiveRecord::Base persisted? && path_changed? end + def human_merge_method + if merge_method == :ff + 'Fast-forward' + else + merge_method.to_s.humanize + end + end + def merge_method if self.merge_requests_ff_only_enabled :ff diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb index 60cb2d380d5..c68a9d923c8 100644 --- a/app/models/project_services/prometheus_service.rb +++ b/app/models/project_services/prometheus_service.rb @@ -71,7 +71,7 @@ class PrometheusService < MonitoringService end def prometheus_client - RestClient::Resource.new(api_url, max_redirects: 0) if api_url && manual_configuration? && active? + RestClient::Resource.new(api_url, max_redirects: 0) if should_return_client? end def prometheus_available? @@ -83,6 +83,10 @@ class PrometheusService < MonitoringService private + def should_return_client? + api_url && manual_configuration? && active? && valid? + end + def synchronize_service_state self.active = prometheus_available? || manual_configuration? diff --git a/app/models/project_services/slack_slash_commands_service.rb b/app/models/project_services/slack_slash_commands_service.rb index 6c82e088231..6a454070fe2 100644 --- a/app/models/project_services/slack_slash_commands_service.rb +++ b/app/models/project_services/slack_slash_commands_service.rb @@ -22,6 +22,10 @@ class SlackSlashCommandsService < SlashCommandsService end end + def chat_responder + ::Gitlab::Chat::Responder::Slack + end + private def format(text) diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb new file mode 100644 index 00000000000..957be685aea --- /dev/null +++ b/app/models/project_services/youtrack_service.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class YoutrackService < IssueTrackerService + validates :project_url, :issues_url, presence: true, public_url: true, if: :activated? + + prop_accessor :description, :project_url, :issues_url + + # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1 + def self.reference_pattern(only_long: false) + if only_long + /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)/ + else + /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)|(#{Issue.reference_prefix}(?<issue>\d+))/ + end + end + + def title + 'YouTrack' + end + + def description + if self.properties && self.properties['description'].present? + self.properties['description'] + else + 'YouTrack issue tracker' + end + end + + def self.to_param + 'youtrack' + end + + def fields + [ + { type: 'text', name: 'description', placeholder: description }, + { type: 'text', name: 'project_url', placeholder: 'Project url', required: true }, + { type: 'text', name: 'issues_url', placeholder: 'Issue url', required: true } + ] + end +end diff --git a/app/models/repository.rb b/app/models/repository.rb index ed55a6e572b..cd761a29618 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -854,6 +854,12 @@ class Repository end end + def merge_to_ref(user, source_sha, merge_request, target_ref, message) + branch = merge_request.target_branch + + raw.merge_to_ref(user, source_sha, branch, target_ref, message) + end + def ff_merge(user, source, target_branch, merge_request: nil) their_commit_id = commit(source)&.id raise 'Invalid merge source' if their_commit_id.nil? diff --git a/app/models/service.rb b/app/models/service.rb index 3461e0bfe70..da523bfa426 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -266,6 +266,7 @@ class Service < ActiveRecord::Base prometheus pushover redmine + youtrack slack_slash_commands slack teamcity diff --git a/app/models/user.rb b/app/models/user.rb index 24101eda0b1..ee51c35d576 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. # @@ -387,7 +388,7 @@ class User < ApplicationRecord find_by(id: user_id) end - def filter(filter_name) + def filter_items(filter_name) case filter_name when 'admins' admins @@ -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) |