summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/application_setting.rb9
-rw-r--r--app/models/ci/build.rb21
-rw-r--r--app/models/ci/pipeline.rb16
-rw-r--r--app/models/ci/pipeline_status.rb86
-rw-r--r--app/models/ci/runner.rb4
-rw-r--r--app/models/ci/runner_project.rb6
-rw-r--r--app/models/ci/trigger.rb2
-rw-r--r--app/models/ci/variable.rb4
-rw-r--r--app/models/commit.rb13
-rw-r--r--app/models/commit_status.rb8
-rw-r--r--app/models/concerns/has_status.rb1
-rw-r--r--app/models/concerns/issuable.rb36
-rw-r--r--app/models/concerns/routable.rb10
-rw-r--r--app/models/event.rb2
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/issue.rb16
-rw-r--r--app/models/label.rb4
-rw-r--r--app/models/merge_request.rb10
-rw-r--r--app/models/milestone.rb1
-rw-r--r--app/models/project.rb26
-rw-r--r--app/models/project_services/builds_email_service.rb102
-rw-r--r--app/models/project_services/chat_message/build_message.rb102
-rw-r--r--app/models/project_services/chat_notification_service.rb18
-rw-r--r--app/models/project_services/hipchat_service.rb45
-rw-r--r--app/models/project_services/mattermost_service.rb1
-rw-r--r--app/models/project_services/prometheus_service.rb9
-rw-r--r--app/models/project_services/slack_service.rb1
-rw-r--r--app/models/project_wiki.rb7
-rw-r--r--app/models/route.rb2
-rw-r--r--app/models/service.rb1
-rw-r--r--app/models/todo.rb8
-rw-r--r--app/models/user.rb2
-rw-r--r--app/models/wiki_page.rb14
33 files changed, 290 insertions, 299 deletions
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index be632930895..671a0fe98cc 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -163,6 +163,8 @@ class ApplicationSetting < ActiveRecord::Base
end
def self.current
+ ensure_cache_setup
+
Rails.cache.fetch(CACHE_KEY) do
ApplicationSetting.last
end
@@ -176,9 +178,16 @@ class ApplicationSetting < ActiveRecord::Base
end
def self.cached
+ ensure_cache_setup
Rails.cache.fetch(CACHE_KEY)
end
+ def self.ensure_cache_setup
+ # This is a workaround for a Rails bug that causes attribute methods not
+ # to be loaded when read from cache: https://github.com/rails/rails/issues/27348
+ ApplicationSetting.define_attribute_methods
+ end
+
def self.defaults_ce
{
after_sign_up_text: nil,
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 3722047251d..ad0be70c32a 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -15,7 +15,7 @@ module Ci
def persisted_environment
@persisted_environment ||= Environment.find_by(
name: expanded_environment_name,
- project_id: gl_project_id
+ project: project
)
end
@@ -223,7 +223,8 @@ module Ci
def merge_request
merge_requests = MergeRequest.includes(:merge_request_diff)
- .where(source_branch: ref, source_project_id: pipeline.gl_project_id)
+ .where(source_branch: ref,
+ source_project: pipeline.project)
.reorder(iid: :asc)
merge_requests.find do |merge_request|
@@ -231,10 +232,6 @@ module Ci
end
end
- def project_id
- gl_project_id
- end
-
def repo_url
auth = "gitlab-ci-token:#{ensure_token!}@"
project.http_url_to_repo.sub(/^https?:\/\//) do |prefix|
@@ -542,6 +539,16 @@ module Ci
Gitlab::Ci::Build::Credentials::Factory.new(self).create!
end
+ def dependencies
+ depended_jobs = depends_on_builds
+
+ return depended_jobs unless options[:dependencies].present?
+
+ depended_jobs.select do |job|
+ options[:dependencies].include?(job.name)
+ end
+ end
+
private
def update_artifacts_size
@@ -561,7 +568,7 @@ module Ci
end
def unscoped_project
- @unscoped_project ||= Project.unscoped.find_by(id: gl_project_id)
+ @unscoped_project ||= Project.unscoped.find_by(id: project_id)
end
CI_REGISTRY_USER = 'gitlab-ci-token'.freeze
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 8a5a9aa4adb..f12be98c80c 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -5,9 +5,7 @@ module Ci
include Importable
include AfterCommitQueue
- self.table_name = 'ci_commits'
-
- belongs_to :project, foreign_key: :gl_project_id
+ belongs_to :project
belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
@@ -22,6 +20,7 @@ module Ci
validate :valid_commit_sha, unless: :importing?
after_create :keep_around_commits, unless: :importing?
+ after_create :refresh_build_status_cache
state_machine :status, initial: :created do
event :enqueue do
@@ -114,6 +113,12 @@ module Ci
success.latest(ref).order(id: :desc).first
end
+ def self.latest_successful_for_refs(refs)
+ success.latest(refs).order(id: :desc).each_with_object({}) do |pipeline, hash|
+ hash[pipeline.ref] ||= pipeline
+ end
+ end
+
def self.truncate_sha(sha)
sha[0...8]
end
@@ -328,6 +333,7 @@ module Ci
when 'manual' then block
end
end
+ refresh_build_status_cache
end
def predefined_variables
@@ -369,6 +375,10 @@ module Ci
.fabricate!
end
+ def refresh_build_status_cache
+ Ci::PipelineStatus.new(project, sha: sha, status: status).store_in_cache_if_needed
+ end
+
private
def pipeline_data
diff --git a/app/models/ci/pipeline_status.rb b/app/models/ci/pipeline_status.rb
new file mode 100644
index 00000000000..048047d0e34
--- /dev/null
+++ b/app/models/ci/pipeline_status.rb
@@ -0,0 +1,86 @@
+# This class is not backed by a table in the main database.
+# It loads the latest Pipeline for the HEAD of a repository, and caches that
+# in Redis.
+module Ci
+ class PipelineStatus
+ attr_accessor :sha, :status, :project, :loaded
+
+ delegate :commit, to: :project
+
+ def self.load_for_project(project)
+ new(project).tap do |status|
+ status.load_status
+ end
+ end
+
+ def initialize(project, sha: nil, status: nil)
+ @project = project
+ @sha = sha
+ @status = status
+ end
+
+ def has_status?
+ loaded? && sha.present? && status.present?
+ end
+
+ def load_status
+ return if loaded?
+
+ if has_cache?
+ load_from_cache
+ else
+ load_from_commit
+ store_in_cache
+ end
+
+ self.loaded = true
+ end
+
+ def load_from_commit
+ return unless commit
+
+ self.sha = commit.sha
+ self.status = commit.status
+ end
+
+ # We only cache the status for the HEAD commit of a project
+ # This status is rendered in project lists
+ def store_in_cache_if_needed
+ return unless sha
+ return delete_from_cache unless commit
+ store_in_cache if commit.sha == self.sha
+ end
+
+ def load_from_cache
+ Gitlab::Redis.with do |redis|
+ self.sha, self.status = redis.hmget(cache_key, :sha, :status)
+ end
+ end
+
+ def store_in_cache
+ Gitlab::Redis.with do |redis|
+ redis.mapped_hmset(cache_key, { sha: sha, status: status })
+ end
+ end
+
+ def delete_from_cache
+ Gitlab::Redis.with do |redis|
+ redis.del(cache_key)
+ end
+ end
+
+ def has_cache?
+ Gitlab::Redis.with do |redis|
+ redis.exists(cache_key)
+ end
+ end
+
+ def loaded?
+ self.loaded
+ end
+
+ def cache_key
+ "projects/#{project.id}/build_status"
+ end
+ end
+end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index edd21f984c8..487ba61bc9c 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -9,7 +9,7 @@ module Ci
has_many :builds
has_many :runner_projects, dependent: :destroy
- has_many :projects, through: :runner_projects, foreign_key: :gl_project_id
+ has_many :projects, through: :runner_projects
has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
@@ -24,7 +24,7 @@ module Ci
scope :owned_or_shared, ->(project_id) do
joins('LEFT JOIN ci_runner_projects ON ci_runner_projects.runner_id = ci_runners.id')
- .where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
+ .where("ci_runner_projects.project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
end
scope :assignable_for, ->(project) do
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 234376a7e4c..5f01a0daae9 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -1,10 +1,10 @@
module Ci
class RunnerProject < ActiveRecord::Base
extend Ci::Model
-
+
belongs_to :runner
- belongs_to :project, foreign_key: :gl_project_id
+ belongs_to :project
- validates :runner_id, uniqueness: { scope: :gl_project_id }
+ validates :runner_id, uniqueness: { scope: :project_id }
end
end
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 90473d41c04..cba1d81a861 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -4,7 +4,7 @@ module Ci
acts_as_paranoid
- belongs_to :project, foreign_key: :gl_project_id
+ belongs_to :project
belongs_to :owner, class_name: "User"
has_many :trigger_requests, dependent: :destroy
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index 2c8698d8b5d..6c6586110c5 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -2,11 +2,11 @@ module Ci
class Variable < ActiveRecord::Base
extend Ci::Model
- belongs_to :project, foreign_key: :gl_project_id
+ belongs_to :project
validates :key,
presence: true,
- uniqueness: { scope: :gl_project_id },
+ uniqueness: { scope: :project_id },
length: { maximum: 255 },
format: { with: /\A[a-zA-Z0-9_]+\z/,
message: "can contain only letters, digits and '_'." }
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 0a18986ef26..ce92cc369ad 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -231,6 +231,10 @@ class Commit
project.pipelines.where(sha: sha)
end
+ def latest_pipeline
+ pipelines.last
+ end
+
def status(ref = nil)
@statuses ||= {}
@@ -317,7 +321,14 @@ class Commit
end
def raw_diffs(*args)
- raw.diffs(*args)
+ use_gitaly = Gitlab::GitalyClient.feature_enabled?(:commit_raw_diffs)
+ deltas_only = args.last.is_a?(Hash) && args.last[:deltas_only]
+
+ if use_gitaly && !deltas_only
+ Gitlab::GitalyClient::Commit.diff_from_parent(self, *args)
+ else
+ raw.diffs(*args)
+ end
end
def diffs(diff_options = nil)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 7e23e14794f..8c71267da65 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds'
- belongs_to :project, foreign_key: :gl_project_id
+ belongs_to :project
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
belongs_to :user
@@ -133,6 +133,12 @@ class CommitStatus < ActiveRecord::Base
false
end
+ # Added in 9.0 to keep backward compatibility for projects exported in 8.17
+ # and prior.
+ def gl_project_id
+ 'dummy'
+ end
+
def detailed_status(current_user)
Gitlab::Ci::Status::Factory
.new(self, current_user)
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 5101cc7e687..0a1a65da05a 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -31,6 +31,7 @@ module HasStatus
WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
WHEN (#{running})+(#{pending})>0 THEN 'running'
WHEN (#{manual})>0 THEN 'manual'
+ WHEN (#{created})>0 THEN 'running'
ELSE 'failed'
END)"
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 3cf4c67d7e7..e7bd20b322a 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -48,11 +48,13 @@ module Issuable
delegate :name,
:email,
+ :public_email,
to: :author,
prefix: true
delegate :name,
:email,
+ :public_email,
to: :assignee,
allow_nil: true,
prefix: true
@@ -144,7 +146,8 @@ module Issuable
when 'milestone_due_desc' then order_milestone_due_desc
when 'downvotes_desc' then order_downvotes_desc
when 'upvotes_desc' then order_upvotes_desc
- when 'priority' then order_labels_priority(excluded_labels: excluded_labels)
+ when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels)
+ when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels)
when 'position_asc' then order_position_asc
else
order_by(method)
@@ -154,7 +157,28 @@ module Issuable
sorted.order(id: :desc)
end
- def order_labels_priority(excluded_labels: [])
+ def order_due_date_and_labels_priority(excluded_labels: [])
+ # The order_ methods also modify the query in other ways:
+ #
+ # - For milestones, we add a JOIN.
+ # - For label priority, we change the SELECT, and add a GROUP BY.#
+ #
+ # After doing those, we need to reorder to the order we want. The existing
+ # ORDER BYs won't work because:
+ #
+ # 1. We need milestone due date first.
+ # 2. We can't ORDER BY a column that isn't in the GROUP BY and doesn't
+ # have an aggregate function applied, so we do a useless MIN() instead.
+ #
+ milestones_due_date = 'MIN(milestones.due_date)'
+
+ order_milestone_due_asc.
+ order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date]).
+ reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
+ Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
+ end
+
+ def order_labels_priority(excluded_labels: [], extra_select_columns: [])
params = {
target_type: name,
target_column: "#{table_name}.id",
@@ -164,7 +188,12 @@ module Issuable
highest_priority = highest_label_priority(params).to_sql
- select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
+ select_columns = [
+ "#{table_name}.*",
+ "(#{highest_priority}) AS highest_priority"
+ ] + extra_select_columns
+
+ select(select_columns.join(', ')).
group(arel_table[:id]).
reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
end
@@ -234,6 +263,7 @@ module Issuable
user: user.hook_attrs,
project: project.hook_attrs,
object_attributes: hook_attrs,
+ labels: labels.map(&:hook_attrs),
# DEPRECATED
repository: project.hook_attrs.slice(:name, :url, :description, :homepage)
}
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb
index 9f6d215ceb3..529fb5ce988 100644
--- a/app/models/concerns/routable.rb
+++ b/app/models/concerns/routable.rb
@@ -51,11 +51,13 @@ module Routable
paths.each do |path|
path = connection.quote(path)
- where = "(routes.path = #{path})"
- if cast_lower
- where = "(#{where} OR (LOWER(routes.path) = LOWER(#{path})))"
- end
+ where =
+ if cast_lower
+ "(LOWER(routes.path) = LOWER(#{path}))"
+ else
+ "(routes.path = #{path})"
+ end
wheres << where
end
diff --git a/app/models/event.rb b/app/models/event.rb
index d7ca8e3c599..5c34844b5d3 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -16,7 +16,7 @@ class Event < ActiveRecord::Base
RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour
- delegate :name, :email, to: :author, prefix: true, allow_nil: true
+ delegate :name, :email, :public_email, to: :author, prefix: true, allow_nil: true
delegate :title, to: :issue, prefix: true, allow_nil: true
delegate :title, to: :merge_request, prefix: true, allow_nil: true
delegate :title, to: :note, prefix: true, allow_nil: true
diff --git a/app/models/group.rb b/app/models/group.rb
index bd0ecae3da4..60274386103 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -207,7 +207,7 @@ class Group < Namespace
end
def members_with_parents
- GroupMember.non_request.where(source_id: ancestors.map(&:id).push(id))
+ GroupMember.non_request.where(source_id: ancestors.pluck(:id).push(id))
end
def users_with_parents
diff --git a/app/models/issue.rb b/app/models/issue.rb
index f188dcb673c..c2b261825b2 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -57,10 +57,24 @@ class Issue < ActiveRecord::Base
state :opened
state :reopened
state :closed
+
+ before_transition any => :closed do |issue|
+ issue.closed_at = Time.zone.now
+ end
+
+ before_transition closed: any do |issue|
+ issue.closed_at = nil
+ end
end
def hook_attrs
- attributes
+ attrs = {
+ total_time_spent: total_time_spent,
+ human_total_time_spent: human_total_time_spent,
+ human_time_estimate: human_time_estimate
+ }
+
+ attributes.merge!(attrs)
end
def self.reference_prefix
diff --git a/app/models/label.rb b/app/models/label.rb
index f68a8c9cff2..568fa6d44f5 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -169,6 +169,10 @@ class Label < ActiveRecord::Base
end
end
+ def hook_attrs
+ attributes
+ end
+
private
def issues_count(user, params = {})
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 0f7b8311588..cef8ad76b07 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -7,6 +7,7 @@ class MergeRequest < ActiveRecord::Base
belongs_to :target_project, class_name: "Project"
belongs_to :source_project, class_name: "Project"
+ belongs_to :project, foreign_key: :target_project_id
belongs_to :merge_user, class_name: "User"
has_many :merge_request_diffs, dependent: :destroy
@@ -523,7 +524,10 @@ class MergeRequest < ActiveRecord::Base
source: source_project.try(:hook_attrs),
target: target_project.hook_attrs,
last_commit: nil,
- work_in_progress: work_in_progress?
+ work_in_progress: work_in_progress?,
+ total_time_spent: total_time_spent,
+ human_total_time_spent: human_total_time_spent,
+ human_time_estimate: human_time_estimate
}
if diff_head_commit
@@ -537,10 +541,6 @@ class MergeRequest < ActiveRecord::Base
target_project != source_project
end
- def project
- target_project
- end
-
# If the merge request closes any issues, save this information in the
# `MergeRequestsClosingIssues` model. This is a performance optimization.
# Calculating this information for a number of merge requests requires
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 7331000a9f2..c0deb59ec4c 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -5,6 +5,7 @@ class Milestone < ActiveRecord::Base
None = MilestoneStruct.new('No Milestone', 'No Milestone', 0)
Any = MilestoneStruct.new('Any Milestone', '', -1)
Upcoming = MilestoneStruct.new('Upcoming', '#upcoming', -2)
+ Started = MilestoneStruct.new('Started', '#started', -3)
include CacheMarkdownField
include InternalId
diff --git a/app/models/project.rb b/app/models/project.rb
index 8c2dadf4659..da4704554b3 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -89,7 +89,6 @@ class Project < ActiveRecord::Base
has_one :campfire_service, dependent: :destroy
has_one :drone_ci_service, dependent: :destroy
has_one :emails_on_push_service, dependent: :destroy
- has_one :builds_email_service, dependent: :destroy
has_one :pipelines_email_service, dependent: :destroy
has_one :irker_service, dependent: :destroy
has_one :pivotaltracker_service, dependent: :destroy
@@ -159,13 +158,13 @@ class Project < ActiveRecord::Base
has_one :project_feature, dependent: :destroy
has_one :statistics, class_name: 'ProjectStatistics', dependent: :delete
- has_many :commit_statuses, dependent: :destroy, foreign_key: :gl_project_id
- has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id
- has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses
- has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id
+ has_many :commit_statuses, dependent: :destroy
+ has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline'
+ has_many :builds, class_name: 'Ci::Build' # the builds are created from the commit_statuses
+ has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
- has_many :variables, dependent: :destroy, class_name: 'Ci::Variable', foreign_key: :gl_project_id
- has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger', foreign_key: :gl_project_id
+ has_many :variables, dependent: :destroy, class_name: 'Ci::Variable'
+ has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger'
has_many :environments, dependent: :destroy
has_many :deployments, dependent: :destroy
@@ -197,6 +196,7 @@ class Project < ActiveRecord::Base
validates :name, uniqueness: { scope: :namespace_id }
validates :path, uniqueness: { scope: :namespace_id }
validates :import_url, addressable_url: true, if: :external_import?
+ validates :import_url, importable_url: true, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :avatar_type,
@@ -881,13 +881,9 @@ class Project < ActiveRecord::Base
end
def http_url_to_repo(user = nil)
- url = web_url
+ credentials = Gitlab::UrlSanitizer.http_credentials_for_user(user)
- if user
- url.sub!(%r{\Ahttps?://}) { |protocol| "#{protocol}#{user.username}@" }
- end
-
- "#{url}.git"
+ Gitlab::UrlSanitizer.new("#{web_url}.git", credentials: credentials).full_url
end
# Check if current branch name is marked as protected in the system
@@ -1209,6 +1205,10 @@ class Project < ActiveRecord::Base
end
end
+ def pipeline_status
+ @pipeline_status ||= Ci::PipelineStatus.load_for_project(self)
+ end
+
def mark_import_as_failed(error_message)
original_errors = errors.dup
sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)
diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb
index ebd21e37189..0c526b53d72 100644
--- a/app/models/project_services/builds_email_service.rb
+++ b/app/models/project_services/builds_email_service.rb
@@ -1,107 +1,11 @@
+# This class is to be removed with 9.1
+# We should also by then remove BuildsEmailService from database
class BuildsEmailService < Service
- prop_accessor :recipients
- boolean_accessor :add_pusher
- boolean_accessor :notify_only_broken_builds
- validates :recipients, presence: true, if: ->(s) { s.activated? && !s.add_pusher? }
-
- def initialize_properties
- if properties.nil?
- self.properties = {}
- self.notify_only_broken_builds = true
- end
- end
-
- def title
- 'Builds emails'
- end
-
- def description
- 'Email the builds status to a list of recipients.'
- end
-
def self.to_param
'builds_email'
end
def self.supported_events
- %w(build)
- end
-
- def execute(push_data)
- return unless supported_events.include?(push_data[:object_kind])
- return unless should_build_be_notified?(push_data)
-
- recipients = all_recipients(push_data)
-
- if recipients.any?
- BuildEmailWorker.perform_async(
- push_data[:build_id],
- recipients,
- push_data
- )
- end
- end
-
- def can_test?
- project.builds.any?
- end
-
- def disabled_title
- "Please setup a build on your repository."
- end
-
- def test_data(project = nil, user = nil)
- Gitlab::DataBuilder::Build.build(project.builds.last)
- end
-
- def fields
- [
- { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' },
- { type: 'checkbox', name: 'add_pusher', label: 'Add pusher to recipients list' },
- { type: 'checkbox', name: 'notify_only_broken_builds' },
- ]
- end
-
- def test(data)
- begin
- # bypass build status verification when testing
- data[:build_status] = "failed"
- data[:build_allow_failure] = false
-
- result = execute(data)
- rescue StandardError => error
- return { success: false, result: error }
- end
-
- { success: true, result: result }
- end
-
- def should_build_be_notified?(data)
- case data[:build_status]
- when 'success'
- !notify_only_broken_builds?
- when 'failed'
- !allow_failure?(data)
- else
- false
- end
- end
-
- def allow_failure?(data)
- data[:build_allow_failure] == true
- end
-
- def all_recipients(data)
- all_recipients = []
-
- unless recipients.blank?
- all_recipients += recipients.split(',').compact.reject(&:blank?)
- end
-
- if add_pusher? && data[:user][:email]
- all_recipients << data[:user][:email]
- end
-
- all_recipients
+ %w[]
end
end
diff --git a/app/models/project_services/chat_message/build_message.rb b/app/models/project_services/chat_message/build_message.rb
deleted file mode 100644
index c776e0a20c4..00000000000
--- a/app/models/project_services/chat_message/build_message.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-module ChatMessage
- class BuildMessage < BaseMessage
- attr_reader :sha
- attr_reader :ref_type
- attr_reader :ref
- attr_reader :status
- attr_reader :project_name
- attr_reader :project_url
- attr_reader :user_name
- attr_reader :user_url
- attr_reader :duration
- attr_reader :stage
- attr_reader :build_id
- attr_reader :build_name
-
- def initialize(params)
- @sha = params[:sha]
- @ref_type = params[:tag] ? 'tag' : 'branch'
- @ref = params[:ref]
- @project_name = params[:project_name]
- @project_url = params[:project_url]
- @status = params[:commit][:status]
- @user_name = params[:commit][:author_name]
- @user_url = params[:commit][:author_url]
- @duration = params[:commit][:duration]
- @stage = params[:build_stage]
- @build_name = params[:build_name]
- @build_id = params[:build_id]
- end
-
- def pretext
- ''
- end
-
- def fallback
- format(message)
- end
-
- def attachments
- [{ text: format(message), color: attachment_color }]
- end
-
- private
-
- def message
- "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_link} #{humanized_status} on build #{build_link} of stage #{stage} in #{duration} #{'second'.pluralize(duration)}"
- end
-
- def build_url
- "#{project_url}/builds/#{build_id}"
- end
-
- def build_link
- link(build_name, build_url)
- end
-
- def user_link
- link(user_name, user_url)
- end
-
- def format(string)
- Slack::Notifier::LinkFormatter.format(string)
- end
-
- def humanized_status
- case status
- when 'success'
- 'passed'
- else
- status
- end
- end
-
- def attachment_color
- if status == 'success'
- 'good'
- else
- 'danger'
- end
- end
-
- def branch_url
- "#{project_url}/commits/#{ref}"
- end
-
- def branch_link
- link(ref, branch_url)
- end
-
- def project_link
- link(project_name, project_url)
- end
-
- def commit_url
- "#{project_url}/commit/#{sha}/builds"
- end
-
- def commit_link
- link(Commit.truncate_sha(sha), commit_url)
- end
- end
-end
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index 8468934425f..200be99f36b 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -6,7 +6,7 @@ class ChatNotificationService < Service
default_value_for :category, 'chat'
prop_accessor :webhook, :username, :channel
- boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines
+ boolean_accessor :notify_only_broken_pipelines
validates :webhook, presence: true, url: true, if: :activated?
@@ -16,7 +16,6 @@ class ChatNotificationService < Service
if properties.nil?
self.properties = {}
- self.notify_only_broken_builds = true
self.notify_only_broken_pipelines = true
end
end
@@ -27,7 +26,7 @@ class ChatNotificationService < Service
def self.supported_events
%w[push issue confidential_issue merge_request note tag_push
- build pipeline wiki_page]
+ pipeline wiki_page]
end
def execute(data)
@@ -89,8 +88,6 @@ class ChatNotificationService < Service
ChatMessage::MergeMessage.new(data) unless is_update?(data)
when "note"
ChatMessage::NoteMessage.new(data)
- when "build"
- ChatMessage::BuildMessage.new(data) if should_build_be_notified?(data)
when "pipeline"
ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
when "wiki_page"
@@ -125,17 +122,6 @@ class ChatNotificationService < Service
data[:object_attributes][:action] == 'update'
end
- def should_build_be_notified?(data)
- case data[:commit][:status]
- when 'success'
- !notify_only_broken_builds?
- when 'failed'
- true
- else
- false
- end
- end
-
def should_pipeline_be_notified?(data)
case data[:object_attributes][:status]
when 'success'
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index c4142c38b2f..8b181221bb0 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -9,13 +9,13 @@ class HipchatService < Service
].freeze
prop_accessor :token, :room, :server, :color, :api_version
- boolean_accessor :notify_only_broken_builds, :notify
+ boolean_accessor :notify_only_broken_pipelines, :notify
validates :token, presence: true, if: :activated?
def initialize_properties
if properties.nil?
self.properties = {}
- self.notify_only_broken_builds = true
+ self.notify_only_broken_pipelines = true
end
end
@@ -41,12 +41,12 @@ class HipchatService < Service
placeholder: 'Leave blank for default (v2)' },
{ type: 'text', name: 'server',
placeholder: 'Leave blank for default. https://hipchat.example.com' },
- { type: 'checkbox', name: 'notify_only_broken_builds' },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
end
def self.supported_events
- %w(push issue confidential_issue merge_request note tag_push build)
+ %w(push issue confidential_issue merge_request note tag_push pipeline)
end
def execute(data)
@@ -90,8 +90,8 @@ class HipchatService < Service
create_merge_request_message(data) unless is_update?(data)
when "note"
create_note_message(data)
- when "build"
- create_build_message(data) if should_build_be_notified?(data)
+ when "pipeline"
+ create_pipeline_message(data) if should_pipeline_be_notified?(data)
end
end
@@ -240,28 +240,29 @@ class HipchatService < Service
message
end
- def create_build_message(data)
- ref_type = data[:tag] ? 'tag' : 'branch'
- ref = data[:ref]
- sha = data[:sha]
- user_name = data[:commit][:author_name]
- status = data[:commit][:status]
- duration = data[:commit][:duration]
+ def create_pipeline_message(data)
+ pipeline_attributes = data[:object_attributes]
+ pipeline_id = pipeline_attributes[:id]
+ ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
+ ref = pipeline_attributes[:ref]
+ user_name = (data[:user] && data[:user][:name]) || 'API'
+ status = pipeline_attributes[:status]
+ duration = pipeline_attributes[:duration]
branch_link = "<a href=\"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"
- commit_link = "<a href=\"#{project_url}/commit/#{CGI.escape(sha)}/builds\">#{Commit.truncate_sha(sha)}</a>"
+ pipeline_url = "<a href=\"#{project_url}/pipelines/#{pipeline_id}\">##{pipeline_id}</a>"
- "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)"
+ "#{project_link}: Pipeline #{pipeline_url} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)"
end
def message_color(data)
- build_status_color(data) || color || 'yellow'
+ pipeline_status_color(data) || color || 'yellow'
end
- def build_status_color(data)
- return unless data && data[:object_kind] == 'build'
+ def pipeline_status_color(data)
+ return unless data && data[:object_kind] == 'pipeline'
- case data[:commit][:status]
+ case data[:object_attributes][:status]
when 'success'
'green'
else
@@ -294,10 +295,10 @@ class HipchatService < Service
end
end
- def should_build_be_notified?(data)
- case data[:commit][:status]
+ def should_pipeline_be_notified?(data)
+ case data[:object_attributes][:status]
when 'success'
- !notify_only_broken_builds?
+ !notify_only_broken_pipelines?
when 'failed'
true
else
diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb
index c13538e9fea..1156d050622 100644
--- a/app/models/project_services/mattermost_service.rb
+++ b/app/models/project_services/mattermost_service.rb
@@ -30,7 +30,6 @@ class MattermostService < ChatNotificationService
[
{ type: 'text', name: 'webhook', placeholder: 'e.g. http://mattermost_host/hooks/…' },
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' },
- { type: 'checkbox', name: 'notify_only_broken_builds' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
end
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 375966b9efc..4d7c81a721f 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -30,7 +30,14 @@ class PrometheusService < MonitoringService
end
def help
- 'Retrieves `container_cpu_usage_seconds_total` and `container_memory_usage_bytes` from the configured Prometheus server. An `environment` label is required on each metric to identify the Environment.'
+ <<-MD.strip_heredoc
+ Retrieves the Kubernetes node metrics `container_cpu_usage_seconds_total`
+ and `container_memory_usage_bytes` from the configured Prometheus server.
+
+ If you are not using [Auto-Deploy](https://docs.gitlab.com/ee/ci/autodeploy/index.html)
+ or have set up your own Prometheus server, an `environment` label is required on each metric to
+ [identify the Environment](https://docs.gitlab.com/ce/user/project/integrations/prometheus.html#metrics-and-labels).
+ MD
end
def self.to_param
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index da7496573ef..b657db6f9ee 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -29,7 +29,6 @@ class SlackService < ChatNotificationService
[
{ type: 'text', name: 'webhook', placeholder: 'e.g. https://hooks.slack.com/services/…' },
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' },
- { type: 'checkbox', name: 'notify_only_broken_builds' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
end
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 539b31780b3..70eef359cdd 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -42,8 +42,11 @@ class ProjectWiki
url_to_repo
end
- def http_url_to_repo
- [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
+ def http_url_to_repo(user = nil)
+ url = "#{Gitlab.config.gitlab.url}/#{path_with_namespace}.git"
+ credentials = Gitlab::UrlSanitizer.http_credentials_for_user(user)
+
+ Gitlab::UrlSanitizer.new(url, credentials: credentials).full_url
end
def wiki_base_path
diff --git a/app/models/route.rb b/app/models/route.rb
index 73574a6206b..41e6eb7cb73 100644
--- a/app/models/route.rb
+++ b/app/models/route.rb
@@ -21,7 +21,7 @@ class Route < ActiveRecord::Base
attributes[:path] = route.path.sub(path_was, path)
end
- if name_changed? && route.name.present?
+ if name_changed? && name_was.present? && route.name.present?
attributes[:name] = route.name.sub(name_was, name)
end
diff --git a/app/models/service.rb b/app/models/service.rb
index 2f75a2e4e7f..e73f7e5d1a3 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -215,7 +215,6 @@ class Service < ActiveRecord::Base
assembla
bamboo
buildkite
- builds_email
bugzilla
campfire
custom_issue_tracker
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 47789a21133..da3fa7277c2 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -48,8 +48,14 @@ class Todo < ActiveRecord::Base
after_save :keep_around_commit
class << self
+ # Priority sorting isn't displayed in the dropdown, because we don't show
+ # milestones, but still show something if the user has a URL with that
+ # selected.
def sort(method)
- method == "priority" ? order_by_labels_priority : order_by(method)
+ case method.to_s
+ when 'priority', 'label_priority' then order_by_labels_priority
+ else order_by(method)
+ end
end
# Order by priority depending on which issue/merge request the Todo belongs to
diff --git a/app/models/user.rb b/app/models/user.rb
index 39c1281179b..8c7ad5d5174 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -877,7 +877,7 @@ class User < ActiveRecord::Base
def ci_authorized_runners
@ci_authorized_runners ||= begin
runner_ids = Ci::RunnerProject.
- where("ci_runner_projects.gl_project_id IN (#{ci_projects_union.to_sql})").
+ where("ci_runner_projects.project_id IN (#{ci_projects_union.to_sql})").
select(:runner_id)
Ci::Runner.specific.where(id: runner_ids)
end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 2caebb496db..c771c22f46a 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -149,7 +149,13 @@ class WikiPage
end
# Returns boolean True or False if this instance
- # has been fully saved to disk or not.
+ # is the latest commit version of the page.
+ def latest?
+ !historical?
+ end
+
+ # Returns boolean True or False if this instance
+ # has been fully created on disk or not.
def persisted?
@persisted == true
end
@@ -220,6 +226,8 @@ class WikiPage
end
def save(method, *args)
+ saved = false
+
project_wiki = wiki
if valid? && project_wiki.send(method, *args)
@@ -237,10 +245,10 @@ class WikiPage
set_attributes
@persisted = true
+ saved = true
else
errors.add(:base, project_wiki.error_message) if project_wiki.error_message
- @persisted = false
end
- @persisted
+ saved
end
end