BigW Consortium Gitlab

commit_status.rb 3.7 KB
Newer Older
1
class CommitStatus < ActiveRecord::Base
2
  include HasStatus
3
  include Importable
4
  include AfterCommitQueue
5

6 7
  self.table_name = 'ci_builds'

8
  belongs_to :project
9
  belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
10
  belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
11 12
  belongs_to :user

13
  delegate :commit, to: :pipeline
Douwe Maan committed
14
  delegate :sha, :short_sha, to: :pipeline
15

16
  validates :pipeline, presence: true, unless: :importing?
17

Douwe Maan committed
18
  validates :name, presence: true
19

20 21
  alias_attribute :author, :user

22 23 24 25 26
  scope :latest, -> do
    max_id = unscope(:select).select("max(#{quoted_table_name}.id)")

    where(id: max_id.group(:name, :commit_id))
  end
27

28
  scope :failed_but_allowed, -> do
29
    where(allow_failure: true, status: [:failed, :canceled])
30
  end
31

32
  scope :exclude_ignored, -> do
33 34 35
    # We want to ignore failed but allowed to fail jobs.
    #
    # TODO, we also skip ignored optional manual actions.
36
    where("allow_failure = ? OR status IN (?)",
37
      false, all_state_names - [:failed, :canceled, :manual])
38
  end
39

40 41
  scope :retried, -> { where.not(id: latest) }
  scope :ordered, -> { order(:name) }
42 43
  scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
  scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
44
  scope :after_stage, -> (index) { where('stage_idx > ?', index) }
45

46
  state_machine :status do
47
    event :enqueue do
48
      transition [:created, :skipped, :manual] => :pending
49 50
    end

51
    event :process do
52
      transition [:skipped, :manual] => :created
53 54
    end

55 56 57 58
    event :run do
      transition pending: :running
    end

59 60 61 62
    event :skip do
      transition [:created, :pending] => :skipped
    end

63
    event :drop do
64
      transition [:created, :pending, :running] => :failed
65 66 67
    end

    event :success do
68
      transition [:created, :pending, :running] => :success
69 70 71
    end

    event :cancel do
72
      transition [:created, :pending, :running, :manual] => :canceled
73 74
    end

75 76
    before_transition created: [:pending, :running] do |commit_status|
      commit_status.queued_at = Time.now
77 78
    end

79 80
    before_transition [:created, :pending] => :running do |commit_status|
      commit_status.started_at = Time.now
81 82
    end

83 84
    before_transition any => [:success, :failed, :canceled] do |commit_status|
      commit_status.finished_at = Time.now
85 86
    end

87
    after_transition do |commit_status, transition|
88
      next if transition.loopback?
89

90 91
      commit_status.run_after_commit do
        pipeline.try do |pipeline|
92
          if complete? || manual?
93
            PipelineProcessWorker.perform_async(pipeline.id)
94
          else
95
            PipelineUpdateWorker.perform_async(pipeline.id)
96
          end
97
        end
98
      end
99 100
    end

101
    after_transition any => :failed do |commit_status|
102
      commit_status.run_after_commit do
103 104
        MergeRequests::AddTodoWhenBuildFailsService
          .new(pipeline.project, nil).execute(self)
105
      end
106
    end
107 108
  end

109 110 111 112
  def locking_enabled?
    status_changed?
  end

113
  def before_sha
114
    pipeline.before_sha || Gitlab::Git::BLANK_SHA
115
  end
116

Kamil Trzcinski committed
117
  def group_name
Kamil Trzcinski committed
118
    name.gsub(/\d+[\s:\/\\]+\d+\s*/, '').strip
Kamil Trzcinski committed
119 120
  end

121
  def failed_but_allowed?
122
    allow_failure? && (failed? || canceled?)
123 124
  end

125 126 127 128
  def duration
    calculate_duration
  end

Kamil Trzcinski committed
129 130 131 132
  def playable?
    false
  end

133 134
  def stuck?
    false
135
  end
Kamil Trzcinski committed
136

137
  def has_trace?
138 139
    false
  end
140

141 142 143 144
  def auto_canceled?
    canceled? && auto_canceled_by_id?
  end

145 146 147 148 149 150
  # Added in 9.0 to keep backward compatibility for projects exported in 8.17
  # and prior.
  def gl_project_id
    'dummy'
  end

151
  def detailed_status(current_user)
152 153 154
    Gitlab::Ci::Status::Factory
      .new(self, current_user)
      .fabricate!
155
  end
156

Mike Greiling committed
157
  def sortable_name
158 159 160 161
    name.split(/(\d+)/).map do |v|
      v =~ /\d+/ ? v.to_i : v
    end
  end
162
end