diff options
author | Winnie Hellmann <winnie@gitlab.com> | 2018-10-22 22:06:05 +0200 |
---|---|---|
committer | Winnie Hellmann <winnie@gitlab.com> | 2018-10-22 22:06:05 +0200 |
commit | 53be95daf41fc4e59deab149485210835e7e54cd (patch) | |
tree | 3f377dcc6289049581e2473b7e12f260e774784f /app/models | |
parent | 3fb7a1f97a812b7b2b5e80a8a0575cb7bfd2d3c4 (diff) | |
parent | d6be7ed79557ce31a5d0062ceea00c877157a6c7 (diff) | |
download | gitlab-ce-53be95daf41fc4e59deab149485210835e7e54cd.tar.gz |
Merge branch 'master' into scheduled-manual-jobs-environment-play-buttons
Conflicts:
spec/javascripts/environments/environment_actions_spec.js
Diffstat (limited to 'app/models')
26 files changed, 241 insertions, 193 deletions
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 65a2f760f93..b66ec0ffab6 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -4,6 +4,7 @@ class ApplicationSetting < ActiveRecord::Base include CacheableAttributes include CacheMarkdownField include TokenAuthenticatable + include IgnorableColumn add_authentication_token_field :runners_registration_token add_authentication_token_field :health_check_access_token @@ -27,6 +28,14 @@ class ApplicationSetting < ActiveRecord::Base serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize + ignore_column :circuitbreaker_failure_count_threshold + ignore_column :circuitbreaker_failure_reset_time + ignore_column :circuitbreaker_storage_timeout + ignore_column :circuitbreaker_access_retries + ignore_column :circuitbreaker_check_interval + ignore_column :koding_url + ignore_column :koding_enabled + cache_markdown_field :sign_in_text cache_markdown_field :help_page_text cache_markdown_field :shared_runners_text, pipeline: :plain_markdown @@ -93,10 +102,6 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :unique_ips_limit_enabled - validates :koding_url, - presence: true, - if: :koding_enabled - validates :plantuml_url, presence: true, if: :plantuml_enabled @@ -150,17 +155,6 @@ class ApplicationSetting < ActiveRecord::Base presence: true, numericality: { greater_than_or_equal_to: 0 } - validates :circuitbreaker_failure_count_threshold, - :circuitbreaker_failure_reset_time, - :circuitbreaker_storage_timeout, - :circuitbreaker_check_interval, - presence: true, - numericality: { only_integer: true, greater_than_or_equal_to: 0 } - - validates :circuitbreaker_access_retries, - presence: true, - numericality: { only_integer: true, greater_than_or_equal_to: 1 } - validates :gitaly_timeout_default, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } @@ -256,8 +250,6 @@ class ApplicationSetting < ActiveRecord::Base housekeeping_gc_period: 200, housekeeping_incremental_repack_period: 10, import_sources: Settings.gitlab['import_sources'], - koding_enabled: false, - koding_url: nil, max_artifacts_size: Settings.artifacts['max_size'], max_attachment_size: Settings.gitlab['max_attachment_size'], mirror_available: true, diff --git a/app/models/blob.rb b/app/models/blob.rb index acc64ffca67..31a839274b5 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -162,7 +162,7 @@ class Blob < SimpleDelegator if stored_externally? if rich_viewer rich_viewer.binary? - elsif Linguist::Language.find_by_extension(name).any? + elsif known_extension? false elsif _mime_type _mime_type.binary? diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index cb73fc74bb6..2b28b702b05 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -27,11 +27,15 @@ module Ci metadata: :gzip, trace: :raw, junit: :gzip, - codequality: :gzip, - sast: :gzip, - dependency_scanning: :gzip, - container_scanning: :gzip, - dast: :gzip + + # All these file formats use `raw` as we need to store them uncompressed + # for Frontend to fetch the files and do analysis + # When they will be only used by backend, they can be `gzipped`. + codequality: :raw, + sast: :raw, + dependency_scanning: :raw, + container_scanning: :raw, + dast: :raw }.freeze belongs_to :project @@ -100,7 +104,8 @@ module Ci } FILE_FORMAT_ADAPTERS = { - gzip: Gitlab::Ci::Build::Artifacts::GzipFileAdapter + gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream, + raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream }.freeze def valid_file_format? diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb index 7be6a14f585..e43a0fd1786 100644 --- a/app/models/clusters/applications/jupyter.rb +++ b/app/models/clusters/applications/jupyter.rb @@ -19,7 +19,7 @@ module Clusters def set_initial_status return unless not_installable? - if cluster&.application_ingress_installed? && cluster.application_ingress.external_ip + if cluster&.application_ingress_available? && cluster.application_ingress.external_ip self.status = 'installable' end end diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb index a4a2e2b79a6..43bf852c7ec 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.31'.freeze + VERSION = '0.1.34'.freeze self.table_name = 'clusters_applications_runners' diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index d7011ef447a..20d53b8e620 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -43,8 +43,9 @@ module Clusters delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true - delegate :installed?, to: :application_helm, prefix: true, allow_nil: true - delegate :installed?, to: :application_ingress, prefix: true, allow_nil: true + delegate :available?, to: :application_helm, prefix: true, allow_nil: true + delegate :available?, to: :application_ingress, prefix: true, allow_nil: true + delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true enum platform_type: { kubernetes: 1 diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb index e3deedfb036..683b45331f6 100644 --- a/app/models/clusters/concerns/application_core.rb +++ b/app/models/clusters/concerns/application_core.rb @@ -15,7 +15,7 @@ module Clusters def set_initial_status return unless not_installable? - self.status = 'installable' if cluster&.application_helm_installed? + self.status = 'installable' if cluster&.application_helm_available? end def self.application_name diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb index a9df59fc059..93bdf9c223d 100644 --- a/app/models/clusters/concerns/application_status.rb +++ b/app/models/clusters/concerns/application_status.rb @@ -66,6 +66,10 @@ module Clusters end end end + + def available? + installed? || updated? + end end end end diff --git a/app/models/concerns/blob_like.rb b/app/models/concerns/blob_like.rb index e96fefe81c4..f20f01486a5 100644 --- a/app/models/concerns/blob_like.rb +++ b/app/models/concerns/blob_like.rb @@ -2,7 +2,7 @@ module BlobLike extend ActiveSupport::Concern - include Linguist::BlobHelper + include Gitlab::BlobHelper def id raise NotImplementedError diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb index 85229cded5d..045bf392ac8 100644 --- a/app/models/concerns/relative_positioning.rb +++ b/app/models/concerns/relative_positioning.rb @@ -12,6 +12,49 @@ module RelativePositioning after_save :save_positionable_neighbours end + class_methods do + def move_to_end(objects) + parent_ids = objects.map(&:parent_ids).flatten.uniq + max_relative_position = in_parents(parent_ids).maximum(:relative_position) || START_POSITION + objects = objects.reject(&:relative_position) + + self.transaction do + objects.each do |object| + relative_position = position_between(max_relative_position, MAX_POSITION) + object.relative_position = relative_position + max_relative_position = relative_position + object.save + end + end + end + + # This method takes two integer values (positions) and + # calculates the position between them. The range is huge as + # the maximum integer value is 2147483647. We are incrementing position by IDEAL_DISTANCE * 2 every time + # when we have enough space. If distance is less then IDEAL_DISTANCE we are calculating an average number + def position_between(pos_before, pos_after) + pos_before ||= MIN_POSITION + pos_after ||= MAX_POSITION + + pos_before, pos_after = [pos_before, pos_after].sort + + halfway = (pos_after + pos_before) / 2 + distance_to_halfway = pos_after - halfway + + if distance_to_halfway < IDEAL_DISTANCE + halfway + else + if pos_before == MIN_POSITION + pos_after - IDEAL_DISTANCE + elsif pos_after == MAX_POSITION + pos_before + IDEAL_DISTANCE + else + halfway + end + end + end + end + def min_relative_position self.class.in_parents(parent_ids).minimum(:relative_position) end @@ -57,7 +100,7 @@ module RelativePositioning @positionable_neighbours = [before] # rubocop:disable Gitlab/ModuleWithInstanceVariables end - self.relative_position = position_between(before.relative_position, after.relative_position) + self.relative_position = self.class.position_between(before.relative_position, after.relative_position) end def move_after(before = self) @@ -72,7 +115,7 @@ module RelativePositioning pos_after = issue_to_move.relative_position end - self.relative_position = position_between(pos_before, pos_after) + self.relative_position = self.class.position_between(pos_before, pos_after) end def move_before(after = self) @@ -87,15 +130,15 @@ module RelativePositioning pos_before = issue_to_move.relative_position end - self.relative_position = position_between(pos_before, pos_after) + self.relative_position = self.class.position_between(pos_before, pos_after) end def move_to_end - self.relative_position = position_between(max_relative_position || START_POSITION, MAX_POSITION) + self.relative_position = self.class.position_between(max_relative_position || START_POSITION, MAX_POSITION) end def move_to_start - self.relative_position = position_between(min_relative_position || START_POSITION, MIN_POSITION) + self.relative_position = self.class.position_between(min_relative_position || START_POSITION, MIN_POSITION) end # Indicates if there is an issue that should be shifted to free the place @@ -112,32 +155,6 @@ module RelativePositioning private - # This method takes two integer values (positions) and - # calculates the position between them. The range is huge as - # the maximum integer value is 2147483647. We are incrementing position by IDEAL_DISTANCE * 2 every time - # when we have enough space. If distance is less then IDEAL_DISTANCE we are calculating an average number - def position_between(pos_before, pos_after) - pos_before ||= MIN_POSITION - pos_after ||= MAX_POSITION - - pos_before, pos_after = [pos_before, pos_after].sort - - halfway = (pos_after + pos_before) / 2 - distance_to_halfway = pos_after - halfway - - if distance_to_halfway < IDEAL_DISTANCE - halfway - else - if pos_before == MIN_POSITION - pos_after - IDEAL_DISTANCE - elsif pos_after == MAX_POSITION - pos_before + IDEAL_DISTANCE - else - halfway - end - end - end - # rubocop:disable Gitlab/ModuleWithInstanceVariables def save_positionable_neighbours return unless @positionable_neighbours diff --git a/app/models/deployment.rb b/app/models/deployment.rb index ed61135cb47..f1bce1a1daf 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -19,6 +19,17 @@ class Deployment < ActiveRecord::Base after_create :create_ref after_create :invalidate_cache + scope :for_environment, -> (environment) { where(environment_id: environment) } + + def self.last_for_environment(environment) + ids = self + .for_environment(environment) + .select('MAX(id) AS id') + .group(:environment_id) + .map(&:id) + find(ids) + end + def commit project.commit(sha) end diff --git a/app/models/environment.rb b/app/models/environment.rb index 309bd4f37c9..0816c395185 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -48,6 +48,8 @@ class Environment < ActiveRecord::Base order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC')) end scope :in_review_folder, -> { where(environment_type: "review") } + scope :for_name, -> (name) { where(name: name) } + scope :for_project, -> (project) { where(project_id: project) } state_machine :state, initial: :available do event :start do diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb new file mode 100644 index 00000000000..5ff3acc0e58 --- /dev/null +++ b/app/models/environment_status.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class EnvironmentStatus + include Gitlab::Utils::StrongMemoize + + attr_reader :environment, :merge_request + + delegate :id, to: :environment + delegate :name, to: :environment + delegate :project, to: :environment + delegate :deployed_at, to: :deployment, allow_nil: true + + def initialize(environment, merge_request) + @environment = environment + @merge_request = merge_request + end + + def deployment + strong_memoize(:deployment) do + environment.first_deployment_for(merge_request.diff_head_sha) + end + end + + def deployed_at + deployment&.created_at + end + + def changes + sha = merge_request.diff_head_sha + return [] if project.route_map_for(sha).nil? + + changed_files.map { |file| build_change(file, sha) }.compact + end + + def changed_files + merge_request.merge_request_diff + .merge_request_diff_files.where(deleted_file: false) + end + + private + + PAGE_EXTENSIONS = /\A\.(s?html?|php|asp|cgi|pl)\z/i.freeze + + def build_change(file, sha) + public_path = project.public_path_for_source_path(file.new_path, sha) + return if public_path.nil? + + ext = File.extname(public_path) + return if ext.present? && ext !~ PAGE_EXTENSIONS + + { + path: public_path, + external_url: environment.external_url_for(file.new_path, sha) + } + end +end diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb deleted file mode 100644 index 0f7067238cd..00000000000 --- a/app/models/forked_project_link.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class ForkedProjectLink < ActiveRecord::Base - belongs_to :forked_to_project, -> { where.not(pending_delete: true) }, class_name: 'Project' - belongs_to :forked_from_project, -> { where.not(pending_delete: true) }, class_name: 'Project' -end diff --git a/app/models/list.rb b/app/models/list.rb index 1a30acc83cf..029685be927 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -15,6 +15,7 @@ class List < ActiveRecord::Base scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) } scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) } + scope :preload_associations, -> { preload(:board, :label) } class << self def destroyable_types diff --git a/app/models/project.rb b/app/models/project.rb index 05e14c578b5..4798fae82b7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -49,8 +49,11 @@ class Project < ActiveRecord::Base attachments: 2 }.freeze - # Valids ports to import from - VALID_IMPORT_PORTS = [22, 80, 443].freeze + VALID_IMPORT_PORTS = [80, 443].freeze + VALID_IMPORT_PROTOCOLS = %w(http https git).freeze + + VALID_MIRROR_PORTS = [22, 80, 443].freeze + VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze cache_markdown_field :description, pipeline: :description @@ -164,20 +167,15 @@ class Project < ActiveRecord::Base has_one :packagist_service has_one :hangouts_chat_service - # TODO: replace these relations with the fork network versions - has_one :forked_project_link, foreign_key: "forked_to_project_id" - has_one :forked_from_project, through: :forked_project_link - - has_many :forked_project_links, foreign_key: "forked_from_project_id" - has_many :forks, through: :forked_project_links, source: :forked_to_project - # TODO: replace these relations with the fork network versions - has_one :root_of_fork_network, foreign_key: 'root_project_id', inverse_of: :root_project, class_name: 'ForkNetwork' has_one :fork_network_member has_one :fork_network, through: :fork_network_member + has_one :forked_from_project, through: :fork_network_member + has_many :forked_to_members, class_name: 'ForkNetworkMember', foreign_key: 'forked_from_project_id' + has_many :forks, through: :forked_to_members, source: :project, inverse_of: :forked_from_project has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent @@ -305,10 +303,10 @@ class Project < ActiveRecord::Base validates :namespace, presence: true validates :name, uniqueness: { scope: :namespace_id } - validates :import_url, url: { protocols: %w(http https ssh git), + validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS }, + ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS }, allow_localhost: false, - enforce_user: true, - ports: VALID_IMPORT_PORTS }, if: [:external_import?, :import_url_changed?] + enforce_user: true }, if: [:external_import?, :import_url_changed?] validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? } @@ -690,6 +688,8 @@ class Project < ActiveRecord::Base else super end + rescue + super end def valid_import_url? @@ -1247,12 +1247,7 @@ class Project < ActiveRecord::Base end def forked? - return true if fork_network && fork_network.root_project != self - - # TODO: Use only the above conditional using the `fork_network` - # This is the old conditional that looks at the `forked_project_link`, we - # fall back to this while we're migrating the new models - !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) + fork_network && fork_network.root_project != self end def fork_source @@ -1543,9 +1538,7 @@ class Project < ActiveRecord::Base def visibility_level_allowed_as_fork?(level = self.visibility_level) return true unless forked? - # self.forked_from_project will be nil before the project is saved, so - # we need to go through the relation - original_project = forked_project_link&.forked_from_project + original_project = fork_source return true unless original_project level <= original_project.visibility_level @@ -1789,7 +1782,7 @@ class Project < ActiveRecord::Base return unless export_file_exists? import_export_upload.remove_export_file! - import_export_upload.save + import_export_upload.save unless import_export_upload.destroyed? end def export_file_exists? diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index d502423726c..d121d088ff6 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -80,13 +80,18 @@ class BambooService < CiService private + def get_build_result_index + # When Bamboo returns multiple results for a given changeset, arbitrarily assume the most relevant result to be the last one. + -1 + end + def read_build_page(response) - if response.code != 200 || response['results']['results']['size'] == '0' + if response.code != 200 || response.dig('results', 'results', 'size') == '0' # If actual build link can't be determined, send user to build summary page. URI.join("#{bamboo_url}/", "browse/#{build_key}").to_s else # If actual build link is available, go to build result page. - result_key = response['results']['results']['result']['planResultKey']['key'] + result_key = response.dig('results', 'results', 'result', get_build_result_index, 'planResultKey', 'key') URI.join("#{bamboo_url}/", "browse/#{result_key}").to_s end end @@ -94,10 +99,10 @@ class BambooService < CiService def read_commit_status(response) return :error unless response.code == 200 || response.code == 404 - status = if response.code == 404 || response['results']['results']['size'] == '0' + status = if response.code == 404 || response.dig('results', 'results', 'size') == '0' 'Pending' else - response['results']['results']['result']['buildState'] + response.dig('results', 'results', 'result', get_build_result_index, 'buildState') end if status.include?('Success') diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 2545df06f6b..76624263aab 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -1,53 +1,5 @@ # frozen_string_literal: true -require "flowdock-git-hook" - -# Flow dock depends on Grit to compute the number of commits between two given -# commits. To make this depend on Gitaly, a monkey patch is applied -module Flowdock - class Git - # pass down a Repository all the way down - def repo - @options[:repo] - end - - def config - {} - end - - def messages - Git::Builder.new(repo: repo, - ref: @ref, - before: @from, - after: @to, - commit_url: @commit_url, - branch_url: @branch_url, - diff_url: @diff_url, - repo_url: @repo_url, - repo_name: @repo_name, - permanent_refs: @permanent_refs, - tags: tags - ).to_hashes - end - - class Builder - def commits - @repo.commits_between(@before, @after).map do |commit| - { - url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil, - id: commit.sha, - message: commit.message, - author: { - name: commit.author_name, - email: commit.author_email - } - } - end - end - end - end -end - class FlowdockService < Service prop_accessor :token validates :token, presence: true, if: :activated? diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index ba7fcb0cf93..5a38f48c542 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -14,6 +14,9 @@ class JiraService < IssueTrackerService format: { with: Gitlab::Regex.jira_transition_id_regex, message: "transition ids can have only numbers which can be split with , or ;" }, allow_blank: true + # JIRA cloud version is deprecating authentication via username and password. + # We should use username/password for JIRA server and email/api_token for JIRA cloud, + # for more information check: https://gitlab.com/gitlab-org/gitlab-ce/issues/49936. prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id, :title, :description before_update :reset_password @@ -95,8 +98,8 @@ class JiraService < IssueTrackerService [ { type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true }, { type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' }, - { type: 'text', name: 'username', placeholder: '', required: true }, - { type: 'password', name: 'password', placeholder: '', required: true }, + { type: 'text', name: 'username', title: 'Username or Email', placeholder: 'Use a username for server version and an email for cloud version', required: true }, + { type: 'password', name: 'password', title: 'Password or API token', placeholder: 'Use a password for server version and an API token for cloud version', required: true }, { type: 'text', name: 'jira_issue_transition_id', title: 'Transition ID(s)', placeholder: 'Use , or ; to separate multiple transition IDs' } ] end diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb index 5b0e5fed092..c34078f13c1 100644 --- a/app/models/project_services/microsoft_teams_service.rb +++ b/app/models/project_services/microsoft_teams_service.rb @@ -17,7 +17,7 @@ class MicrosoftTeamsService < ChatNotificationService 'This service sends notifications about projects events to Microsoft Teams channels.<br /> To set up this service: <ol> - <li><a href="https://msdn.microsoft.com/en-us/microsoft-teams/connectors">Getting started with 365 Office Connectors For Microsoft Teams</a>.</li> + <li><a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors/connectors-using#setting-up-a-custom-incoming-webhook">Setup a custom Incoming Webhook using Office 365 Connectors For Microsoft Teams</a>.</li> <li>Paste the <strong>Webhook URL</strong> into the field below.</li> <li>Select events below to enable notifications.</li> </ol>' diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb index 509e5b6089b..211e5c3fcbf 100644 --- a/app/models/project_services/prometheus_service.rb +++ b/app/models/project_services/prometheus_service.rb @@ -26,7 +26,7 @@ class PrometheusService < MonitoringService end def editable? - manual_configuration? || !prometheus_installed? + manual_configuration? || !prometheus_available? end def title @@ -56,7 +56,6 @@ class PrometheusService < MonitoringService name: 'api_url', title: 'API URL', placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'), - help: s_('PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.'), required: true } ] @@ -75,17 +74,17 @@ class PrometheusService < MonitoringService RestClient::Resource.new(api_url) if api_url && manual_configuration? && active? end - def prometheus_installed? + def prometheus_available? return false if template? return false unless project - project.clusters.enabled.any? { |cluster| cluster.application_prometheus&.installed? } + project.clusters.enabled.any? { |cluster| cluster.application_prometheus_available? } end private def synchronize_service_state - self.active = prometheus_installed? || manual_configuration? + self.active = prometheus_available? || manual_configuration? true end diff --git a/app/models/repository.rb b/app/models/repository.rb index a3a3ce179fc..37a1dd64052 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -36,7 +36,7 @@ class Repository # For example, for entry `:commit_count` there's a method called `commit_count` which # stores its data in the `commit_count` cache key. CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide - changelog license_blob license_key gitignore koding_yml + changelog license_blob license_key gitignore gitlab_ci_yml branch_names tag_names branch_count tag_count avatar exists? root_ref has_visible_content? issue_template_names merge_request_template_names xcode_project?).freeze @@ -53,7 +53,6 @@ class Repository license: %i(license_blob license_key license), contributing: :contribution_guide, gitignore: :gitignore, - koding: :koding_yml, gitlab_ci: :gitlab_ci_yml, avatar: :avatar, issue_template: :issue_template_names, @@ -488,7 +487,20 @@ class Repository end def blob_at(sha, path) - Blob.decorate(raw_repository.blob_at(sha, path), project) + blob = Blob.decorate(raw_repository.blob_at(sha, path), project) + + # Don't attempt to return a special result if there is no blob at all + return unless blob + + # Don't attempt to return a special result unless we're looking at HEAD + return blob unless head_commit&.sha == sha + + case path + when head_tree&.readme_path + ReadmeBlob.new(blob, self) + else + blob + end rescue Gitlab::Git::Repository::NoRepository nil end @@ -570,9 +582,7 @@ class Repository cache_method :merge_request_template_names, fallback: [] def readme - if readme = tree(:head)&.readme - ReadmeBlob.new(readme, self) - end + head_tree&.readme end def rendered_readme @@ -619,11 +629,6 @@ class Repository end cache_method :gitignore - def koding_yml - file_on_head(:koding) - end - cache_method :koding_yml - def gitlab_ci_yml file_on_head(:gitlab_ci) end @@ -881,10 +886,12 @@ class Repository delegate :merged_branch_names, to: :raw_repository - def merge_base(first_commit_id, second_commit_id) - first_commit_id = commit(first_commit_id).try(:id) || first_commit_id - second_commit_id = commit(second_commit_id).try(:id) || second_commit_id - raw_repository.merge_base(first_commit_id, second_commit_id) + def merge_base(*commits_or_ids) + commit_ids = commits_or_ids.map do |commit_or_id| + commit_or_id.is_a?(::Commit) ? commit_or_id.id : commit_or_id + end + + raw_repository.merge_base(*commit_ids) end def ancestor?(ancestor_id, descendant_id) diff --git a/app/models/tree.rb b/app/models/tree.rb index 3641c33254c..cd385872171 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -2,6 +2,7 @@ class Tree include Gitlab::MarkupHelper + include Gitlab::Utils::StrongMemoize attr_accessor :repository, :sha, :path, :entries @@ -16,32 +17,36 @@ class Tree @entries = Gitlab::Git::Tree.where(git_repo, @sha, @path, recursive) end - def readme - return @readme if defined?(@readme) - - available_readmes = blobs.select do |blob| - Gitlab::FileDetector.type_of(blob.name) == :readme - end - - previewable_readmes = available_readmes.select do |blob| - previewable?(blob.name) - end - - plain_readmes = available_readmes.select do |blob| - plain?(blob.name) + def readme_path + strong_memoize(:readme_path) do + available_readmes = blobs.select do |blob| + Gitlab::FileDetector.type_of(blob.name) == :readme + end + + previewable_readmes = available_readmes.select do |blob| + previewable?(blob.name) + end + + plain_readmes = available_readmes.select do |blob| + plain?(blob.name) + end + + # Prioritize previewable over plain readmes + entry = previewable_readmes.first || plain_readmes.first + next nil unless entry + + if path == '/' + entry.name + else + File.join(path, entry.name) + end end + end - # Prioritize previewable over plain readmes - readme_tree = previewable_readmes.first || plain_readmes.first - - # Return if we can't preview any of them - if readme_tree.nil? - return @readme = nil + def readme + strong_memoize(:readme) do + repository.blob_at(sha, readme_path) if readme_path end - - readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name) - - @readme = repository.blob_at(sha, readme_path) end def trees diff --git a/app/models/user.rb b/app/models/user.rb index 8a7acfb73b1..34efb22b359 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -217,7 +217,7 @@ class User < ActiveRecord::Base # User's Dashboard preference # Note: When adding an option, it MUST go on the end of the array. - enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests] + enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests, :operations] # User's Project preference # Note: When adding an option, it MUST go on the end of the array. @@ -264,7 +264,7 @@ class User < ActiveRecord::Base scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) } scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) } scope :confirmed, -> { where.not(confirmed_at: nil) } - scope :by_username, -> (usernames) { iwhere(username: usernames) } + scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) } scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) } # Limits the users to those that have TODOs, optionally in the given state. diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb index 2c0e8659fc1..1cd05cf3aac 100644 --- a/app/models/user_callout.rb +++ b/app/models/user_callout.rb @@ -6,8 +6,7 @@ class UserCallout < ActiveRecord::Base enum feature_name: { gke_cluster_integration: 1, gcp_signup_offer: 2, - cluster_security_warning: 3, - gold_trial: 4 + cluster_security_warning: 3 } validates :user, presence: true diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 42fd213d03b..c5e349ae913 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -160,7 +160,9 @@ class WikiPage # Returns boolean True or False if this instance # is an old version of the page. def historical? - @page.historical? && last_version.sha != version.sha + return false unless last_commit_sha && version + + @page.historical? && last_commit_sha != version.sha end # Returns boolean True or False if this instance |