Merge lp:~cjohnston/qa-dashboard/dashboard-sru-2-sru into lp:qa-dashboard
- dashboard-sru-2-sru
- Merge into dev
Status: | Rejected |
---|---|
Rejected by: | Chris Johnston |
Proposed branch: | lp:~cjohnston/qa-dashboard/dashboard-sru-2-sru |
Merge into: | lp:qa-dashboard |
Diff against target: |
612 lines (+352/-156) 12 files modified
dashboard/migrations/0014_remove_sru_models.py (+18/-0) dashboard/models.py (+0/-132) dashboard/templatetags/__init__.py (+0/-15) qa_dashboard/settings.py (+1/-0) qa_dashboard/urls.py (+7/-7) sru/management/__init__.py (+14/-0) sru/management/commands/__init__.py (+14/-0) sru/management/commands/jenkins_pull_sru.py (+1/-1) sru/migrations/0001_add_initial_models.py (+136/-0) sru/models.py (+144/-0) sru/tests.py (+16/-0) sru/views.py (+1/-1) |
To merge this branch: | bzr merge lp:~cjohnston/qa-dashboard/dashboard-sru-2-sru |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Joe Talbott | Approve | ||
Chris Johnston | Pending | ||
Review via email: mp+141944@code.launchpad.net |
This proposal supersedes a proposal from 2013-01-04.
Commit message
Moves sru code from dashboard to new sru app
Description of the change
Joe Talbott (joetalbott) wrote : Posted in a previous version of this proposal | # |
Chris Johnston (cjohnston) : Posted in a previous version of this proposal | # |
Joe Talbott (joetalbott) wrote : | # |
Remove lines 24-93 please.
Line 365 needs inserted 'from django.db import connection'
Joe Talbott (joetalbott) wrote : | # |
Looks good, thanks.
Chris Johnston (cjohnston) wrote : | # |
The attempt to merge lp:~chrisjohnston/qa-dashboard/dashboard-sru-2-sru into lp:qa-dashboard failed. Below is the output from the failed tests.
Creating test database for alias 'default'...
Traceback (most recent call last):
File "manage.py", line 26, in <module>
execute_
File "/usr/lib/
utility.
File "/usr/lib/
self.
File "/usr/lib/
self.
File "/usr/lib/
output = self.handle(*args, **options)
File "/usr/lib/
super(Command, self).handle(*args, **kwargs)
File "/usr/lib/
failures = test_runner.
File "/usr/lib/
old_config = self.setup_
File "/usr/lib/
test_db_name = connection.
File "/usr/lib/
load_
File "/usr/lib/
return klass.execute(
File "/usr/lib/
output = self.handle(*args, **options)
File "/usr/lib/
return self.handle_
File "/usr/lib/
management.
File "/usr/lib/
return klass.execute(
File "/usr/lib/
output = self.handle(*args, **options)
File "/usr/lib/
ignore_ghosts = ignore_ghosts,
File "/usr/lib/
success = migrator.
File "/usr/lib/
result = migrator.
File "/usr/lib/
result = self.migrate(
File "/usr/lib/
Unmerged revisions
- 205. By Chris Johnston
-
requested changes
- 204. By Chris Johnston
-
Fixes indentation
- 203. By Chris Johnston
-
Fixes indentation
- 202. By Chris Johnston
-
Updates SRU
Preview Diff
1 | === added file 'dashboard/migrations/0014_remove_sru_models.py' |
2 | --- dashboard/migrations/0014_remove_sru_models.py 1970-01-01 00:00:00 +0000 |
3 | +++ dashboard/migrations/0014_remove_sru_models.py 2013-01-04 18:06:05 +0000 |
4 | @@ -0,0 +1,18 @@ |
5 | +# -*- coding: utf-8 -*- |
6 | +import datetime |
7 | +from south.db import db |
8 | +from south.v2 import SchemaMigration |
9 | +from django.db import models |
10 | + |
11 | + |
12 | +class Migration(SchemaMigration): |
13 | + |
14 | + depends_on = ( |
15 | + ('sru', '0001_add_initial_models'), |
16 | + ) |
17 | + |
18 | + def forwards(self, orm): |
19 | + pass |
20 | + |
21 | + def backwards(self, orm): |
22 | + pass |
23 | |
24 | === modified file 'dashboard/models.py' |
25 | --- dashboard/models.py 2013-01-03 19:40:12 +0000 |
26 | +++ dashboard/models.py 2013-01-04 18:06:05 +0000 |
27 | @@ -19,9 +19,6 @@ |
28 | from common.models import DashboardBaseModel, Bug |
29 | |
30 | |
31 | -### |
32 | -# Smoke |
33 | -### |
34 | class ResultLog(DashboardBaseModel): |
35 | class Meta: |
36 | db_table = 'result_logs' |
37 | @@ -237,132 +234,3 @@ |
38 | @property |
39 | def log_count(self): |
40 | return self.resultlog_set.count() |
41 | - |
42 | -### |
43 | -# Kernel SRU |
44 | -### |
45 | - |
46 | -class Kernel(DashboardBaseModel): |
47 | - class Meta: |
48 | - db_table = "kernels" |
49 | - |
50 | - job_type = models.CharField(max_length=100) |
51 | - release = models.CharField(max_length=100) |
52 | - variant = models.CharField(max_length=100) |
53 | - arch = models.CharField(max_length=100) |
54 | - gpu = models.CharField(max_length=100) |
55 | - version = models.CharField(max_length=100) |
56 | - |
57 | - # Used by MySerializer to add property fields to the JSON representation |
58 | - # of an instance of this class. |
59 | - extra_fields = [ |
60 | - 'pass_count', |
61 | - 'skip_count', |
62 | - 'fail_count', |
63 | - 'total_count', |
64 | - 'pass_rate', |
65 | - 'pass_rate_pct', |
66 | - 'bug_count', |
67 | - 'log_count', |
68 | - ] |
69 | - |
70 | - def debug_str(self): |
71 | - return "{}-{}-{}-{}".format( |
72 | - self.release, |
73 | - self.variant, |
74 | - self.arch, |
75 | - self.gpu, |
76 | - ) |
77 | - |
78 | - @property |
79 | - def name(self): |
80 | - return "{}-{}".format(self.release, self.variant) |
81 | - |
82 | - @property |
83 | - def total_count(self): |
84 | - return self.sruresult_set.aggregate(models.Sum('total_count'))['total_count__sum'] or 0 |
85 | - |
86 | - @property |
87 | - def pass_count(self): |
88 | - return self.sruresult_set.aggregate(models.Sum('pass_count'))['pass_count__sum'] or 0 |
89 | - |
90 | - @property |
91 | - def fail_count(self): |
92 | - return self.sruresult_set.aggregate(models.Sum('fail_count'))['fail_count__sum'] or 0 |
93 | - |
94 | - @property |
95 | - def skip_count(self): |
96 | - return self.sruresult_set.aggregate(models.Sum('skip_count'))['skip_count__sum'] or 0 |
97 | - |
98 | - @property |
99 | - def pass_rate(self): |
100 | - return self.pass_count*1.0 / self.total_count if self.total_count > 0 else 0 |
101 | - |
102 | - @property |
103 | - def pass_rate_pct(self): |
104 | - return "%d%%" % int(self.pass_rate*100) |
105 | - |
106 | - @property |
107 | - def bug_count(self): |
108 | - return self.sruresult_set.annotate(num_bugs=models.Count('bugs')).aggregate(models.Sum('num_bugs'))['num_bugs__sum'] or 0 |
109 | - |
110 | - @property |
111 | - def log_count(self): |
112 | - return self.sruresultlog_set.count() |
113 | - |
114 | - @property |
115 | - def last_run_date(self): |
116 | - return self.sruresult_set.aggregate(models.Max('ran_at'))['ran_at__max'].strftime("%Y-%m-%d %H:%M") |
117 | - |
118 | -# XXX: refactor this and Result |
119 | -class SRUResult(DashboardBaseModel): |
120 | - class Meta: |
121 | - db_table = 'sru_results' |
122 | - |
123 | - kernel = models.ForeignKey(Kernel) |
124 | - bugs = models.ManyToManyField(Bug) |
125 | - |
126 | - jenkins_build = models.CharField(max_length=255) |
127 | - jenkins_url = models.URLField() |
128 | - name = models.CharField(max_length=255) |
129 | - pass_count = models.IntegerField() |
130 | - fail_count = models.IntegerField() |
131 | - skip_count = models.IntegerField() |
132 | - total_count = models.IntegerField() |
133 | - ran_at = models.DateTimeField('date run') |
134 | - |
135 | - # Used by MySerializer to add property fields to the JSON representation |
136 | - # of an instance of this class. |
137 | - extra_fields = [ |
138 | - 'pass_rate', |
139 | - 'pass_rate_pct', |
140 | - 'bug_count', |
141 | - 'log_count', |
142 | - ] |
143 | - |
144 | - @property |
145 | - def pass_rate(self): |
146 | - return self.pass_count*1.0 / self.total_count if self.total_count > 0 else 0 |
147 | - |
148 | - @property |
149 | - def pass_rate_pct(self): |
150 | - return "%d%%" % int(self.pass_rate*100) |
151 | - |
152 | - @property |
153 | - def bug_count(self): |
154 | - return self.bugs.count() |
155 | - |
156 | - @property |
157 | - def log_count(self): |
158 | - return self.resultlog_set.count() |
159 | - |
160 | -class SRUResultLog(DashboardBaseModel): |
161 | - class Meta: |
162 | - db_table = 'sru_result_logs' |
163 | - display_name = models.CharField(max_length=255, null = True) |
164 | - path = models.TextField() |
165 | - sru_result = models.ForeignKey('SRUResult') |
166 | - remote_url = models.URLField() |
167 | - |
168 | - def __unicode__(self): |
169 | - return self.path |
170 | |
171 | === removed directory 'dashboard/templatetags' |
172 | === removed file 'dashboard/templatetags/__init__.py' |
173 | --- dashboard/templatetags/__init__.py 2012-12-02 02:51:10 +0000 |
174 | +++ dashboard/templatetags/__init__.py 1970-01-01 00:00:00 +0000 |
175 | @@ -1,15 +0,0 @@ |
176 | -# QA Dashboard |
177 | -# Copyright 2012 Canonical Ltd. |
178 | - |
179 | -# This program is free software: you can redistribute it and/or modify it |
180 | -# under the terms of the GNU Affero General Public License version 3, as published |
181 | -# by the Free Software Foundation. |
182 | - |
183 | -# This program is distributed in the hope that it will be useful, but |
184 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
185 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
186 | -# PURPOSE. See the GNU Affero General Public License for more details. |
187 | - |
188 | -# You should have received a copy of the GNU Affero General Public License along |
189 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
190 | - |
191 | |
192 | === modified file 'qa_dashboard/settings.py' |
193 | --- qa_dashboard/settings.py 2012-12-14 23:59:31 +0000 |
194 | +++ qa_dashboard/settings.py 2013-01-04 18:06:05 +0000 |
195 | @@ -146,6 +146,7 @@ |
196 | 'bootspeed', |
197 | 'common', |
198 | 'south', |
199 | + 'sru', |
200 | ) |
201 | |
202 | # A sample logging configuration. The only tangible logging |
203 | |
204 | === modified file 'qa_dashboard/urls.py' |
205 | --- qa_dashboard/urls.py 2012-12-13 03:33:47 +0000 |
206 | +++ qa_dashboard/urls.py 2013-01-04 18:06:05 +0000 |
207 | @@ -35,15 +35,15 @@ |
208 | url(r'^api/smoke/run/(?P<run_id>\d+)/image/(?P<image_id>\d+)/$', 'api.smoke.api_image'), |
209 | url(r'^api/smoke/run/(?P<run_id>\d+)/image/(?P<image_id>\d+)/result/$', 'api.smoke.api_results'), |
210 | url(r'^api/smoke/run/(?P<run_id>\d+)/image/(?P<image_id>\d+)/result/(?P<result_id>\d+)/$', 'api.smoke.api_result'), |
211 | - url(r'^sru/$', 'sru.overview', name='sru'), |
212 | - url(r'^sru/(?P<release>\w+)/$', 'sru.overview', name='sru_overview'), |
213 | - url(r'^sru/(?P<release>\w+)/version/(?P<kernel_version>[^/]+)/$', 'sru.overview_kernel', name='sru_overview_kernel'), |
214 | - url(r'^api/sru/$', 'sru.api_overview'), |
215 | - url(r'^api/sru/(?P<release>\w+)/$', 'sru.api_overview'), |
216 | - url(r'^api/sru/(?P<release>\w+)/(?P<version>[^/]+)/$', 'sru.api_overview'), |
217 | url(r'^api/help/$', 'api.api_help', name='api_help'), |
218 | ) |
219 | - |
220 | + |
221 | +urlpatterns += patterns('sru.views', |
222 | + url(r'^sru/$', 'overview', name='sru'), |
223 | + url(r'^sru/(?P<release>\w+)/$', 'overview', name='sru_overview'), |
224 | + url(r'^sru/(?P<release>\w+)/version/(?P<kernel_version>[^/]+)/$', 'overview_kernel', name='sru_overview_kernel'), |
225 | +) |
226 | + |
227 | urlpatterns += patterns('bootspeed.views', |
228 | url(r'^bootspeed/$', 'arch_overview', name='bootspeed_arch'), |
229 | url(r'^bootspeed/arch/(?P<arch>\w+)/$', 'arch_overview', name='bootspeed_arch_overview'), |
230 | |
231 | === added directory 'sru' |
232 | === added file 'sru/__init__.py' |
233 | === added directory 'sru/management' |
234 | === added file 'sru/management/__init__.py' |
235 | --- sru/management/__init__.py 1970-01-01 00:00:00 +0000 |
236 | +++ sru/management/__init__.py 2013-01-04 18:06:05 +0000 |
237 | @@ -0,0 +1,14 @@ |
238 | +# QA Dashboard |
239 | +# Copyright 2012 Canonical Ltd. |
240 | + |
241 | +# This program is free software: you can redistribute it and/or modify it |
242 | +# under the terms of the GNU Affero General Public License version 3, as published |
243 | +# by the Free Software Foundation. |
244 | + |
245 | +# This program is distributed in the hope that it will be useful, but |
246 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
247 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
248 | +# PURPOSE. See the GNU Affero General Public License for more details. |
249 | + |
250 | +# You should have received a copy of the GNU Affero General Public License along |
251 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
252 | |
253 | === added directory 'sru/management/commands' |
254 | === added file 'sru/management/commands/__init__.py' |
255 | --- sru/management/commands/__init__.py 1970-01-01 00:00:00 +0000 |
256 | +++ sru/management/commands/__init__.py 2013-01-04 18:06:05 +0000 |
257 | @@ -0,0 +1,14 @@ |
258 | +# QA Dashboard |
259 | +# Copyright 2012 Canonical Ltd. |
260 | + |
261 | +# This program is free software: you can redistribute it and/or modify it |
262 | +# under the terms of the GNU Affero General Public License version 3, as published |
263 | +# by the Free Software Foundation. |
264 | + |
265 | +# This program is distributed in the hope that it will be useful, but |
266 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
267 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
268 | +# PURPOSE. See the GNU Affero General Public License for more details. |
269 | + |
270 | +# You should have received a copy of the GNU Affero General Public License along |
271 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
272 | |
273 | === renamed file 'dashboard/management/commands/jenkins_pull_sru.py' => 'sru/management/commands/jenkins_pull_sru.py' |
274 | --- dashboard/management/commands/jenkins_pull_sru.py 2013-01-03 21:22:50 +0000 |
275 | +++ sru/management/commands/jenkins_pull_sru.py 2013-01-04 18:06:05 +0000 |
276 | @@ -28,7 +28,7 @@ |
277 | |
278 | from common.utils import regexes |
279 | |
280 | -from dashboard.models import ( |
281 | +from sru.models import ( |
282 | Kernel, |
283 | SRUResult, |
284 | SRUResultLog, |
285 | |
286 | === added directory 'sru/migrations' |
287 | === added file 'sru/migrations/0001_add_initial_models.py' |
288 | --- sru/migrations/0001_add_initial_models.py 1970-01-01 00:00:00 +0000 |
289 | +++ sru/migrations/0001_add_initial_models.py 2013-01-04 18:06:05 +0000 |
290 | @@ -0,0 +1,136 @@ |
291 | +# -*- coding: utf-8 -*- |
292 | +import datetime |
293 | +from south.db import db |
294 | +from south.v2 import SchemaMigration |
295 | +from django.db import models, connection |
296 | + |
297 | + |
298 | +class Migration(SchemaMigration): |
299 | + |
300 | + def forwards(self, orm): |
301 | + |
302 | + table_names = connection.introspection.table_names() |
303 | + |
304 | + if 'kernels' not in table_names: |
305 | + # Adding model 'Kernel' |
306 | + db.create_table('kernels', ( |
307 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
308 | + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), |
309 | + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), |
310 | + ('internal', self.gf('django.db.models.fields.BooleanField')(default=True)), |
311 | + ('publish', self.gf('django.db.models.fields.BooleanField')(default=True)), |
312 | + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=100)), |
313 | + ('release', self.gf('django.db.models.fields.CharField')(max_length=100)), |
314 | + ('variant', self.gf('django.db.models.fields.CharField')(max_length=100)), |
315 | + ('arch', self.gf('django.db.models.fields.CharField')(max_length=100)), |
316 | + ('gpu', self.gf('django.db.models.fields.CharField')(max_length=100)), |
317 | + ('version', self.gf('django.db.models.fields.CharField')(max_length=100)), |
318 | + )) |
319 | + db.send_create_signal('sru', ['Kernel']) |
320 | + |
321 | + if 'sru_results' not in table_names: |
322 | + # Adding model 'SRUResult' |
323 | + db.create_table('sru_results', ( |
324 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
325 | + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), |
326 | + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), |
327 | + ('internal', self.gf('django.db.models.fields.BooleanField')(default=True)), |
328 | + ('publish', self.gf('django.db.models.fields.BooleanField')(default=True)), |
329 | + ('kernel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sru.Kernel'])), |
330 | + ('jenkins_build', self.gf('django.db.models.fields.CharField')(max_length=255)), |
331 | + ('jenkins_url', self.gf('django.db.models.fields.URLField')(max_length=200)), |
332 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), |
333 | + ('pass_count', self.gf('django.db.models.fields.IntegerField')()), |
334 | + ('fail_count', self.gf('django.db.models.fields.IntegerField')()), |
335 | + ('skip_count', self.gf('django.db.models.fields.IntegerField')()), |
336 | + ('total_count', self.gf('django.db.models.fields.IntegerField')()), |
337 | + ('ran_at', self.gf('django.db.models.fields.DateTimeField')()), |
338 | + )) |
339 | + db.send_create_signal('sru', ['SRUResult']) |
340 | + |
341 | + if 'sru_results_bugs' not in table_names: |
342 | + # Adding M2M table for field bugs on 'SRUResult' |
343 | + db.create_table('sru_results_bugs', ( |
344 | + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), |
345 | + ('sruresult', models.ForeignKey(orm['sru.sruresult'], null=False)), |
346 | + ('bug', models.ForeignKey(orm['common.bug'], null=False)) |
347 | + )) |
348 | + db.create_unique('sru_results_bugs', ['sruresult_id', 'bug_id']) |
349 | + |
350 | + if 'sru_result_logs' not in table_names: |
351 | + # Adding model 'SRUResultLog' |
352 | + db.create_table('sru_result_logs', ( |
353 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
354 | + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), |
355 | + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), |
356 | + ('internal', self.gf('django.db.models.fields.BooleanField')(default=True)), |
357 | + ('publish', self.gf('django.db.models.fields.BooleanField')(default=True)), |
358 | + ('display_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)), |
359 | + ('path', self.gf('django.db.models.fields.TextField')()), |
360 | + ('sru_result', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sru.SRUResult'])), |
361 | + ('remote_url', self.gf('django.db.models.fields.URLField')(max_length=200)), |
362 | + )) |
363 | + db.send_create_signal('sru', ['SRUResultLog']) |
364 | + |
365 | + |
366 | + def backwards(self, orm): |
367 | + pass |
368 | + |
369 | + models = { |
370 | + 'common.bug': { |
371 | + 'Meta': {'object_name': 'Bug', 'db_table': "'bugs'"}, |
372 | + 'bug_no': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
373 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
374 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
375 | + 'internal': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
376 | + 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
377 | + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
378 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
379 | + }, |
380 | + 'sru.kernel': { |
381 | + 'Meta': {'object_name': 'Kernel', 'db_table': "'kernels'"}, |
382 | + 'arch': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
383 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
384 | + 'gpu': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
385 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
386 | + 'internal': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
387 | + 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
388 | + 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
389 | + 'release': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
390 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), |
391 | + 'variant': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
392 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
393 | + }, |
394 | + 'sru.sruresult': { |
395 | + 'Meta': {'object_name': 'SRUResult', 'db_table': "'sru_results'"}, |
396 | + 'bugs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['common.Bug']", 'symmetrical': 'False'}), |
397 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
398 | + 'fail_count': ('django.db.models.fields.IntegerField', [], {}), |
399 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
400 | + 'internal': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
401 | + 'jenkins_build': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
402 | + 'jenkins_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), |
403 | + 'kernel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sru.Kernel']"}), |
404 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
405 | + 'pass_count': ('django.db.models.fields.IntegerField', [], {}), |
406 | + 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
407 | + 'ran_at': ('django.db.models.fields.DateTimeField', [], {}), |
408 | + 'skip_count': ('django.db.models.fields.IntegerField', [], {}), |
409 | + 'total_count': ('django.db.models.fields.IntegerField', [], {}), |
410 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
411 | + }, |
412 | + 'sru.sruresultlog': { |
413 | + 'Meta': {'object_name': 'SRUResultLog', 'db_table': "'sru_result_logs'"}, |
414 | + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
415 | + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), |
416 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
417 | + 'internal': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
418 | + 'path': ('django.db.models.fields.TextField', [], {}), |
419 | + 'publish': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
420 | + 'remote_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), |
421 | + 'sru_result': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sru.SRUResult']"}), |
422 | + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
423 | + } |
424 | + } |
425 | + |
426 | + complete_apps = ['sru'] |
427 | |
428 | === added file 'sru/migrations/__init__.py' |
429 | === added file 'sru/models.py' |
430 | --- sru/models.py 1970-01-01 00:00:00 +0000 |
431 | +++ sru/models.py 2013-01-04 18:06:05 +0000 |
432 | @@ -0,0 +1,144 @@ |
433 | +# QA Dashboard |
434 | +# Copyright 2012 Canonical Ltd. |
435 | + |
436 | +# This program is free software: you can redistribute it and/or modify it |
437 | +# under the terms of the GNU Affero General Public License version 3, as published |
438 | +# by the Free Software Foundation. |
439 | + |
440 | +# This program is distributed in the hope that it will be useful, but |
441 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
442 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
443 | +# PURPOSE. See the GNU Affero General Public License for more details. |
444 | + |
445 | +# You should have received a copy of the GNU Affero General Public License along |
446 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
447 | + |
448 | +from django.db import models |
449 | +import datetime |
450 | + |
451 | +from common.models import DashboardBaseModel, Bug |
452 | + |
453 | +class Kernel(DashboardBaseModel): |
454 | + class Meta: |
455 | + db_table = "kernels" |
456 | + |
457 | + job_type = models.CharField(max_length=100) |
458 | + release = models.CharField(max_length=100) |
459 | + variant = models.CharField(max_length=100) |
460 | + arch = models.CharField(max_length=100) |
461 | + gpu = models.CharField(max_length=100) |
462 | + version = models.CharField(max_length=100) |
463 | + |
464 | + # Used by MySerializer to add property fields to the JSON representation |
465 | + # of an instance of this class. |
466 | + extra_fields = [ |
467 | + 'pass_count', |
468 | + 'skip_count', |
469 | + 'fail_count', |
470 | + 'total_count', |
471 | + 'pass_rate', |
472 | + 'pass_rate_pct', |
473 | + 'bug_count', |
474 | + 'log_count', |
475 | + ] |
476 | + |
477 | + def debug_str(self): |
478 | + return "{}-{}-{}-{}".format( |
479 | + self.release, |
480 | + self.variant, |
481 | + self.arch, |
482 | + self.gpu, |
483 | + ) |
484 | + |
485 | + @property |
486 | + def name(self): |
487 | + return "{}-{}".format(self.release, self.variant) |
488 | + |
489 | + @property |
490 | + def total_count(self): |
491 | + return self.sruresult_set.aggregate(models.Sum('total_count'))['total_count__sum'] or 0 |
492 | + |
493 | + @property |
494 | + def pass_count(self): |
495 | + return self.sruresult_set.aggregate(models.Sum('pass_count'))['pass_count__sum'] or 0 |
496 | + |
497 | + @property |
498 | + def fail_count(self): |
499 | + return self.sruresult_set.aggregate(models.Sum('fail_count'))['fail_count__sum'] or 0 |
500 | + |
501 | + @property |
502 | + def skip_count(self): |
503 | + return self.sruresult_set.aggregate(models.Sum('skip_count'))['skip_count__sum'] or 0 |
504 | + |
505 | + @property |
506 | + def pass_rate(self): |
507 | + return self.pass_count*1.0 / self.total_count if self.total_count > 0 else 0 |
508 | + |
509 | + @property |
510 | + def pass_rate_pct(self): |
511 | + return "%d%%" % int(self.pass_rate*100) |
512 | + |
513 | + @property |
514 | + def bug_count(self): |
515 | + return self.sruresult_set.annotate(num_bugs=models.Count('bugs')).aggregate(models.Sum('num_bugs'))['num_bugs__sum'] or 0 |
516 | + |
517 | + @property |
518 | + def log_count(self): |
519 | + return self.sruresultlog_set.count() |
520 | + |
521 | + @property |
522 | + def last_run_date(self): |
523 | + return self.sruresult_set.aggregate(models.Max('ran_at'))['ran_at__max'].strftime("%Y-%m-%d %H:%M") |
524 | + |
525 | +# XXX: refactor this and Result |
526 | +class SRUResult(DashboardBaseModel): |
527 | + class Meta: |
528 | + db_table = 'sru_results' |
529 | + |
530 | + kernel = models.ForeignKey(Kernel) |
531 | + bugs = models.ManyToManyField(Bug) |
532 | + |
533 | + jenkins_build = models.CharField(max_length=255) |
534 | + jenkins_url = models.URLField() |
535 | + name = models.CharField(max_length=255) |
536 | + pass_count = models.IntegerField() |
537 | + fail_count = models.IntegerField() |
538 | + skip_count = models.IntegerField() |
539 | + total_count = models.IntegerField() |
540 | + ran_at = models.DateTimeField('date run') |
541 | + |
542 | + # Used by MySerializer to add property fields to the JSON representation |
543 | + # of an instance of this class. |
544 | + extra_fields = [ |
545 | + 'pass_rate', |
546 | + 'pass_rate_pct', |
547 | + 'bug_count', |
548 | + 'log_count', |
549 | + ] |
550 | + |
551 | + @property |
552 | + def pass_rate(self): |
553 | + return self.pass_count*1.0 / self.total_count if self.total_count > 0 else 0 |
554 | + |
555 | + @property |
556 | + def pass_rate_pct(self): |
557 | + return "%d%%" % int(self.pass_rate*100) |
558 | + |
559 | + @property |
560 | + def bug_count(self): |
561 | + return self.bugs.count() |
562 | + |
563 | + @property |
564 | + def log_count(self): |
565 | + return self.resultlog_set.count() |
566 | + |
567 | +class SRUResultLog(DashboardBaseModel): |
568 | + class Meta: |
569 | + db_table = 'sru_result_logs' |
570 | + display_name = models.CharField(max_length=255, null = True) |
571 | + path = models.TextField() |
572 | + sru_result = models.ForeignKey('SRUResult') |
573 | + remote_url = models.URLField() |
574 | + |
575 | + def __unicode__(self): |
576 | + return self.path |
577 | |
578 | === added directory 'sru/templates' |
579 | === renamed directory 'dashboard/templates/sru' => 'sru/templates/sru' |
580 | === added file 'sru/tests.py' |
581 | --- sru/tests.py 1970-01-01 00:00:00 +0000 |
582 | +++ sru/tests.py 2013-01-04 18:06:05 +0000 |
583 | @@ -0,0 +1,16 @@ |
584 | +""" |
585 | +This file demonstrates writing tests using the unittest module. These will pass |
586 | +when you run "manage.py test". |
587 | + |
588 | +Replace this with more appropriate tests for your application. |
589 | +""" |
590 | + |
591 | +from django.test import TestCase |
592 | + |
593 | + |
594 | +class SimpleTest(TestCase): |
595 | + def test_basic_addition(self): |
596 | + """ |
597 | + Tests that 1 + 1 always equals 2. |
598 | + """ |
599 | + self.assertEqual(1 + 1, 2) |
600 | |
601 | === renamed file 'dashboard/views/sru.py' => 'sru/views.py' |
602 | --- dashboard/views/sru.py 2013-01-03 21:22:50 +0000 |
603 | +++ sru/views.py 2013-01-04 18:06:05 +0000 |
604 | @@ -18,7 +18,7 @@ |
605 | from django.db.models import Sum, F |
606 | from django.template import RequestContext |
607 | |
608 | -from dashboard.models import Kernel |
609 | +from sru.models import Kernel |
610 | from common.utils import ( |
611 | JSONResponse, |
612 | MySerializer, |
I'd prefer to change have jenkins_get() and friends in common/ management/ __init_ _.py rather than common/helpers.py since that code is only used in management commands.
The sru/migrations/ 0001_initial. py logic needs to test if the table name exists and add it if it doesn't. This means we can't return after each check because none of the other checks will happen. I propose something like this:
table_names = connection. introspection. table_names( )
if 'kernels' not in table_names: create_ table(' kernels' ...
db.
if 'sru_results' not in talbe_names: create_ table(' sru_results' ...
db.