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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
# == Schema Information
#
# Table name: builds
#
# id :integer not null, primary key
# project_id :integer
# ref :string(255)
# status :string(255)
# finished_at :datetime
# trace :text
# created_at :datetime not null
# updated_at :datetime not null
# sha :string(255)
# started_at :datetime
# tmp_file :string(255)
# before_sha :string(255)
# push_data :text
# runner_id :integer
#
class Build < ActiveRecord::Base
belongs_to :project
belongs_to :runner
serialize :push_data
attr_accessible :project_id, :ref, :sha, :before_sha,
:status, :finished_at, :trace, :started_at, :push_data, :runner_id, :project_name
validates :before_sha, presence: true
validates :sha, presence: true
validates :ref, presence: true
validates :status, presence: true
validate :valid_commit_sha
scope :running, ->() { where(status: "running") }
scope :pending, ->() { where(status: "pending") }
scope :success, ->() { where(status: "success") }
scope :failed, ->() { where(status: "failed") }
scope :uniq_sha, ->() { select('DISTINCT(sha)') }
def self.last_month
where('created_at > ?', Date.today - 1.month)
end
def self.first_pending
pending.where(runner_id: nil).order('created_at ASC').first
end
def self.create_from(build)
new_build = build.dup
new_build.status = :pending
new_build.runner_id = nil
new_build.save
end
state_machine :status, initial: :pending do
event :run do
transition pending: :running
end
event :drop do
transition running: :failed
end
event :success do
transition 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
project = build.project
if project.web_hooks?
WebHookService.new.execute_hooks(build)
end
if project.email_notification?
if build.status.to_sym == :failed || !project.email_only_broken_builds
NotificationService.new.build_ended(build)
end
end
end
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
state :success, value: 'success'
state :canceled, value: 'canceled'
end
def valid_commit_sha
if self.sha =~ /\A00000000/
self.errors.add(:sha, " cant be 00000000 (branch removal)")
end
end
def compare?
gitlab? && before_sha
end
def gitlab?
project.gitlab?
end
def ci_skip?
!!(git_commit_message =~ /(\[ci skip\])/)
end
def git_author_name
commit_data[:author][:name] if commit_data && commit_data[:author]
end
def git_author_email
commit_data[:author][:email] if commit_data && commit_data[:author]
end
def git_commit_message
commit_data[:message] if commit_data
end
def short_before_sha
before_sha[0..8]
end
def short_sha
sha[0..8]
end
def trace_html
html = Ansi2html::convert(trace) if trace.present?
html ||= ''
end
def started?
!pending? && !canceled? && started_at
end
def active?
running? || pending?
end
def complete?
canceled? || success? || failed?
end
def commands
project.scripts
end
def commit_data
push_data[:commits].each do |commit|
return commit if commit[:id] == sha
end
rescue
nil
end
# Build a clone-able repo url
# using http and basic auth
def repo_url
auth = "gitlab-ci-token:#{project.token}@"
url = project.gitlab_url + ".git"
url.sub(/^https?:\/\//) do |prefix|
prefix + auth
end
end
def timeout
project.timeout
end
def allow_git_fetch
project.allow_git_fetch
end
def project_name
project.name
end
def project_recipients
recipients = project.email_recipients.split(' ')
recipients << git_author_email if project.email_add_committer?
recipients.uniq
end
def duration
if started_at && finished_at
finished_at - started_at
elsif started_at
Time.now - started_at
end
end
end
|