Rcov report for: app/models/hudson_job.rb

NameTotal linesLines of codeTotal coverageCode coverage
app/models/hudson_job.rb296227
86.49%
85.46%
1 # $Id$
2 
3 require 'hudson_build'
4 require 'hudson_api_error'
5 require 'hudson_exceptions'
6 
7 class HudsonJob < ActiveRecord::Base
8   unloadable
9   has_many :health_reports, :class_name => 'HudsonHealthReport', :dependent => :destroy
10   has_one :job_settings, :class_name => 'HudsonJobSettings', :dependent => :destroy
11   belongs_to :project, :foreign_key => 'project_id'
12   belongs_to :settings, :class_name => 'HudsonSettings', :foreign_key => 'hudson_id'
13 
14   attr_reader :hudson_api_errors
15 
16   # ���������������������������
17   validates_presence_of :project_id, :hudson_id, :name
18 
19   include HudsonHelper
20   include RexmlHelper
21 
22   def initialize(attributes = nil)
23     super attributes
24     self.job_settings = HudsonJobSettings.new
25     @hudson_api_errors = []
26   end
27 
28   def after_find
29     @hudson_api_errors = []
30   end
31 
32   def after_save
33     self.job_settings = HudsonJobSettings.new unless self.job_settings
34     self.job_settings.hudson_job_id = self.id
35     self.job_settings.save!
36   end
37 
38   def url_for(type = :user)
39     return "" unless self.settings
40     return "" unless (self.name && self.name.length > 0)
41     return "#{self.settings.url_for(type)}job/#{self.name}"
42   end
43 
44   def build_url_for(type = :user)
45     return "" if url_for(type) == ""
46     return "#{url_for(type)}/build"
47   end
48 
49   def rss_url_for(type = :user)
50     return "" if url_for(type) == ""
51     return "#{url_for(type)}/rssAll"
52   end
53 
54   def config_url_for(type = :user)
55     return "" if url_for(type) == ""
56     return "#{url_for(type)}/config.xml"
57   end
58 
59   def api_url_for(type = :user)
60     return "" if url_for(type) == ""
61     return "#{url_for(type)}/api"
62   end
63 
64   def get_build(number)
65     return HudsonNoBuild.new unless number
66 
67     retval = HudsonBuild.find(:first, :conditions => ["#{HudsonBuild.table_name}.hudson_job_id = ? AND #{HudsonBuild.table_name}.number = ?",
68                                                       self.id, number])
69     retval = HudsonNoBuild.new unless retval
70     return retval
71   end
72 
73   def latest_build
74     latest_build = get_build(self.latest_build_number)
75     return latest_build
76   end
77 
78   def destroy_builds
79     HudsonBuild.destroy_all(["#{HudsonBuild.table_name}.hudson_job_id = ?", self.id])
80   end
81 
82   def update_by_xml(element)
83     self.description = get_element_value(element, "description")
84     self.state = get_element_value(element, "color")
85     latest_build_info = element.elements["lastBuild"]
86     self.latest_build_number = get_element_value(latest_build_info, "number") if latest_build_info
87   end
88 
89   def update_health_report_by_xml(element)
90     hr_index = 0
91     element.elements.each("healthReport") do |hReport|
92       report = nil
93       if hr_index < self.health_reports.length
94         report = self.health_reports[hr_index]
95       end
96 
97       unless report
98         report = HudsonHealthReport.new
99         report.job = self
100         report.hudson_job_id = self.id
101         self.health_reports << report
102       end
103 
104       report.update_by_xml(hReport)
105       report.save
106 
107       hr_index += 1
108     end
109   end
110 
111   def request_build
112     clear_hudson_api_errors
113     api_url = build_url_for(:plugin)
114     open_hudson_api(api_url, self.settings.auth_user, self.settings.auth_password)
115   rescue HudsonApiException => error
116     @hudson_api_errors << HudsonApiError.new(self.class.name, "request_build '#{self.name}'", error)
117   end
118 
119   def fetch_recent_builds
120     clear_hudson_api_errors
121     api_uri = rss_url_for(:plugin)
122     content = open_hudson_api(api_uri, self.settings.auth_user, self.settings.auth_password)
123 
124     doc = REXML::Document.new content
125     retval = []
126     doc.elements.each("//entry") do |entry|
127       buildinfo = HudsonBuild.parse_rss(entry)
128       retval << buildinfo
129     end
130     return retval
131   rescue HudsonApiException => error
132     @hudson_api_errors << HudsonApiError.new(self.class.name, "fetch_recent_builds '#{self.name}'", error)
133   end
134 
135   def fetch_builds
136     clear_hudson_api_errors
137     
138     return unless do_fetch?
139 
140     fetch_summary unless self.settings.get_build_details
141     fetch_detail if self.settings.get_build_details
142 
143     latest_build = get_build(self.latest_build_number)
144     add_latest_build if latest_build.is_a? HudsonNoBuild
145 
146   rescue HudsonApiException => error
147     @hudson_api_errors << HudsonApiError.new(self.class.name, "fetch_builds '#{self.name}'", error)
148   end
149 
150 private
151   def clear_hudson_api_errors
152     @hudson_api_errors = []
153   end
154 
155   def fetch_summary
156     api_url = rss_url_for(:plugin)
157     begin
158       content = open_hudson_api(api_url, self.settings.auth_user, self.settings.auth_password)
159     rescue HudsonApiException => error
160       raise error
161     end
162 
163     doc = REXML::Document.new content
164     doc.elements.each("//entry") do |entry|
165       buildinfo = HudsonBuild.parse_rss(entry)
166 
167       next unless HudsonBuildRotator.can_store?(self, buildinfo[:number])
168       next unless HudsonBuild.to_be_updated?(self.id, buildinfo[:number])
169 
170       build = get_build(buildinfo[:number])
171 
172       if build.is_a?(HudsonNoBuild)
173         build = new_build
174       end
175 
176       build.update_by_rss(entry)
177       build.save
178 
179     end
180   end
181 
182   def fetch_detail
183 
184     api_url = "#{api_url_for(:plugin)}/xml/?depth=1"
185     api_url << "&exclude=//build/changeSet/item/path"
186     api_url << "&exclude=//build/changeSet/item/addedPath"
187     api_url << "&exclude=//build/changeSet/item/modifiedPath"
188     api_url << "&exclude=//build/changeSet/item/deletedPath"
189     api_url << "&exclude=//build/culprit"
190     api_url << "&exclude=//module"
191     api_url << "&exclude=//firstBuild&exclude=//lastBuild"
192     api_url << "&exclude=//lastCompletedBuild"
193     api_url << "&exclude=//lastFailedBuild"
194     api_url << "&exclude=//lastStableBuild"
195     api_url << "&exclude=//lastSuccessfulBuild"
196     api_url << "&exclude=//downstreamProject"
197     api_url << "&exclude=//upstreamProject"
198     content = ""
199     begin
200       content = open_hudson_api(api_url, self.settings.auth_user, self.settings.auth_password)
201     rescue HudsonApiException => error
202       raise error
203     end
204 
205     begin
206       doc = REXML::Document.new content
207     rescue REXML::ParseException => error
208       raise HudsonApiException.new(error)
209     end
210 
211     doc.elements.each("//build") do |buildelem|
212       build_number = get_element_value(buildelem, "number")
213 
214       next unless HudsonBuildRotator.can_store?(self, build_number)
215       next unless HudsonBuild.to_be_updated?(self.id, build_number)
216 
217       build = get_build(build_number)
218 
219       if build.is_a?(HudsonNoBuild)
220         build = new_build
221       end
222       
223       build.update_by_api(buildelem)
224       build.save
225 
226       # ������������������������������������
227       build.add_changesets_from_xml buildelem if self.project.repository != nil
228 
229       # ������������������������������
230       build.add_testresult_from_xml buildelem
231 
232       # ������������������������
233       build.add_artifact_from_xml buildelem
234 
235     end
236     
237   end
238 
239   def do_fetch?
240     latest_build = get_build(self.latest_build_number)
241     return true if latest_build.is_a? HudsonNoBuild
242     return true if latest_build.building?
243     
244     return false
245   end
246 
247   def add_latest_build
248     build = new_build
249     build.number = self.latest_build_number
250     build.result = ""
251     build.finished_at = ""
252     build.building = "true"
253     build.caused_by = 1
254     build.error = ""
255     build.save
256   end
257 
258   def new_build
259     retval = HudsonBuild.new()
260     retval.job = self
261     retval.hudson_job_id = self.id
262     return retval
263   end
264 
265 end
266 
267 class HudsonNoJob
268   attr_reader :settings, :hudson_id, :project_id, :id, :name, :latest_build_number, :created_at, :updated_at, :description, :state, :job_settings
269 
270   def initialize(args = nil)
271     @id = ""
272     @project_id = ""
273     @name = ""
274     @latest_build_number = ""
275     @created_at = ""
276     @updated_at = ""
277     @description = ""
278     @state = ""
279     @job_settings = nil
280     @settings = nil
281 
282     return unless args
283 
284     @settings = args[:settings]
285     @name = args[:name]
286 
287   end
288 
289   def url_for(type = :user)
290     return "" unless self.settings
291     return "" unless (self.name && self.name.length > 0)
292     return "#{self.settings.url_for(type)}job/#{self.name}"
293   end
294 
295 end
296