Merge lp:~cjohnston/ubuntu-ci-services-itself/ts-project-write-api into lp:ubuntu-ci-services-itself

Proposed by Chris Johnston
Status: Merged
Approved by: Ursula Junque
Approved revision: 39
Merged at revision: 42
Proposed branch: lp:~cjohnston/ubuntu-ci-services-itself/ts-project-write-api
Merge into: lp:ubuntu-ci-services-itself
Diff against target: 299 lines (+132/-53)
4 files modified
docs/components/ticket-system.rst (+33/-0)
ticket_system/people/tests.py (+1/-1)
ticket_system/project/api.py (+7/-4)
ticket_system/project/tests.py (+91/-48)
To merge this branch: bzr merge lp:~cjohnston/ubuntu-ci-services-itself/ts-project-write-api
Reviewer Review Type Date Requested Status
Francis Ginther Approve
Ursula Junque (community) Needs Information
Review via email: mp+199173@code.launchpad.net

Commit message

Add a write API to the TS project app

Description of the change

L52/53 is just changing the name to better describe the test

To post a comment you must log in.
Revision history for this message
Francis Ginther (fginther) wrote :

A binary package may not be associated with a source package, it may just refer to a binary package that is available in the archive, but not otherwise seeded in the base image.

The changes to the binary package list should only become permanent after the ticket is successfully processed. Once the ticket is completed, they can then be integrated into the package list for future builds.

For example:

After a few successful builds, the binary package list contains unity8, mir and libmir. The most recently built package will contain these packages.

A new request is made to build a source package from the autopilot source package and add python3-autopilot and python3 to the binary package list. When this builds, python3-autopilot and python3 needs to be included in the image, but it only gets promoted to the master binary package list after a successful build and test.

With two different API calls to add binary and source packages, it's unclear to me how a build request with source and binary package updates would be atomic.

review: Needs Information
Revision history for this message
Ursula Junque (ursinha) wrote :

> A binary package may not be associated with a source package, it may just
> refer to a binary package that is available in the archive, but not otherwise
> seeded in the base image.
>
> The changes to the binary package list should only become permanent after the
> ticket is successfully processed. Once the ticket is completed, they can then
> be integrated into the package list for future builds.

I believe we have a different understanding of what this binary package list is. In my understanding for phase 0 this would be a list of seeded/relevant binary packages that should be tested when building and testing images, but as dep8 tests are part of the sources this list would be used only as input to an external script that should come up with the sources list, hence we storing only the source packages list, not binary (as described in the docs).

This is only the initial implementation of what used to be the "project manager" component (similar to cu2d-config). In your scenario, this list would change per ticket? It seems to me that this is completely different than what was understood when we discussed the tests manager/project manager/ticket system split.

>
> For example:
>
> After a few successful builds, the binary package list contains unity8, mir
> and libmir. The most recently built package will contain these packages.
>
> A new request is made to build a source package from the autopilot source
> package and add python3-autopilot and python3 to the binary package list. When
> this builds, python3-autopilot and python3 needs to be included in the image,
> but it only gets promoted to the master binary package list after a successful
> build and test.

>
> With two different API calls to add binary and source packages, it's unclear
> to me how a build request with source and binary package updates would be
> atomic.

review: Needs Information
Revision history for this message
Chris Johnston (cjohnston) wrote :

On Mon, Dec 16, 2013 at 8:28 PM, Ursula Junque wrote:

> Review: Needs Information
>
> > A binary package may not be associated with a source package, it may just
> > refer to a binary package that is available in the archive, but not
> otherwise
> > seeded in the base image.
> >
> > The changes to the binary package list should only become permanent
> after the
> > ticket is successfully processed. Once the ticket is completed, they can
> then
> > be integrated into the package list for future builds.
>
>
> I believe we have a different understanding of what this binary package
> list is. In my understanding for phase 0 this would be a list of
> seeded/relevant binary packages that should be tested when building and
> testing images, but as dep8 tests are part of the sources this list would
> be used only as input to an external script that should come up with the
> sources list, hence we storing only the source packages list, not binary
> (as described in the docs).
>
> This is only the initial implementation of what used to be the "project
> manager" component (similar to cu2d-config). In your scenario, this list
> would change per ticket? It seems to me that this is completely different
> than what was understood when we discussed the tests manager/project
> manager/ticket system split.
>
>
>
I had the same understanding that Ursula did.

> >
> > For example:
> >
> > After a few successful builds, the binary package list contains unity8,
> mir
> > and libmir. The most recently built package will contain these packages.
> >
> > A new request is made to build a source package from the autopilot source
> > package and add python3-autopilot and python3 to the binary package
> list. When
> > this builds, python3-autopilot and python3 needs to be included in the
> image,
> > but it only gets promoted to the master binary package list after a
> successful
> > build and test.
>
>
> >
> > With two different API calls to add binary and source packages, it's
> unclear
> > to me how a build request with source and binary package updates would be
> > atomic.
>
>

Revision history for this message
Francis Ginther (fginther) wrote :

Based on our conversation, this is ok to go.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'docs/components/ticket-system.rst'
2--- docs/components/ticket-system.rst 2013-12-12 16:53:14 +0000
3+++ docs/components/ticket-system.rst 2013-12-16 19:00:41 +0000
4@@ -219,6 +219,39 @@
5 curl --dump-header - http://localhost:8000/api/v1/person/?is_team=True
6 curl --dump-header - http://localhost:8000/api/v1/person/?is_team=False
7
8+Project
9+-------
10+
11+get_source_package
12+~~~~~~~~~~~~~~~~~~
13+
14+*return all binary packages*
15+
16+::
17+ curl --dump-header - http://localhost:8000/api/v1/sourcepackage/
18+
19+add_source_package
20+~~~~~~~~~~~~~~~~~~
21+
22+::
23+
24+ curl --dump-header - -H "Content-Type: application/json" -X POST --data '{"name": "my-package"}' http://localhost:8000/api/v1/sourcepackage/
25+
26+ get_binary_package
27+~~~~~~~~~~~~~~~~~~
28+
29+*return all binary packages*
30+
31+::
32+ curl --dump-header - http://localhost:8000/api/v1/binarypackage/
33+
34+add_binary_package
35+~~~~~~~~~~~~~~~~~~
36+
37+::
38+
39+ curl --dump-header - -H "Content-Type: application/json" -X POST --data '{"name": "my-package", "sourcepackage": "/api/v1/sourcepackage/1/", "seeded": "False"}' http://localhost:8000/api/v1/binarypackage/
40+
41 Models
42 ******
43
44
45=== modified file 'ticket_system/people/tests.py'
46--- ticket_system/people/tests.py 2013-12-12 16:53:14 +0000
47+++ ticket_system/people/tests.py 2013-12-16 19:00:41 +0000
48@@ -90,7 +90,7 @@
49 # Verify a new one has been added.
50 self.assertEqual(Person.objects.filter(is_team=True).count(), 1)
51
52- def test_put_detail(self):
53+ def test_patch_detail(self):
54 # Grab the current data & modify it slightly.
55 original_data = self.getResource(self.detail_url)
56 new_data = original_data.copy()
57
58=== modified file 'ticket_system/project/api.py'
59--- ticket_system/project/api.py 2013-12-09 19:35:22 +0000
60+++ ticket_system/project/api.py 2013-12-16 19:00:41 +0000
61@@ -14,6 +14,7 @@
62 # along with this program. If not, see <http://www.gnu.org/licenses/>.
63
64 from tastypie import fields
65+from tastypie.authorization import Authorization
66 from tastypie.resources import ModelResource
67 from tastypie.constants import ALL
68 from project.models import SourcePackage, BinaryPackage
69@@ -23,9 +24,10 @@
70
71 class Meta:
72 queryset = SourcePackage.objects.all()
73- allowed_methods = ['get']
74+ allowed_methods = ['get', 'post', 'patch']
75+ authorization = Authorization()
76 filtering = {
77- "name": ('exact', 'startswith'),
78+ "name": ('exact', 'iexact', 'startswith', 'istartswith'),
79 }
80
81
82@@ -35,8 +37,9 @@
83
84 class Meta:
85 queryset = BinaryPackage.objects.all()
86- allowed_methods = ['get']
87+ allowed_methods = ['get', 'post', 'patch']
88+ authorization = Authorization()
89 filtering = {
90- "name": ('exact', 'startswith'),
91+ "name": ('exact', 'iexact', 'startswith', 'istartswith'),
92 "seeded": ALL,
93 }
94
95=== modified file 'ticket_system/project/tests.py'
96--- ticket_system/project/tests.py 2013-12-10 18:29:34 +0000
97+++ ticket_system/project/tests.py 2013-12-16 19:00:41 +0000
98@@ -14,105 +14,122 @@
99 # along with this program. If not, see <http://www.gnu.org/licenses/>.
100
101 from django.test import TestCase
102+from model_mommy import mommy
103 from ci_utils.tastypie.test import TastypieTestCase
104 from project.models import SourcePackage, BinaryPackage
105
106
107-def create_sourcepackage(name="awesome-package"):
108- package = SourcePackage()
109- package.name = name
110- package.save()
111- return package
112-
113-
114-def create_binarypackage(name="awesome-binary", sourcepackage=None,
115- seeded=False):
116- binary = BinaryPackage()
117- binary.name = name
118- binary.sourcepackage = sourcepackage
119- binary.seeded = seeded
120- binary.save()
121- return binary
122-
123-
124 class SourcePackageModelTest(TestCase):
125
126- def test_creating_a_sourcepackage(self):
127- package = create_sourcepackage()
128+ def setUp(self):
129+ self.sourcepackage = mommy.make('SourcePackage')
130+
131+ def test_creating_sourcepackage(self):
132 package_in_database = SourcePackage.objects.all()
133 self.assertEquals(len(package_in_database), 1)
134 only_package_in_database = package_in_database[0]
135- self.assertEquals(only_package_in_database, package)
136+ self.assertEquals(only_package_in_database, self.sourcepackage)
137
138- self.assertEquals(only_package_in_database.name, "awesome-package")
139+ self.assertEquals(only_package_in_database.name,
140+ self.sourcepackage.name)
141
142
143 class BinaryPackageModelTest(TestCase):
144
145 def setUp(self):
146- self.sourcepackage = create_sourcepackage()
147- self.binarypackage = create_binarypackage(
148- sourcepackage=self.sourcepackage)
149+ self.sourcepackage = mommy.make('SourcePackage')
150+ self.binarypackage = mommy.make('BinaryPackage',
151+ sourcepackage=self.sourcepackage)
152
153- def test_creating_a_binarypackage(self):
154+ def test_creating_binarypackage(self):
155 binarypackage_in_database = BinaryPackage.objects.all()
156 self.assertEquals(len(binarypackage_in_database), 1)
157 only_binarypackage_in_database = binarypackage_in_database[0]
158 self.assertEquals(only_binarypackage_in_database, self.binarypackage)
159
160 self.assertEquals(only_binarypackage_in_database.name,
161- "awesome-binary")
162+ self.binarypackage.name)
163
164
165 class SourcePackageResourceTest(TastypieTestCase):
166
167 def setUp(self):
168 super(SourcePackageResourceTest, self).setUp('/api/v1')
169- create_sourcepackage()
170- self.sourcepackage_1 = SourcePackage.objects.get(
171- name='awesome-package')
172- self.detail_url = 'sourcepackage/{0}/'.format(self.sourcepackage_1.pk)
173+ self.sourcepackage = mommy.make('SourcePackage')
174+ self.detail_url = 'sourcepackage/{0}/'.format(self.sourcepackage.pk)
175+ self.post_sourcepackage_data = {
176+ 'name': 'ubuntu-ci',
177+ }
178
179 def test_get_sourcepackage_list_json(self):
180 obj = self.getResource('sourcepackage/')
181 self.assertEqual(obj['objects'][0], {
182- u'id': self.sourcepackage_1.pk,
183- u'name': u'awesome-package',
184+ u'id': self.sourcepackage.pk,
185+ u'name': unicode(self.sourcepackage.name),
186 u'resource_uri': u'/api/v1/sourcepackage/{0}/'.format(
187- self.sourcepackage_1.pk)
188+ self.sourcepackage.pk)
189 })
190
191 def test_get_sourcepackage_detail_json(self):
192 obj = self.getResource(self.detail_url)
193 # We use ``assertKeys`` here to just verify the keys, not all the data.
194 self.assertKeys(obj, ['id', 'name', 'resource_uri'])
195- self.assertEqual(obj['name'], 'awesome-package')
196+ self.assertEqual(obj['name'], self.sourcepackage.name)
197+
198+ def test_post_sourcepackage(self):
199+ # Check how many are there first.
200+ self.assertEqual(SourcePackage.objects.count(), 1)
201+ self.post(resource='sourcepackage/',
202+ params=self.post_sourcepackage_data)
203+ # Verify a new one has been added.
204+ self.assertEqual(SourcePackage.objects.count(), 2)
205+
206+ def test_patch_detail(self):
207+ # Grab the current data & modify it slightly.
208+ original_data = self.getResource(self.detail_url)
209+ new_data = original_data.copy()
210+ new_data['name'] = 'ci-ubuntu'
211+
212+ self.assertEqual(SourcePackage.objects.count(), 1)
213+ self.patch(resource=self.detail_url, params=new_data)
214+ # Make sure the count hasn't changed & we did an update.
215+ self.assertEqual(SourcePackage.objects.count(), 1)
216+ # Check for updated data.
217+ self.assertEqual(SourcePackage.objects.get(
218+ pk=self.sourcepackage.pk).name, new_data['name'])
219+
220+ def test_delete_sourcepackage_not_allowed(self):
221+ resp = self.delete(resource=self.detail_url)
222+ self.assertHttpMethodNotAllowed(resp)
223
224
225 class BinaryPackageResourceTest(TastypieTestCase):
226
227 def setUp(self):
228 super(BinaryPackageResourceTest, self).setUp('/api/v1')
229- create_sourcepackage()
230- self.sourcepackage_1 = SourcePackage.objects.get(
231- name='awesome-package')
232- create_binarypackage(sourcepackage=self.sourcepackage_1)
233- self.binarypackage_1 = BinaryPackage.objects.get(name='awesome-binary')
234- self.detail_url = 'binarypackage/{0}/'.format(self.binarypackage_1.pk)
235+ self.sourcepackage = mommy.make('SourcePackage')
236+ self.binarypackage = mommy.make('BinaryPackage',
237+ sourcepackage=self.sourcepackage)
238+ self.detail_url = 'binarypackage/{0}/'.format(self.binarypackage.pk)
239+ self.post_binarypackage_data = {
240+ 'name': 'ubuntu-ci',
241+ 'sourcepackage': '/api/v1/sourcepackage/{0}/'.format(
242+ self.sourcepackage.pk)
243+ }
244
245 def test_get_binarypackage_list_json(self):
246 obj = self.getResource('binarypackage/')
247 self.assertEqual(obj['objects'][0], {
248- u'id': self.binarypackage_1.pk,
249- u'name': u'awesome-binary',
250- u'seeded': False,
251+ u'id': self.binarypackage.pk,
252+ u'name': unicode(self.binarypackage.name),
253+ u'seeded': self.binarypackage.seeded,
254 u'sourcepackage': {
255- u'id': self.sourcepackage_1.pk,
256- u'name': u'awesome-package',
257+ u'id': self.sourcepackage.pk,
258+ u'name': unicode(self.sourcepackage.name),
259 u'resource_uri': u'/api/v1/sourcepackage/{0}/'.format(
260- self.sourcepackage_1.pk)},
261+ self.sourcepackage.pk)},
262 u'resource_uri': u'/api/v1/binarypackage/{0}/'.format(
263- self.binarypackage_1.pk)
264+ self.binarypackage.pk)
265 })
266
267 def test_get_binarypackage_detail_json(self):
268@@ -121,4 +138,30 @@
269 # We use ``assertKeys`` here to just verify the keys, not all the data.
270 self.assertKeys(obj, ['id', 'name', 'resource_uri', 'seeded',
271 'sourcepackage'])
272- self.assertEqual(obj['name'], 'awesome-binary')
273+ self.assertEqual(obj['name'], self.binarypackage.name)
274+
275+ def test_post_binarypackage(self):
276+ # Check how many are there first.
277+ self.assertEqual(BinaryPackage.objects.count(), 1)
278+ self.post(resource='binarypackage/',
279+ params=self.post_binarypackage_data)
280+ # Verify a new one has been added.
281+ self.assertEqual(BinaryPackage.objects.count(), 2)
282+
283+ def test_patch_detail(self):
284+ # Grab the current data & modify it slightly.
285+ original_data = self.getResource(self.detail_url)
286+ new_data = original_data.copy()
287+ new_data['name'] = 'ci-ubuntu'
288+
289+ self.assertEqual(BinaryPackage.objects.count(), 1)
290+ self.patch(resource=self.detail_url, params=new_data)
291+ # Make sure the count hasn't changed & we did an update.
292+ self.assertEqual(BinaryPackage.objects.count(), 1)
293+ # Check for updated data.
294+ self.assertEqual(BinaryPackage.objects.get(
295+ pk=self.binarypackage.pk).name, new_data['name'])
296+
297+ def test_delete_binarypackage_not_allowed(self):
298+ resp = self.delete(resource=self.detail_url)
299+ self.assertHttpMethodNotAllowed(resp)

Subscribers

People subscribed via source and target branches