Merge lp:~linaro-infrastructure/linaro-ci-dashboard/kernel-ci into lp:linaro-ci-dashboard

Proposed by Deepti B. Kalakeri
Status: Merged
Merged at revision: 26
Proposed branch: lp:~linaro-infrastructure/linaro-ci-dashboard/kernel-ci
Merge into: lp:linaro-ci-dashboard
Diff against target: 904 lines (+722/-1)
23 files modified
Makefile (+2/-0)
config_template/build_scripts/KernelLoop.sh (+17/-0)
config_template/jenkins-jobs/KernelLoop.xml (+21/-0)
dashboard/frontend/android_build/models/android_loop.py (+1/-1)
dashboard/frontend/kernel_build/forms/kernel_loop_form.py (+26/-0)
dashboard/frontend/kernel_build/migrations/0001_initial.py (+60/-0)
dashboard/frontend/kernel_build/models/__init__.py (+1/-0)
dashboard/frontend/kernel_build/models/kernel_loop.py (+130/-0)
dashboard/frontend/kernel_build/templates/kernel_loop_create.html (+8/-0)
dashboard/frontend/kernel_build/templates/kernel_loop_detail.html (+59/-0)
dashboard/frontend/kernel_build/templates/kernel_loop_update.html (+8/-0)
dashboard/frontend/kernel_build/tests/__init__.py (+9/-0)
dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py (+109/-0)
dashboard/frontend/kernel_build/tests/test_kernel_build_views.py (+60/-0)
dashboard/frontend/kernel_build/urls.py (+34/-0)
dashboard/frontend/kernel_build/views/kernel_loop_create_view.py (+54/-0)
dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py (+42/-0)
dashboard/frontend/kernel_build/views/kernel_loop_update_view.py (+56/-0)
dashboard/frontend/models/loop.py (+3/-0)
dashboard/frontend/templates/index.html (+18/-0)
dashboard/frontend/views/index_view.py (+2/-0)
dashboard/settings.py (+1/-0)
dashboard/urls.py (+1/-0)
To merge this branch: bzr merge lp:~linaro-infrastructure/linaro-ci-dashboard/kernel-ci
Reviewer Review Type Date Requested Status
Milo Casagrande (community) Approve
Linaro Infrastructure Pending
Review via email: mp+120774@code.launchpad.net

Description of the change

This branch adds the Kernel CI loop models, forms, views for building kernel deb packages.

To post a comment you must log in.
Revision history for this message
Milo Casagrande (milo) wrote :

Hello!

On Wed, Aug 22, 2012 at 4:04 PM, Deepti B. Kalakeri
<email address hidden> wrote:
>
> === modified file 'dashboard/frontend/android_build/models/android_loop.py'
> --- dashboard/frontend/android_build/models/android_loop.py 2012-08-20 09:10:05 +0000
> +++ dashboard/frontend/android_build/models/android_loop.py 2012-08-22 13:37:45 +0000
> @@ -34,7 +34,7 @@
> BUILD_ANDROID_TOOLCHAIN_LINARO,
> )
>
> -# Inetrnal name of the board, and a user visible name
> +# Internal name of the board, and a user visible name
> BEAGLEBOARD = (r'beagleboard', 'Beagleboard')
> PANDABOARD = (r'panda', 'Pandaboard')
> SNOWBALL = (r'snowball', 'Snowball')

Thanks for fixing this!

> === added directory 'dashboard/frontend/kernel_build/migrations'
> === added file 'dashboard/frontend/kernel_build/migrations/0001_initial.py'
>
> === added file 'dashboard/frontend/kernel_build/migrations/0002_auto__del_field_kernelloop_lava_test_plan__del_field_kernelloop_lava_s.py'

About this, can we just have one migration? We are starting from
scratch basically, so I think it could be good to have just one.

> === added file 'dashboard/frontend/kernel_build/models/kernel_loop.py'

Regarding this one, some PEP8 fixes:
models/kernel_loop.py:24:69: W291 trailing whitespace
models/kernel_loop.py:36:9: E222 multiple spaces after operator
models/kernel_loop.py:37:24: E203 whitespace before ','
models/kernel_loop.py:89:80: E501 line too long (81 characters)
models/kernel_loop.py:95:52: E231 missing whitespace after ','
models/kernel_loop.py:106:1: W293 blank line contains whitespace
models/kernel_loop.py:116:5: E303 too many blank lines (2)

> +#Internal name of the board, and a user visible name
> +BEAGLEBOARD = (r'beagleboard', 'Beagleboard')
> +PANDABOARD = (r'panda', 'Pandaboard')
> +SNOWBALL = (r'snowball', 'Snowball')
> +VEXPRESS = (r'vexpress', 'Vexpress')

As soon as we land everything, and maybe start working also on Ubuntu
loop, we can sit down and think what we should take out from the
different loops and create separate tables.
The previous elements call for it, since they are used also in android_build.
Same thing for a generic "Repository" one, as we already discussed.

> + def schedule_build(self):
> + # Every time before the build is scheduled, update the
> + # loop config on the remote server.
> + self.server.create_or_update_integration_loop(self)
> + super(KernelLoop, self).schedule_build()

As we discovered during working with android_build, this method is not
called, ever. The one that will be called is always the one inside
Loop, as long as you do not create your own "KernelBuildView" class
that inherits from "LoopBuildView" (loop_build_view). Doing this makes
sense only if you have to pass special parameters to Jenkins (as we
have to do with android_build).
It is safe to remove it.

Another thing, a couple of tests might be good to have, even if they
are repeating, at least if we start refactoring we will be sure that
what gets broken will be fixed.

--
Milo Casagrande
Infrastructure Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs

Revision history for this message
Milo Casagrande (milo) wrote :

On Thu, Aug 23, 2012 at 12:18 PM, Milo Casagrande
<email address hidden> wrote:
>
> Another thing, a couple of tests might be good to have, even if they
> are repeating, at least if we start refactoring we will be sure that
> what gets broken will be fixed.

Saw now the branch with the tests. Forget that comment then.

--
Milo Casagrande
Infrastructure Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs

Revision history for this message
Milo Casagrande (milo) :
review: Needs Fixing
38. By Deepti B. Kalakeri

Added tests for Kernel CI changes

39. By Paul Sokolovsky

Show list of kernel loops on frontpage, just all the other loops.

Revision history for this message
Paul Sokolovsky (pfalcon) wrote :

Tests were merged to this branch now.

40. By Paul Sokolovsky

Squash development migrations into one before merging to trunk.

Revision history for this message
Paul Sokolovsky (pfalcon) wrote :

>> === added file 'dashboard/frontend/kernel_build/migrations/0002_auto__del_field_kernelloop_lava_test_plan__del_field_kernelloop_lava_s.py'

> About this, can we just have one migration? We are starting from
> scratch basically, so I think it could be good to have just one.

Makes sense, done.

Revision history for this message
Paul Sokolovsky (pfalcon) wrote :

>As soon as we land everything, and maybe start working also on Ubuntu
loop, we can sit down and think what we should take out from the
different loops and create separate tables.

By all means, current stuff doesn't scale at all, but as Danilo commented it, it's something material for refactoring.

Revision history for this message
Paul Sokolovsky (pfalcon) wrote :

>> + def schedule_build(self):

> As we discovered during working with android_build, this method is not
called, ever.
[]
> It is safe to remove it.

Well, this method currently present as is in all 3 models we have. Thus, it should be removed consistently from all 3 models, with good commit message. So, I'd prefer to leave that for future refactoring.

41. By Deepti B. Kalakeri

pep fixes

Revision history for this message
Deepti B. Kalakeri (deeptik) wrote :

Pushed pep fixes as well. So I guess all the comment have been addressed.
Please review the same and let us know.

Thanks!!!
Deepti

Revision history for this message
Milo Casagrande (milo) wrote :

Hello there!
Thanks for working on it, looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2012-08-17 14:20:47 +0000
3+++ Makefile 2012-08-23 12:29:48 +0000
4@@ -14,6 +14,8 @@
5 echo "No changes to jenkins models."
6 python dashboard/manage.py schemamigration android_build --auto || \
7 echo "No changes to android_build models."
8+ python dashboard/manage.py schemamigration kernel_build --auto || \
9+ echo "No changes to kernel_build models."
10 python dashboard/manage.py schemamigration integration_loop --auto || \
11 echo "No changes to integration_loop models."
12 python dashboard/manage.py migrate
13
14=== added file 'config_template/build_scripts/KernelLoop.sh'
15--- config_template/build_scripts/KernelLoop.sh 1970-01-01 00:00:00 +0000
16+++ config_template/build_scripts/KernelLoop.sh 2012-08-23 12:29:48 +0000
17@@ -0,0 +1,17 @@
18+build_script_dir="lci-build-tools"
19+git clone {kernel_git_repo} . || true
20+git fetch
21+git checkout {kernel_branch}
22+git merge origin/{kernel_branch}
23+if [ -d "$build_script_dir" ]; then
24+ rm -rf "$build_script_dir"
25+fi
26+export hwpack_type={hwpack_type}
27+export board_type={board_type}
28+export kernel_flavour={kernel_flavour}
29+export kernel_config={kernel_config}
30+export rootfs_type={rootfs_type}
31+bzr branch {build_tools_branch} "$build_script_dir"
32+./"$build_script_dir"/jenkins_kernel_build_inst
33+# TODO: Add required EULA/OPEN-EULA file when
34+# we decide to submit the test hwpack to snapshots.linaro.org
35
36=== added file 'config_template/jenkins-jobs/KernelLoop.xml'
37--- config_template/jenkins-jobs/KernelLoop.xml 1970-01-01 00:00:00 +0000
38+++ config_template/jenkins-jobs/KernelLoop.xml 2012-08-23 12:29:48 +0000
39@@ -0,0 +1,21 @@
40+<?xml version='1.0' encoding='UTF-8'?>
41+<project>
42+ <actions/>
43+ <description></description>
44+ <keepDependencies>false</keepDependencies>
45+ <properties/>
46+ <scm class="hudson.scm.NullSCM"/>
47+ <canRoam>true</canRoam>
48+ <disabled>false</disabled>
49+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
50+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
51+ <triggers class="vector"/>
52+ <concurrentBuild>false</concurrentBuild>
53+ <builders>
54+ <hudson.tasks.Shell>
55+ <command>{build_script}</command>
56+ </hudson.tasks.Shell>
57+ </builders>
58+ <publishers/>
59+ <buildWrappers/>
60+</project>
61
62=== modified file 'dashboard/frontend/android_build/models/android_loop.py'
63--- dashboard/frontend/android_build/models/android_loop.py 2012-08-20 09:10:05 +0000
64+++ dashboard/frontend/android_build/models/android_loop.py 2012-08-23 12:29:48 +0000
65@@ -34,7 +34,7 @@
66 BUILD_ANDROID_TOOLCHAIN_LINARO,
67 )
68
69-# Inetrnal name of the board, and a user visible name
70+# Internal name of the board, and a user visible name
71 BEAGLEBOARD = (r'beagleboard', 'Beagleboard')
72 PANDABOARD = (r'panda', 'Pandaboard')
73 SNOWBALL = (r'snowball', 'Snowball')
74
75=== added directory 'dashboard/frontend/kernel_build'
76=== added file 'dashboard/frontend/kernel_build/__init__.py'
77=== added directory 'dashboard/frontend/kernel_build/forms'
78=== added file 'dashboard/frontend/kernel_build/forms/__init__.py'
79=== added file 'dashboard/frontend/kernel_build/forms/kernel_loop_form.py'
80--- dashboard/frontend/kernel_build/forms/kernel_loop_form.py 1970-01-01 00:00:00 +0000
81+++ dashboard/frontend/kernel_build/forms/kernel_loop_form.py 2012-08-23 12:29:48 +0000
82@@ -0,0 +1,26 @@
83+#!/usr/bin/env python
84+# Copyright (C) 2012 Linaro
85+#
86+# This file is part of linaro-ci-dashboard.
87+#
88+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
89+# it under the terms of the GNU Affero General Public License as published by
90+# the Free Software Foundation, either version 3 of the License, or
91+# (at your option) any later version.
92+#
93+# linaro-ci-dashboard is distributed in the hope that it will be useful,
94+# but WITHOUT ANY WARRANTY; without even the implied warranty of
95+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96+# GNU Affero General Public License for more details.
97+#
98+# You should have received a copy of the GNU Affero General Public License
99+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
100+
101+from django.forms import ModelForm
102+from frontend.kernel_build.models.kernel_loop import KernelLoop
103+
104+
105+class KernelLoopForm(ModelForm):
106+ class Meta:
107+ model = KernelLoop
108+ exclude = ('server')
109
110=== added directory 'dashboard/frontend/kernel_build/migrations'
111=== added file 'dashboard/frontend/kernel_build/migrations/0001_initial.py'
112--- dashboard/frontend/kernel_build/migrations/0001_initial.py 1970-01-01 00:00:00 +0000
113+++ dashboard/frontend/kernel_build/migrations/0001_initial.py 2012-08-23 12:29:48 +0000
114@@ -0,0 +1,60 @@
115+# encoding: utf-8
116+import datetime
117+from south.db import db
118+from south.v2 import SchemaMigration
119+from django.db import models
120+
121+class Migration(SchemaMigration):
122+
123+ def forwards(self, orm):
124+
125+ # Adding model 'KernelLoop'
126+ db.create_table('kernel_build_kernelloop', (
127+ ('loop_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['frontend.Loop'], unique=True, primary_key=True)),
128+ ('build_tools_branch', self.gf('django.db.models.fields.CharField')(default='lp:linaro-ci', max_length=200)),
129+ ('kernel_git_repo', self.gf('django.db.models.fields.CharField')(default=('git://git.linaro.org/kernel/linux-linaro-tracking.git', 'Linux Linaro Tracking'), max_length=255)),
130+ ('kernel_branch', self.gf('django.db.models.fields.CharField')(default=('linux-linaro', 'linux-linaro Branch'), max_length=100)),
131+ ('kernel_config', self.gf('django.db.models.fields.CharField')(default='omap2plus_defconfig', max_length=100)),
132+ ('hwpack_type', self.gf('django.db.models.fields.CharField')(default=('panda', 'Pandaboard'), max_length=50)),
133+ ('board_type', self.gf('django.db.models.fields.CharField')(default=('panda', 'Pandaboard'), max_length=50)),
134+ ('kernel_flavour', self.gf('django.db.models.fields.CharField')(default='omap', max_length=50)),
135+ ('rootfs_type', self.gf('django.db.models.fields.CharField')(default='nano', max_length=100)),
136+ ))
137+ db.send_create_signal('kernel_build', ['KernelLoop'])
138+
139+
140+ def backwards(self, orm):
141+
142+ # Deleting model 'KernelLoop'
143+ db.delete_table('kernel_build_kernelloop')
144+
145+
146+ models = {
147+ 'frontend.loop': {
148+ 'Meta': {'object_name': 'Loop'},
149+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
150+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
151+ 'server': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['jenkinsserver.JenkinsServer']"})
152+ },
153+ 'jenkinsserver.jenkinsserver': {
154+ 'Meta': {'object_name': 'JenkinsServer'},
155+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
156+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
157+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
158+ 'username': ('django.db.models.fields.CharField', [], {'max_length': '100'})
159+ },
160+ 'kernel_build.kernelloop': {
161+ 'Meta': {'object_name': 'KernelLoop', '_ormbases': ['frontend.Loop']},
162+ 'board_type': ('django.db.models.fields.CharField', [], {'default': "('panda', 'Pandaboard')", 'max_length': '50'}),
163+ 'build_tools_branch': ('django.db.models.fields.CharField', [], {'default': "'lp:linaro-ci'", 'max_length': '200'}),
164+ 'hwpack_type': ('django.db.models.fields.CharField', [], {'default': "('panda', 'Pandaboard')", 'max_length': '50'}),
165+ 'kernel_branch': ('django.db.models.fields.CharField', [], {'default': "('linux-linaro', 'linux-linaro Branch')", 'max_length': '100'}),
166+ 'kernel_config': ('django.db.models.fields.CharField', [], {'default': "'omap2plus_defconfig'", 'max_length': '100'}),
167+ 'kernel_flavour': ('django.db.models.fields.CharField', [], {'default': "'omap'", 'max_length': '50'}),
168+ 'kernel_git_repo': ('django.db.models.fields.CharField', [], {'default': "('git://git.linaro.org/kernel/linux-linaro-tracking.git', 'Linux Linaro Tracking')", 'max_length': '255'}),
169+ 'loop_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['frontend.Loop']", 'unique': 'True', 'primary_key': 'True'}),
170+ 'rootfs_type': ('django.db.models.fields.CharField', [], {'default': "'nano'", 'max_length': '100'})
171+ }
172+ }
173+
174+ complete_apps = ['kernel_build']
175
176=== added file 'dashboard/frontend/kernel_build/migrations/__init__.py'
177=== added directory 'dashboard/frontend/kernel_build/models'
178=== added file 'dashboard/frontend/kernel_build/models/__init__.py'
179--- dashboard/frontend/kernel_build/models/__init__.py 1970-01-01 00:00:00 +0000
180+++ dashboard/frontend/kernel_build/models/__init__.py 2012-08-23 12:29:48 +0000
181@@ -0,0 +1,1 @@
182+from frontend.kernel_build.models.kernel_loop import KernelLoop
183
184=== added file 'dashboard/frontend/kernel_build/models/kernel_loop.py'
185--- dashboard/frontend/kernel_build/models/kernel_loop.py 1970-01-01 00:00:00 +0000
186+++ dashboard/frontend/kernel_build/models/kernel_loop.py 2012-08-23 12:29:48 +0000
187@@ -0,0 +1,130 @@
188+#!/usr/bin/env python
189+# Copyright (C) 2012 Linaro
190+#
191+# This file is part of linaro-ci-dashboard.
192+#
193+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
194+# it under the terms of the GNU Affero General Public License as published by
195+# the Free Software Foundation, either version 3 of the License, or
196+# (at your option) any later version.
197+#
198+# linaro-ci-dashboard is distributed in the hope that it will be useful,
199+# but WITHOUT ANY WARRANTY; without even the implied warranty of
200+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201+# GNU Affero General Public License for more details.
202+#
203+# You should have received a copy of the GNU Affero General Public License
204+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
205+
206+from django.db import models
207+from frontend.models.loop import Loop
208+from jenkinsserver.models.jenkins_server import JenkinsServer
209+
210+
211+LLT_URL = (r'git://git.linaro.org/kernel/linux-linaro-tracking.git',
212+ 'Linux Linaro Tracking')
213+LN_URL = (r'git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git',
214+ 'Linux Next')
215+LM_URL = (r'git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git',
216+ 'Linux Master')
217+LARM_URL = (r'git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git',
218+ 'Linux ARM SoC')
219+
220+REPO_URLS = (LLT_URL, LN_URL, LM_URL, LARM_URL)
221+
222+# Kernel branches names
223+MASTER = (r'master', 'Master Branch')
224+FOR_NEXT = (r'for-next', 'for-next Branch')
225+LLT = (r'linux-linaro-tracking', 'linux-linaro-tracking Branch')
226+LL = (r'linux-linaro', 'linux-linaro Branch')
227+
228+REPO_BRANCHES = (MASTER, FOR_NEXT, LLT, LL)
229+
230+#Internal name of the board, and a user visible name
231+BEAGLEBOARD = (r'beagleboard', 'Beagleboard')
232+PANDABOARD = (r'panda', 'Pandaboard')
233+SNOWBALL = (r'snowball', 'Snowball')
234+VEXPRESS = (r'vexpress', 'Vexpress')
235+# The supported boards for the build.
236+HWPACK_TYPES = (BEAGLEBOARD, PANDABOARD, SNOWBALL, VEXPRESS)
237+
238+#LAVA board names
239+SNOWBALL = (r'snowball_sd', 'Snowball')
240+BOARD_TYPES = (BEAGLEBOARD, PANDABOARD, SNOWBALL, VEXPRESS)
241+
242+# Kernel Config names
243+KERNEL_CONFIGS = (
244+ (r'omap2plus_defconfig', 'omap2plus'),
245+ (r'u8500_defconfig', 'u8500'),
246+ (r'exynos4_defconfig', 'exynos4'),
247+ (r'vexpress_defconfig', 'vexpress'),
248+ )
249+
250+# ROOTFS types
251+ROOTFS_TYPES = (
252+ (r'nano', 'Nano image'),
253+ (r'developer', 'Developer image'),
254+ )
255+
256+#Kernel Flavours
257+KERNEL_FLAVOURS = (
258+ (r'omap', 'Omap'),
259+ (r'origen', 'Origen'),
260+ (r'vexpress', 'Vexpress'),
261+ (r'u8500', 'U8500'),
262+ )
263+
264+
265+class KernelLoop(Loop):
266+ class Meta:
267+ app_label = 'kernel_build'
268+
269+ # The default values used by the build scripts
270+ DEFAULT_KERNEL_CONFIG = 'omap2plus_defconfig'
271+ DEFAULT_HWPACK_TYPE = DEFAULT_BOARD_TYPE = PANDABOARD
272+ DEFAULT_KERNEL_FLAVOUR = 'omap'
273+ DEFAULT_ROOTFS_TYPE = 'nano'
274+
275+ # The branch containing the build scripts used for kernel builds
276+ build_tools_branch = models.CharField(max_length=200,
277+ default='lp:linaro-ci')
278+
279+ # GIT REPO
280+ kernel_git_repo = models.CharField(max_length=255, choices=REPO_URLS,
281+ default=LLT_URL)
282+ # GIT REPO BRANCH
283+ kernel_branch = models.CharField(max_length=100, choices=REPO_BRANCHES,
284+ default=LL)
285+ # KERNEL CONFIGS
286+ kernel_config = models.CharField(max_length=100, choices=KERNEL_CONFIGS,
287+ default=DEFAULT_KERNEL_CONFIG)
288+ # HWPACK_TYPE
289+ hwpack_type = models.CharField(max_length=50, choices=HWPACK_TYPES,
290+ default=DEFAULT_HWPACK_TYPE)
291+ # BOARD TYPE
292+ board_type = models.CharField(max_length=50, choices=BOARD_TYPES,
293+ default=DEFAULT_BOARD_TYPE)
294+ # KERNEL FLAVOUR
295+ kernel_flavour = models.CharField(max_length=50, choices=KERNEL_FLAVOURS,
296+ default=DEFAULT_KERNEL_FLAVOUR)
297+
298+ # ROOTFS TYPES
299+ rootfs_type = models.CharField(max_length=100, choices=ROOTFS_TYPES,
300+ default=DEFAULT_ROOTFS_TYPE)
301+
302+ def save(self, *args, **kwargs):
303+ self.server = JenkinsServer.objects.get(id=1)
304+ super(KernelLoop, self).save(*args, **kwargs)
305+ # We do not want a failure in remote server to affect the
306+ # CI Loop flow.
307+ try:
308+ self.server.create_or_update_integration_loop(self)
309+ except:
310+ # TODO: Log error.
311+ pass
312+
313+ def schedule_build(self):
314+ # Every time before the build is scheduled, update the
315+ # loop config on the remote server.
316+ self.server.create_or_update_integration_loop(self)
317+ super(KernelLoop, self).schedule_build()
318
319=== added directory 'dashboard/frontend/kernel_build/templates'
320=== added file 'dashboard/frontend/kernel_build/templates/__init__.py'
321=== added file 'dashboard/frontend/kernel_build/templates/kernel_loop_create.html'
322--- dashboard/frontend/kernel_build/templates/kernel_loop_create.html 1970-01-01 00:00:00 +0000
323+++ dashboard/frontend/kernel_build/templates/kernel_loop_create.html 2012-08-23 12:29:48 +0000
324@@ -0,0 +1,8 @@
325+{% extends "base.html" %}
326+
327+{% block content %}
328+<form action="{% url KernelLoopCreate %}" method="post">{% csrf_token %}
329+{{ form.as_p }}
330+<div><input type="submit" value="Submit" /></div>
331+</form>
332+{% endblock %}
333
334=== added file 'dashboard/frontend/kernel_build/templates/kernel_loop_detail.html'
335--- dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 1970-01-01 00:00:00 +0000
336+++ dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 2012-08-23 12:29:48 +0000
337@@ -0,0 +1,59 @@
338+{% extends "base.html" %}
339+
340+{% block breadcrumbs %}
341+<div>
342+<a href="{% url Index %}">Index</a>
343+</div>
344+{% endblock %}
345+
346+{% block content %}
347+ <h2>Loop {{ kernel_loop_detail.name }}</h2>
348+
349+ <h4>Details</h4>
350+ <div>
351+ <table>
352+ {% for k, v in kernel_loop_detail.json.items %}
353+ <tr><td>{{ k }}</td><td>{{ v }}</td></tr>
354+ {% endfor %}
355+ </table>
356+ </div>
357+
358+ <div>
359+ <button type="button" id="update_button">Update loop configuration</button>
360+ </div>
361+
362+ <h4>Builds</h4>
363+ <div id="builds">
364+ {% for build in builds %}
365+ <div id="build_{{ build.id }}">
366+ Build: {{ build.build_number }} || {{ build.status }} || {{ build.duration }} || {{ build.remote_number }}
367+ </div>
368+ {% endfor %}
369+ </div>
370+
371+ <div>
372+ <button type="button" id="schedule_button">Schedule new build</button>
373+ </div>
374+{% endblock %}
375+
376+{% block scripts %}
377+<script type="text/javascript">
378+$("#schedule_button").click(function() {
379+ $.get("{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}/loop/build/{{ kernel_loop_detail.name }}/", function(data) {
380+ data = $.parseJSON(data);
381+ $("<div/>", {
382+ "class": "test",
383+ text: "Build: " + data[0].fields.build_number + " || " +
384+ data[0].fields.status + " || " +
385+ data[0].fields.duration + " || " +
386+ data[0].fields.remote_number,
387+ })
388+ .prependTo($("#builds"));
389+ });
390+});
391+
392+$("#update_button").click(function() {
393+ window.location.href = "{% url KernelLoopUpdate kernel_loop_detail.name %}";
394+});
395+</script>
396+{% endblock %}
397
398=== added file 'dashboard/frontend/kernel_build/templates/kernel_loop_update.html'
399--- dashboard/frontend/kernel_build/templates/kernel_loop_update.html 1970-01-01 00:00:00 +0000
400+++ dashboard/frontend/kernel_build/templates/kernel_loop_update.html 2012-08-23 12:29:48 +0000
401@@ -0,0 +1,8 @@
402+{% extends "base.html" %}
403+
404+{% block content %}
405+<form action="{% url KernelLoopUpdate kernel_loop_update.name %}" method="post">{% csrf_token %}
406+{{ form.as_p }}
407+<div><input type="submit" value="Submit" /></div>
408+</form>
409+{% endblock %}
410
411=== added directory 'dashboard/frontend/kernel_build/tests'
412=== added file 'dashboard/frontend/kernel_build/tests/__init__.py'
413--- dashboard/frontend/kernel_build/tests/__init__.py 1970-01-01 00:00:00 +0000
414+++ dashboard/frontend/kernel_build/tests/__init__.py 2012-08-23 12:29:48 +0000
415@@ -0,0 +1,9 @@
416+from dashboard.frontend.kernel_build.tests.test_kernel_build_views import *
417+from dashboard.frontend.kernel_build.tests.test_kernel_build_clientresponse \
418+ import *
419+
420+
421+__test__ = {
422+ 'KernelBuildViewsTest': KernelBuildViewsTest,
423+ 'KernelBuildClientResponseTests': KernelBuildClientResponseTests,
424+}
425
426=== added file 'dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py'
427--- dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 1970-01-01 00:00:00 +0000
428+++ dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 2012-08-23 12:29:48 +0000
429@@ -0,0 +1,109 @@
430+# Copyright (C) 2012 Linaro
431+#
432+# This file is part of linaro-ci-dashboard.
433+#
434+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
435+# it under the terms of the GNU Affero General Public License as published by
436+# the Free Software Foundation, either version 3 of the License, or
437+# (at your option) any later version.
438+#
439+# linaro-ci-dashboard is distributed in the hope that it will be useful,
440+# but WITHOUT ANY WARRANTY; without even the implied warranty of
441+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
442+# GNU Affero General Public License for more details.
443+#
444+# You should have received a copy of the GNU Affero General Public License
445+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
446+import urlparse
447+
448+from frontend.tests.test_clientresponse import ClientResponseTestsGeneral
449+
450+
451+class KernelBuildClientResponseTests(ClientResponseTestsGeneral):
452+
453+ def setUp(self):
454+ super(KernelBuildClientResponseTests, self).setUp()
455+ self.kernel_build_data = {"name": "kernel_build",
456+ "kernel_git_repo": \
457+ "git://git.linaro.org/kernel/linux-linaro-tracking.git",
458+ "rootfs_type": "nano",
459+ "loop_ptr": 1,
460+ "server": 1,
461+ "build_tools_branch": "linaro-ci",
462+ "board_type": "panda",
463+ "hwpack_type": "panda",
464+ "kernel_config": "omap2plus_defconfig",
465+ "kernel_branch": "linux-linaro",
466+ "id": 1,
467+ "kernel_flavour": "omap"}
468+
469+ def test_kernel_build_create_get(self):
470+ self.client.login(username=self.user, password=self.passwd)
471+ response = self.client.get("/kernel/create/")
472+ self.assertIn("/kernel/create/", response.content)
473+ template_names = [template.name for template in
474+ response.templates]
475+ self.assertEquals(template_names, ["kernel_loop_create.html",
476+ "base.html",
477+ "login.html",
478+ ])
479+
480+ def test_kernel_build_create_post_no_data(self):
481+ self.client.login(username=self.user, password=self.passwd)
482+ response = self.client.post("/kernel/create/", {})
483+ self.assertEquals(response.status_code, 200)
484+ self.assertIn("This field is required", response.content)
485+
486+ def test_kernel_build_create_post(self):
487+ self.client.login(username=self.user, password=self.passwd)
488+
489+ # Follow redirect after save.
490+ response = self.client.post("/kernel/create/",
491+ self.kernel_build_data, follow=True)
492+ # Assert response code.
493+ self.assertEquals(response.status_code, 200)
494+ # Assert content for required fields filled
495+ self.assertNotIn("This field is required", response.content)
496+ # Assert template names for detail page.
497+ template_names = [template.name for template in
498+ response.templates]
499+ self.assertEquals(template_names, ["kernel_loop_detail.html",
500+ "base.html",
501+ "login.html",
502+ ])
503+ # Assert if everything is present on detail page.
504+ for key in self.kernel_build_data.iterkeys():
505+ self.assertIn(str(self.kernel_build_data[key]), response.content)
506+
507+
508+ def test_kernel_build_create_repost_error(self):
509+ self.client.login(username=self.user, password=self.passwd)
510+
511+ # Follow redirect after save.
512+ response = self.client.post("/kernel/create/",
513+ self.kernel_build_data, follow=True)
514+ # Assert response code.
515+ self.assertEquals(response.status_code, 200)
516+ response = self.client.post("/kernel/create/",
517+ self.kernel_build_data, follow=True)
518+ self.assertIn("Loop with this Name already exists.", response.content)
519+
520+
521+ def test_kernel_build_detail_get(self):
522+ self.client.login(username=self.user, password=self.passwd)
523+
524+ # Follow redirect after save.
525+ target_file = "/kernel/create/"
526+ url = urlparse.urljoin("http://testserver/", target_file)
527+ response = self.client.post(url, self.kernel_build_data, follow=True)
528+ # Assert response code.
529+ self.assertEquals(response.status_code, 200)
530+ # Assert content for required fields filled
531+ self.assertNotIn("This field is required", response.content)
532+
533+ target_file = "/kernel/detail/%s/" % self.kernel_build_data["name"]
534+ url = urlparse.urljoin("http://testserver/", target_file)
535+ response = self.client.get(url, follow=True)
536+ # Assert response code.
537+ self.assertEquals(response.status_code, 200)
538+ self.assertIn("Details", response.content)
539
540=== added file 'dashboard/frontend/kernel_build/tests/test_kernel_build_views.py'
541--- dashboard/frontend/kernel_build/tests/test_kernel_build_views.py 1970-01-01 00:00:00 +0000
542+++ dashboard/frontend/kernel_build/tests/test_kernel_build_views.py 2012-08-23 12:29:48 +0000
543@@ -0,0 +1,60 @@
544+# Copyright (C) 2012 Linaro
545+#
546+# This file is part of linaro-ci-dashboard.
547+#
548+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
549+# it under the terms of the GNU Affero General Public License as published by
550+# the Free Software Foundation, either version 3 of the License, or
551+# (at your option) any later version.
552+#
553+# linaro-ci-dashboard is distributed in the hope that it will be useful,
554+# but WITHOUT ANY WARRANTY; without even the implied warranty of
555+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
556+# GNU Affero General Public License for more details.
557+#
558+# You should have received a copy of the GNU Affero General Public License
559+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
560+from django.test import TestCase
561+from mock import MagicMock
562+
563+from frontend.kernel_build.views.kernel_loop_create_view \
564+ import KernelLoopCreateView
565+from frontend.kernel_build.views.kernel_loop_detail_view \
566+ import KernelLoopDetailView
567+from frontend.kernel_build.views.kernel_loop_update_view\
568+ import KernelLoopUpdateView
569+
570+
571+class KernelBuildViewsTest(TestCase):
572+
573+ def setUp(self):
574+ self.mock_loop = MagicMock()
575+ self.mock_loop.loop_ptr = MagicMock()
576+ self.mock_loop.loop_ptr.id = 0
577+ self.mock_loop.loop_ptr.loopbuild_set = MagicMock()
578+ self.mock_loop.loop_ptr.loopbuild_set.all = MagicMock()
579+
580+ def test_create_view_get_context_data(self):
581+ kernel_loop_create_view = KernelLoopCreateView()
582+ kernel_loop_create_view.request = "some request data"
583+ kernel_loop_create_view.object = self.mock_loop
584+ context = KernelLoopCreateView.get_context_data(
585+ kernel_loop_create_view)
586+ self.assertEqual(context['request'], "some request data")
587+
588+ def test_detail_view_get_context_data(self):
589+ kernel_loop_detail_view = KernelLoopDetailView()
590+ kernel_loop_detail_view.request = "some request data"
591+ kernel_loop_detail_view.object = self.mock_loop
592+ context = KernelLoopDetailView.get_context_data(
593+ kernel_loop_detail_view)
594+ self.assertEqual(context['request'], "some request data")
595+ self.assertEqual(context['builds'].__class__.__name__, "MagicMock")
596+
597+ def test_update_view_get_context_data(self):
598+ kernel_loop_update_view = KernelLoopUpdateView()
599+ kernel_loop_update_view.request = "some request data"
600+ kernel_loop_update_view.object = self.mock_loop
601+ context = KernelLoopUpdateView.get_context_data(
602+ kernel_loop_update_view)
603+ self.assertEqual(context['request'], "some request data")
604
605=== added file 'dashboard/frontend/kernel_build/urls.py'
606--- dashboard/frontend/kernel_build/urls.py 1970-01-01 00:00:00 +0000
607+++ dashboard/frontend/kernel_build/urls.py 2012-08-23 12:29:48 +0000
608@@ -0,0 +1,34 @@
609+# Copyright (C) 2012 Linaro
610+#
611+# This file is part of linaro-ci-dashboard.
612+#
613+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
614+# it under the terms of the GNU Affero General Public License as published by
615+# the Free Software Foundation, either version 3 of the License, or
616+# (at your option) any later version.
617+#
618+# linaro-ci-dashboard is distributed in the hope that it will be useful,
619+# but WITHOUT ANY WARRANTY; without even the implied warranty of
620+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
621+# GNU Affero General Public License for more details.
622+#
623+# You should have received a copy of the GNU Affero General Public License
624+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
625+
626+from django.conf.urls.defaults import patterns, include, url
627+from frontend.kernel_build.views.kernel_loop_create_view \
628+ import KernelLoopCreateView
629+from frontend.kernel_build.views.kernel_loop_update_view \
630+ import KernelLoopUpdateView
631+from frontend.kernel_build.views.kernel_loop_detail_view \
632+ import KernelLoopDetailView
633+
634+
635+urlpatterns = patterns('',
636+ url(r'^kernel/create/$',
637+ KernelLoopCreateView.as_view(), name='KernelLoopCreate'),
638+ url(r'^kernel/detail/(?P<slug>[\w|\W]+)/$',
639+ KernelLoopDetailView.as_view(), name='KernelLoopDetail'),
640+ url(r'^kernel/update/(?P<slug>[\w|\W]+)/$',
641+ KernelLoopUpdateView.as_view(), name='KernelLoopUpdate'),
642+)
643
644=== added directory 'dashboard/frontend/kernel_build/views'
645=== added file 'dashboard/frontend/kernel_build/views/__init__.py'
646=== added file 'dashboard/frontend/kernel_build/views/kernel_loop_create_view.py'
647--- dashboard/frontend/kernel_build/views/kernel_loop_create_view.py 1970-01-01 00:00:00 +0000
648+++ dashboard/frontend/kernel_build/views/kernel_loop_create_view.py 2012-08-23 12:29:48 +0000
649@@ -0,0 +1,54 @@
650+#!/usr/bin/env python
651+# Copyright (C) 2012 Linaro
652+#
653+# This file is part of linaro-ci-dashboard.
654+#
655+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
656+# it under the terms of the GNU Affero General Public License as published by
657+# the Free Software Foundation, either version 3 of the License, or
658+# (at your option) any later version.
659+#
660+# linaro-ci-dashboard is distributed in the hope that it will be useful,
661+# but WITHOUT ANY WARRANTY; without even the implied warranty of
662+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
663+# GNU Affero General Public License for more details.
664+#
665+# You should have received a copy of the GNU Affero General Public License
666+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
667+
668+from django.contrib.auth.decorators import login_required
669+from django.core.urlresolvers import reverse
670+from django.views.generic.edit import CreateView
671+from django.utils.decorators import method_decorator
672+from frontend.kernel_build.forms.kernel_loop_form \
673+ import KernelLoopForm
674+from frontend.kernel_build.models.kernel_loop import KernelLoop
675+
676+
677+class KernelLoopCreateView(CreateView):
678+
679+ template_name = "kernel_loop_create.html"
680+ form_class = KernelLoopForm
681+ model = KernelLoop
682+
683+ def form_valid(self, form):
684+ """This method is called when valid form data has been POSTed.
685+
686+ It should return an HttpResponse."""
687+
688+ return super(KernelLoopCreateView, self).form_valid(form)
689+
690+ @method_decorator(login_required)
691+ def dispatch(self, *args, **kwargs):
692+ return super(KernelLoopCreateView, self).dispatch(*args, **kwargs)
693+
694+ def get_context_data(self, **kwargs):
695+ '''Get the context data passed to template.'''
696+ context = super(KernelLoopCreateView,
697+ self).get_context_data(**kwargs)
698+ context['request'] = self.request
699+ return context
700+
701+ def get_success_url(self):
702+ '''Return the URL when the form is valid.'''
703+ return reverse('KernelLoopDetail', args=[self.object.name])
704
705=== added file 'dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py'
706--- dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 1970-01-01 00:00:00 +0000
707+++ dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 2012-08-23 12:29:48 +0000
708@@ -0,0 +1,42 @@
709+#!/usr/bin/env python
710+# Copyright (C) 2012 Linaro
711+#
712+# This file is part of linaro-ci-dashboard.
713+#
714+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
715+# it under the terms of the GNU Affero General Public License as published by
716+# the Free Software Foundation, either version 3 of the License, or
717+# (at your option) any later version.
718+#
719+# linaro-ci-dashboard is distributed in the hope that it will be useful,
720+# but WITHOUT ANY WARRANTY; without even the implied warranty of
721+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
722+# GNU Affero General Public License for more details.
723+#
724+# You should have received a copy of the GNU Affero General Public License
725+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
726+
727+from django.contrib.auth.decorators import login_required
728+from django.views.generic.detail import DetailView
729+from django.utils.decorators import method_decorator
730+from frontend.kernel_build.models.kernel_loop import KernelLoop
731+
732+
733+class KernelLoopDetailView(DetailView):
734+
735+ model = KernelLoop
736+ context_object_name = 'kernel_loop_detail'
737+ slug_field = "name"
738+ template_name = "kernel_loop_detail.html"
739+
740+ @method_decorator(login_required)
741+ def dispatch(self, *args, **kwargs):
742+ return super(KernelLoopDetailView, self).dispatch(*args, **kwargs)
743+
744+ def get_context_data(self, **kwargs):
745+ '''Get the context data passed to template.'''
746+ context = super(KernelLoopDetailView,
747+ self).get_context_data(**kwargs)
748+ context['request'] = self.request
749+ context['builds'] = self.object.loop_ptr.loopbuild_set.all()
750+ return context
751
752=== added file 'dashboard/frontend/kernel_build/views/kernel_loop_update_view.py'
753--- dashboard/frontend/kernel_build/views/kernel_loop_update_view.py 1970-01-01 00:00:00 +0000
754+++ dashboard/frontend/kernel_build/views/kernel_loop_update_view.py 2012-08-23 12:29:48 +0000
755@@ -0,0 +1,56 @@
756+#!/usr/bin/env python
757+# Copyright (C) 2012 Linaro
758+#
759+# This file is part of linaro-ci-dashboard.
760+#
761+# linaro-ci-dashboard is free software: you can redistribute it and/or modify
762+# it under the terms of the GNU Affero General Public License as published by
763+# the Free Software Foundation, either version 3 of the License, or
764+# (at your option) any later version.
765+#
766+# linaro-ci-dashboard is distributed in the hope that it will be useful,
767+# but WITHOUT ANY WARRANTY; without even the implied warranty of
768+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
769+# GNU Affero General Public License for more details.
770+#
771+# You should have received a copy of the GNU Affero General Public License
772+# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
773+
774+from django.contrib.auth.decorators import login_required
775+from django.core.urlresolvers import reverse
776+from django.views.generic.edit import UpdateView
777+from django.utils.decorators import method_decorator
778+from frontend.kernel_build.forms.kernel_loop_form \
779+ import KernelLoopForm
780+from frontend.kernel_build.models.kernel_loop import KernelLoop
781+
782+
783+class KernelLoopUpdateView(UpdateView):
784+
785+ template_name = "kernel_loop_update.html"
786+ form_class = KernelLoopForm
787+ context_object_name = 'kernel_loop_update'
788+ model = KernelLoop
789+ slug_field = "name"
790+
791+ def form_valid(self, form):
792+ """This method is called when valid form data has been POSTed.
793+
794+ It should return an HttpResponse."""
795+
796+ return super(KernelLoopUpdateView, self).form_valid(form)
797+
798+ @method_decorator(login_required)
799+ def dispatch(self, *args, **kwargs):
800+ return super(KernelLoopUpdateView, self).dispatch(*args, **kwargs)
801+
802+ def get_context_data(self, **kwargs):
803+ '''Get the context data passed to template.'''
804+ context = super(KernelLoopUpdateView,
805+ self).get_context_data(**kwargs)
806+ context['request'] = self.request
807+ return context
808+
809+ def get_success_url(self):
810+ '''Return the URL when the form is valid.'''
811+ return reverse('KernelLoopDetail', args=[self.object.name])
812
813=== modified file 'dashboard/frontend/models/loop.py'
814--- dashboard/frontend/models/loop.py 2012-08-21 09:46:34 +0000
815+++ dashboard/frontend/models/loop.py 2012-08-23 12:29:48 +0000
816@@ -54,3 +54,6 @@
817 """
818 from django.forms.models import model_to_dict
819 return model_to_dict(self)
820+
821+ def __repr__(self):
822+ return "%s(id=%d, ...)" % (self.__class__.__name__, self.id)
823
824=== modified file 'dashboard/frontend/templates/index.html'
825--- dashboard/frontend/templates/index.html 2012-08-20 09:10:05 +0000
826+++ dashboard/frontend/templates/index.html 2012-08-23 12:29:48 +0000
827@@ -28,12 +28,27 @@
828 </div>
829 {% endfor %}
830 </div>
831+
832+ <h2>CI Kernel Loops</h2>
833+ <div id="kernel_loops">
834+ {% for kernel_loop in kernel_loops %}
835+ <div id="kernel_loop_{{ kernel_loop.id }}">
836+ Loop: {{ kernel_loop.id }} ||
837+ <a href="{% url KernelLoopDetail kernel_loop.name %}">
838+ {{ kernel_loop.name }}
839+ </a>
840+ </div>
841+ {% endfor %}
842+ </div>
843 <div>
844 <button type="button" id="create_button">Add new Integration loop</button>
845 </div>
846 <div>
847 <button type="button" id="create_android_button">Add new Android loop</button>
848 </div>
849+<div>
850+ <button type="button" id="create_kernel_button">Add new Kernel loop</button>
851+</div>
852 {% endblock %}
853
854 {% block scripts %}
855@@ -44,5 +59,8 @@
856 $("#create_android_button").click(function() {
857 window.location.href = "{% url AndroidLoopCreate %}";
858 });
859+$("#create_kernel_button").click(function() {
860+ window.location.href = "{% url KernelLoopCreate %}";
861+});
862 </script>
863 {% endblock %}
864
865=== modified file 'dashboard/frontend/views/index_view.py'
866--- dashboard/frontend/views/index_view.py 2012-08-20 09:10:05 +0000
867+++ dashboard/frontend/views/index_view.py 2012-08-23 12:29:48 +0000
868@@ -21,6 +21,7 @@
869 from django.contrib.auth.decorators import login_required
870 from frontend.integration_loop.models.integration_loop import IntegrationLoop
871 from frontend.android_build.models.android_loop import AndroidLoop
872+from frontend.kernel_build.models.kernel_loop import KernelLoop
873
874
875 class IndexView(TemplateView):
876@@ -36,4 +37,5 @@
877 context['request'] = self.request
878 context['integration_loops'] = IntegrationLoop.objects.all()
879 context['android_loops'] = AndroidLoop.objects.all()
880+ context['kernel_loops'] = KernelLoop.objects.all()
881 return context
882
883=== modified file 'dashboard/settings.py'
884--- dashboard/settings.py 2012-08-21 09:47:43 +0000
885+++ dashboard/settings.py 2012-08-23 12:29:48 +0000
886@@ -141,6 +141,7 @@
887 'jenkinsserver',
888 'frontend',
889 'frontend.android_build',
890+ 'frontend.kernel_build',
891 'frontend.integration_loop',
892 'south',
893 # Uncomment the next line to enable the admin:
894
895=== modified file 'dashboard/urls.py'
896--- dashboard/urls.py 2012-08-16 15:12:10 +0000
897+++ dashboard/urls.py 2012-08-23 12:29:48 +0000
898@@ -31,5 +31,6 @@
899 {'document_root': settings.JS_PATH}),
900 url(r'^', include('dashboard.frontend.urls')),
901 url(r'^', include('dashboard.frontend.android_build.urls')),
902+ url(r'^', include('dashboard.frontend.kernel_build.urls')),
903 url(r'^', include('dashboard.frontend.integration_loop.urls')),
904 )

Subscribers

People subscribed via source and target branches

to all changes: