Merge lp:~cjohnston/ubuntu-ci-services-itself/ts-next into lp:ubuntu-ci-services-itself

Proposed by Chris Johnston
Status: Merged
Approved by: Chris Johnston
Approved revision: 104
Merged at revision: 112
Proposed branch: lp:~cjohnston/ubuntu-ci-services-itself/ts-next
Merge into: lp:ubuntu-ci-services-itself
Diff against target: 200 lines (+153/-3)
4 files modified
docs/components/ticket-system.rst (+4/-0)
ticket_system/ticket/api.py (+28/-0)
ticket_system/ticket/tests/test_full_read_api.py (+117/-0)
ticket_system/ticket_system/urls.py (+4/-3)
To merge this branch: bzr merge lp:~cjohnston/ubuntu-ci-services-itself/ts-next
Reviewer Review Type Date Requested Status
Andy Doan (community) Approve
Chris Johnston (community) Needs Resubmitting
Francis Ginther Approve
Review via email: mp+201854@code.launchpad.net

Commit message

Add next/ API for the lander to get tickets from the TS

Description of the change

Adds a next/ api for the lander to either get the current ticket in progress, or if there are no in progress tickets, the next ticket in the queue.

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

Approve from the lander (api consumer) perspective.

review: Approve
Revision history for this message
Andy Doan (doanac) wrote :

On 01/15/2014 03:14 PM, Chris Johnston wrote:
> + def get_object_list(self, request):
> + exclude = ['000', '1000']
> + in_progress = ['200', '300', '400', '500']

aren't there constants in models.py we can use instead?

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

How do you suggest using them?

Revision history for this message
Andy Doan (doanac) wrote :

On 01/16/2014 07:02 AM, Chris Johnston wrote:
> How do you suggest using them?

This is one way, and I'm sure 2 other people would have 2 more ways, but:

  exclude = [
      TicketWorkflowStepStatus.NEW.value,
      TicketWorkflowStepStatus.COMPLETE.value,
  ]

104. By Chris Johnston

Update per review

Revision history for this message
Chris Johnston (cjohnston) :
review: Needs Resubmitting
Revision history for this message
Andy Doan (doanac) :
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 2014-01-15 02:23:07 +0000
3+++ docs/components/ticket-system.rst 2014-01-16 15:41:47 +0000
4@@ -171,6 +171,10 @@
5
6 Show the current in progress, or the first pending ticket.
7
8+::
9+
10+ curl --dump-header - http://162.213.34.2:8000/api/v1/next/
11+
12 get_ticket_status
13 ~~~~~~~~~~~~~~~~~
14
15
16=== modified file 'ticket_system/ticket/api.py'
17--- ticket_system/ticket/api.py 2014-01-15 00:31:20 +0000
18+++ ticket_system/ticket/api.py 2014-01-16 15:41:47 +0000
19@@ -161,3 +161,31 @@
20 filtering = {
21 "current_workflow_step": ALL,
22 }
23+
24+
25+class NextTicketResource(TicketTranslatedResource):
26+ subticket = fields.ToManyField(FullSubTicketResource, 'subticket_set',
27+ full=True)
28+
29+ class Meta:
30+ queryset = Ticket.objects.all()
31+ allowed_methods = ['get']
32+ resource_name = 'next'
33+
34+ def get_object_list(self, request):
35+ exclude = [TicketWorkflowStep.NEW.value,
36+ TicketWorkflowStep.COMPLETED.value]
37+ in_progress = [TicketWorkflowStep.PKG_BUILDING.value,
38+ TicketWorkflowStep.IMAGE_BUILDING.value,
39+ TicketWorkflowStep.IMAGE_TESTING.value,
40+ TicketWorkflowStep.PKG_PUBLISHING.value]
41+ qs = super(NextTicketResource, self).get_object_list(request).exclude(
42+ current_workflow_step__in=exclude).order_by('id')[:1]
43+ process = Ticket.objects.exclude(
44+ current_workflow_step__in=exclude,
45+ ).filter(current_workflow_step__in=in_progress)
46+ if process:
47+ qs = process
48+ else:
49+ qs = qs
50+ return qs
51
52=== modified file 'ticket_system/ticket/tests/test_full_read_api.py'
53--- ticket_system/ticket/tests/test_full_read_api.py 2014-01-09 21:06:18 +0000
54+++ ticket_system/ticket/tests/test_full_read_api.py 2014-01-16 15:41:47 +0000
55@@ -123,3 +123,120 @@
56 u'resource_uri': u'/api/v1/fullsubticket/{0}/'.format(
57 self.subticket.pk),
58 })
59+
60+
61+class GetNextTicketTest(TastypieTestCase):
62+ """
63+ Test that /next/ returns the current inprogress ticket, or the next
64+ 'queued' ticket.
65+ """
66+ def setUp(self):
67+ super(GetNextTicketTest, self).setUp('/api/v1')
68+ self.ticket_1 = mommy.make(
69+ 'Ticket', current_workflow_step=int(TicketWorkflowStep.NEW))
70+ self.ticket_2 = mommy.make(
71+ 'Ticket', current_workflow_step=int(TicketWorkflowStep.QUEUED))
72+ self.ticket_3 = mommy.make(
73+ 'Ticket', current_workflow_step=int(TicketWorkflowStep.QUEUED))
74+ self.ticket_4 = mommy.make(
75+ 'Ticket', current_workflow_step=int(TicketWorkflowStep.COMPLETED))
76+ self.sourcepackage = mommy.make('SourcePackage')
77+ self.spu = mommy.make('SourcePackageUpload',
78+ sourcepackage=self.sourcepackage)
79+ self.subticket_1 = mommy.make('SubTicket', ticket=self.ticket_1,
80+ source_package_upload=self.spu)
81+ self.artifact_1 = mommy.make('Artifact', subticket=self.subticket_1)
82+ self.subticket_2 = mommy.make('SubTicket', ticket=self.ticket_2,
83+ source_package_upload=self.spu)
84+ self.artifact_2 = mommy.make('Artifact', subticket=self.subticket_2)
85+ self.subticket_3 = mommy.make('SubTicket', ticket=self.ticket_3,
86+ source_package_upload=self.spu)
87+ self.artifact_3 = mommy.make('Artifact', subticket=self.subticket_3)
88+ self.subticket_4 = mommy.make('SubTicket', ticket=self.ticket_4,
89+ source_package_upload=self.spu)
90+ self.artifact_4 = mommy.make('Artifact', subticket=self.subticket_4)
91+
92+ def test_queued_ticket_next(self):
93+ obj = self.getResource('next/')
94+ self.assertEqual(len(obj['objects']), 1)
95+ self.assertEqual(obj['objects'][0][u'resource_uri'],
96+ u'/api/v1/next/{0}/'.format(
97+ self.ticket_2.pk))
98+ self.assertEqual(
99+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
100+ self.ticket_2.current_workflow_step, TicketWorkflowStep))
101+
102+ def test_pkg_building_ticket_next(self):
103+ self.ticket_3.current_workflow_step = int(
104+ TicketWorkflowStep.PKG_BUILDING)
105+ self.ticket_3.save()
106+ obj = self.getResource('next/')
107+ self.assertEqual(len(obj['objects']), 1)
108+ self.assertEqual(obj['objects'][0][u'resource_uri'],
109+ u'/api/v1/next/{0}/'.format(
110+ self.ticket_3.pk))
111+ self.assertEqual(
112+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
113+ self.ticket_3.current_workflow_step, TicketWorkflowStep))
114+
115+ def test_image_building_ticket_next(self):
116+ self.ticket_3.current_workflow_step = int(
117+ TicketWorkflowStep.IMAGE_BUILDING)
118+ self.ticket_3.save()
119+ obj = self.getResource('next/')
120+ self.assertEqual(len(obj['objects']), 1)
121+ self.assertEqual(obj['objects'][0][u'resource_uri'],
122+ u'/api/v1/next/{0}/'.format(
123+ self.ticket_3.pk))
124+ self.assertEqual(
125+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
126+ self.ticket_3.current_workflow_step, TicketWorkflowStep))
127+
128+ def test_image_testing_ticket_next(self):
129+ self.ticket_3.current_workflow_step = int(
130+ TicketWorkflowStep.IMAGE_TESTING)
131+ self.ticket_3.save()
132+ obj = self.getResource('next/')
133+ self.assertEqual(len(obj['objects']), 1)
134+ self.assertEqual(obj['objects'][0][u'resource_uri'],
135+ u'/api/v1/next/{0}/'.format(
136+ self.ticket_3.pk))
137+ self.assertEqual(
138+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
139+ self.ticket_3.current_workflow_step, TicketWorkflowStep))
140+
141+ def test_pkg_publishing_ticket_next(self):
142+ self.ticket_3.current_workflow_step = int(
143+ TicketWorkflowStep.PKG_PUBLISHING)
144+ self.ticket_3.save()
145+ obj = self.getResource('next/')
146+ self.assertEqual(len(obj['objects']), 1)
147+ self.assertEqual(obj['objects'][0][u'resource_uri'],
148+ u'/api/v1/next/{0}/'.format(
149+ self.ticket_3.pk))
150+ self.assertEqual(
151+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
152+ self.ticket_3.current_workflow_step, TicketWorkflowStep))
153+
154+ def test_ticket_complete_next_new_ticket_next(self):
155+ self.ticket_3.current_workflow_step = int(
156+ TicketWorkflowStep.COMPLETED)
157+ self.ticket_3.save()
158+ obj = self.getResource('next/')
159+ self.assertEqual(len(obj['objects']), 1)
160+ self.assertEqual(obj['objects'][0][u'resource_uri'],
161+ u'/api/v1/next/{0}/'.format(
162+ self.ticket_2.pk))
163+ self.assertEqual(
164+ obj['objects'][0][u'current_workflow_step'], get_enum_title(
165+ self.ticket_2.current_workflow_step, TicketWorkflowStep))
166+
167+ def test_no_queued_or_in_progress_ticket_next(self):
168+ self.ticket_2.current_workflow_step = int(
169+ TicketWorkflowStep.NEW)
170+ self.ticket_2.save()
171+ self.ticket_3.current_workflow_step = int(
172+ TicketWorkflowStep.NEW)
173+ self.ticket_3.save()
174+ obj = self.getResource('next/')
175+ self.assertEqual(len(obj['objects']), 0)
176
177=== modified file 'ticket_system/ticket_system/urls.py'
178--- ticket_system/ticket_system/urls.py 2014-01-15 00:16:52 +0000
179+++ ticket_system/ticket_system/urls.py 2014-01-16 15:41:47 +0000
180@@ -21,9 +21,9 @@
181 from ticket.api import (TicketResource, SubTicketResource, ArtifactResource,
182 SourcePackageUploadResource, FullSubTicketResource,
183 FullTicketResource, FullArtifactResource,
184- SubTicketUpdateStatusResource,
185- SubTicketStatusResource,
186- TicketStatusResource, TicketUpdateStatusResource)
187+ TicketStatusResource, TicketUpdateStatusResource,
188+ SubTicketUpdateStatusResource, NextTicketResource,
189+ SubTicketStatusResource)
190
191 admin.autodiscover()
192 v1_api = Api(api_name='v1')
193@@ -41,6 +41,7 @@
194 v1_api.register(SubTicketStatusResource())
195 v1_api.register(TicketUpdateStatusResource())
196 v1_api.register(TicketStatusResource())
197+v1_api.register(NextTicketResource())
198
199 urlpatterns = patterns(
200 '',

Subscribers

People subscribed via source and target branches