summaryrefslogtreecommitdiff
path: root/app/models/commit_status.rb
blob: 21c5c87bc3d28f6973b6e1a88ef7da379351f726 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# == Schema Information
#
#  project_id            integer
#  status                string
#  finished_at           datetime
#  trace                 text
#  created_at            datetime
#  updated_at            datetime
#  started_at            datetime
#  runner_id             integer
#  coverage              float
#  commit_id             integer
#  commands              text
#  job_id                integer
#  name                  string
#  deploy                boolean           default: false
#  options               text
#  allow_failure         boolean           default: false, null: false
#  stage                 string
#  trigger_request_id    integer
#  stage_idx             integer
#  tag                   boolean
#  ref                   string
#  user_id               integer
#  type                  string
#  target_url            string
#  description           string
#

class CommitStatus < ActiveRecord::Base
  self.table_name = 'ci_builds'

  belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
  belongs_to :commit, class_name: 'Ci::Commit'
  belongs_to :user

  validates :commit, presence: true
  validates :status, inclusion: { in: %w(pending running failed success canceled) }

  validates_presence_of :name

  alias_attribute :author, :user

  scope :running, -> { where(status: 'running') }
  scope :pending, -> { where(status: 'pending') }
  scope :success, -> { where(status: 'success') }
  scope :failed, -> { where(status: 'failed')  }
  scope :running_or_pending, -> { where(status: [:running, :pending]) }
  scope :finished, -> { where(status: [:success, :failed, :canceled]) }
  scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
  scope :ordered, -> { order(:ref, :stage_idx, :name) }
  scope :for_ref, ->(ref) { where(ref: ref) }

  state_machine :status, initial: :pending do
    event :run do
      transition pending: :running
    end

    event :drop do
      transition [:pending, :running] => :failed
    end

    event :success do
      transition [:pending, :running] => :success
    end

    event :cancel do
      transition [:pending, :running] => :canceled
    end

    after_transition pending: :running do |build, transition|
      build.update_attributes started_at: Time.now
    end

    after_transition any => [:success, :failed, :canceled] do |build, transition|
      build.update_attributes finished_at: Time.now
    end

    after_transition [:pending, :running] => :success do |build, transition|
      MergeRequests::MergeWhenBuildSucceedsService.new(build.commit.project, nil).trigger(build)
    end

    state :pending, value: 'pending'
    state :running, value: 'running'
    state :failed, value: 'failed'
    state :success, value: 'success'
    state :canceled, value: 'canceled'
  end

  delegate :sha, :short_sha, to: :commit, prefix: false

  # TODO: this should be removed with all references
  def before_sha
    Gitlab::Git::BLANK_SHA
  end

  def started?
    !pending? && !canceled? && started_at
  end

  def active?
    running? || pending?
  end

  def complete?
    canceled? || success? || failed?
  end

  def duration
    if started_at && finished_at
      finished_at - started_at
    elsif started_at
      Time.now - started_at
    end
  end

  def cancel_url
    nil
  end

  def retry_url
    nil
  end

  def show_warning?
    false
  end

  def download_url
    nil
  end
end