Merge lp:~ursinha/uci-engine/ts-add-mp-support into lp:uci-engine
- ts-add-mp-support
- Merge into trunk
Proposed by
Ursula Junque
Status: | Merged |
---|---|
Approved by: | Ursula Junque |
Approved revision: | 494 |
Merged at revision: | 508 |
Proposed branch: | lp:~ursinha/uci-engine/ts-add-mp-support |
Merge into: | lp:uci-engine |
Diff against target: |
329 lines (+234/-15) 3 files modified
ticket_system/ticket/migrations/0002_uce0.py (+110/-0) ticket_system/ticket/models.py (+42/-2) ticket_system/ticket/tests/test_models.py (+82/-13) |
To merge this branch: | bzr merge lp:~ursinha/uci-engine/ts-add-mp-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andy Doan (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Chris Johnston (community) | Needs Information | ||
Review via email: mp+220275@code.launchpad.net |
Commit message
This branch adds Merge Proposals to the Ticket System.
Description of the change
This branch adds Merge Proposals to the Ticket System.
To post a comment you must log in.
Revision history for this message
Chris Johnston (cjohnston) : | # |
Revision history for this message
Ursula Junque (ursinha) : | # |
Revision history for this message
Chris Johnston (cjohnston) : | # |
review:
Needs Fixing
Revision history for this message
Chris Johnston (cjohnston) : | # |
review:
Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Needs Fixing
(continuous-integration)
Revision history for this message
Ursula Junque (ursinha) : | # |
Revision history for this message
Ursula Junque (ursinha) : | # |
Revision history for this message
Andy Doan (doanac) wrote : | # |
two largely bike-shedding comments. feel free to ignore.
Revision history for this message
Chris Johnston (cjohnston) : | # |
Revision history for this message
Ursula Junque (ursinha) : | # |
- 493. By Ursula Junque
-
Removing max_length from IntegerField
- 494. By Ursula Junque
-
merging trunk for the last time
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:494
http://
Executed test runs:
Click here to trigger a rebuild:
http://
review:
Approve
(continuous-integration)
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 | === added file 'ticket_system/ticket/migrations/0002_uce0.py' |
2 | --- ticket_system/ticket/migrations/0002_uce0.py 1970-01-01 00:00:00 +0000 |
3 | +++ ticket_system/ticket/migrations/0002_uce0.py 2014-05-26 08:30:26 +0000 |
4 | @@ -0,0 +1,110 @@ |
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 | + def forwards(self, orm): |
15 | + # Adding model 'MergeProposal' |
16 | + db.create_table('mergeproposal', ( |
17 | + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
18 | + ('project', self.gf('django.db.models.fields.CharField')(max_length=4096)), |
19 | + ('lp_url', self.gf('django.db.models.fields.CharField')(max_length=4096)), |
20 | + ('target_branch', self.gf('django.db.models.fields.CharField')(max_length=4096)), |
21 | + ('approved_revno', self.gf('django.db.models.fields.IntegerField')()), |
22 | + ('sourcepackage', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['project.SourcePackage'])), |
23 | + ('version', self.gf('django.db.models.fields.CharField')(max_length=4096)), |
24 | + )) |
25 | + db.send_create_signal(u'ticket', ['MergeProposal']) |
26 | + |
27 | + # Adding field 'SubTicket.merge_proposal' |
28 | + db.add_column('subticket', 'merge_proposal', |
29 | + self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['ticket.MergeProposal'], null=True, blank=True), |
30 | + keep_default=False) |
31 | + |
32 | + |
33 | + # Changing field 'SubTicket.source_package_upload' |
34 | + db.alter_column('subticket', 'source_package_upload_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ticket.SourcePackageUpload'], null=True)) |
35 | + |
36 | + def backwards(self, orm): |
37 | + # Deleting model 'MergeProposal' |
38 | + db.delete_table('mergeproposal') |
39 | + |
40 | + # Deleting field 'SubTicket.merge_proposal' |
41 | + db.delete_column('subticket', 'merge_proposal_id') |
42 | + |
43 | + |
44 | + # Changing field 'SubTicket.source_package_upload' |
45 | + db.alter_column('subticket', 'source_package_upload_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['ticket.SourcePackageUpload'])) |
46 | + |
47 | + models = { |
48 | + u'project.sourcepackage': { |
49 | + 'Meta': {'object_name': 'SourcePackage', 'db_table': "'sourcepackage'"}, |
50 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
51 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}) |
52 | + }, |
53 | + u'ticket.mergeproposal': { |
54 | + 'Meta': {'object_name': 'MergeProposal', 'db_table': "'mergeproposal'"}, |
55 | + 'approved_revno': ('django.db.models.fields.IntegerField', [], {}), |
56 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
57 | + 'lp_url': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
58 | + 'project': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
59 | + 'sourcepackage': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['project.SourcePackage']"}), |
60 | + 'target_branch': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
61 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) |
62 | + }, |
63 | + u'ticket.sourcepackageupload': { |
64 | + 'Meta': {'object_name': 'SourcePackageUpload', 'db_table': "'sourcepackageupload'"}, |
65 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
66 | + 'sourcepackage': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['project.SourcePackage']"}), |
67 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) |
68 | + }, |
69 | + u'ticket.subticket': { |
70 | + 'Meta': {'object_name': 'SubTicket', 'db_table': "'subticket'"}, |
71 | + 'assignee': ('django.db.models.fields.EmailField', [], {'max_length': '254'}), |
72 | + 'current_workflow_step': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '4096'}), |
73 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
74 | + 'merge_proposal': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['ticket.MergeProposal']", 'null': 'True', 'blank': 'True'}), |
75 | + 'source_package_upload': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['ticket.SourcePackageUpload']", 'null': 'True', 'blank': 'True'}), |
76 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '4096'}), |
77 | + 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ticket.Ticket']"}) |
78 | + }, |
79 | + u'ticket.subticketartifact': { |
80 | + 'Meta': {'object_name': 'SubTicketArtifact', 'db_table': "'subticket_artifact'"}, |
81 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
82 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
83 | + 'reference': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
84 | + 'subticket': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ticket.SubTicket']", 'null': 'True'}), |
85 | + 'type': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) |
86 | + }, |
87 | + u'ticket.ticket': { |
88 | + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket'"}, |
89 | + 'added_binaries': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'null': 'True', 'blank': 'True'}), |
90 | + 'base_image': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '4096'}), |
91 | + 'bug_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
92 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
93 | + 'current_workflow_step': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '4096'}), |
94 | + 'description': ('django.db.models.fields.TextField', [], {}), |
95 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
96 | + 'master_ppa': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '4096'}), |
97 | + 'owner': ('django.db.models.fields.EmailField', [], {'max_length': '254'}), |
98 | + 'removed_binaries': ('django.db.models.fields.CharField', [], {'max_length': '4096', 'null': 'True', 'blank': 'True'}), |
99 | + 'series': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '4096'}), |
100 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '4096'}), |
101 | + 'title': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
102 | + 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) |
103 | + }, |
104 | + u'ticket.ticketartifact': { |
105 | + 'Meta': {'object_name': 'TicketArtifact', 'db_table': "'ticket_artifact'"}, |
106 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
107 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
108 | + 'reference': ('django.db.models.fields.CharField', [], {'max_length': '4096'}), |
109 | + 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ticket.Ticket']", 'null': 'True'}), |
110 | + 'type': ('django.db.models.fields.CharField', [], {'max_length': '4096'}) |
111 | + } |
112 | + } |
113 | + |
114 | + complete_apps = ['ticket'] |
115 | \ No newline at end of file |
116 | |
117 | === modified file 'ticket_system/ticket/models.py' |
118 | --- ticket_system/ticket/models.py 2014-05-22 14:48:56 +0000 |
119 | +++ ticket_system/ticket/models.py 2014-05-26 08:30:26 +0000 |
120 | @@ -123,6 +123,28 @@ |
121 | return "{} {}".format(self.sourcepackage, self.version) |
122 | |
123 | |
124 | +class MergeProposal(models.Model): |
125 | + class Meta: |
126 | + db_table = 'mergeproposal' |
127 | + |
128 | + project = models.CharField(max_length=4096) |
129 | + lp_url = models.CharField(max_length=4096) |
130 | + target_branch = models.CharField(max_length=4096) |
131 | + approved_revno = models.IntegerField() |
132 | + # All branches submitted to ci-airline will result on a package, so |
133 | + # will have a debian packaging dir with the latest version. |
134 | + sourcepackage = models.ForeignKey(SourcePackage) |
135 | + version = models.CharField(max_length=4096) |
136 | + |
137 | + def __unicode__(self): |
138 | + return "{} {}".format(self.project, self.lp_url, self.sourcepackage, |
139 | + self.version) |
140 | + |
141 | + @property |
142 | + def proposed_branch(self): |
143 | + return "lp:{}".format(self.lp_url.split("/+merge")[0]) |
144 | + |
145 | + |
146 | class SubTicket(models.Model): |
147 | class Meta: |
148 | db_table = 'subticket' |
149 | @@ -135,10 +157,28 @@ |
150 | default=000) |
151 | ticket = models.ForeignKey(Ticket) |
152 | assignee = models.EmailField(max_length=254) |
153 | - source_package_upload = models.ForeignKey(SourcePackageUpload) |
154 | + source_package_upload = models.ForeignKey(SourcePackageUpload, null=True, |
155 | + blank=True, default=None) |
156 | + merge_proposal = models.ForeignKey(MergeProposal, null=True, blank=True, |
157 | + default=None) |
158 | + |
159 | + def save(self, *args, **kwargs): |
160 | + if self.source_package_upload and self.merge_proposal: |
161 | + raise IntegrityError("Subtickets only accept a source package " |
162 | + "upload or a merge proposal at a time, you " |
163 | + "provided both.") |
164 | + elif not self.source_package_upload and not self.merge_proposal: |
165 | + raise IntegrityError("A subticket requires at least one source " |
166 | + "package upload or one merge proposal, you " |
167 | + "provided neither.") |
168 | + super(SubTicket, self).save(*args, **kwargs) |
169 | |
170 | def __unicode__(self): |
171 | - return "{} {}".format(self.ticket, self.source_package_upload) |
172 | + if self.source_package_upload: |
173 | + target = self.source_package_upload |
174 | + else: |
175 | + target = self.merge_proposal |
176 | + return "{} {}".format(self.ticket, target) |
177 | |
178 | |
179 | class ArtifactBase(models.Model): |
180 | |
181 | === modified file 'ticket_system/ticket/tests/test_models.py' |
182 | --- ticket_system/ticket/tests/test_models.py 2014-05-16 19:16:57 +0000 |
183 | +++ ticket_system/ticket/tests/test_models.py 2014-05-26 08:30:26 +0000 |
184 | @@ -19,9 +19,10 @@ |
185 | from django.test import TestCase |
186 | from project.models import SourcePackage |
187 | from ticket.models import (TicketArtifact, SubTicketArtifact, SubTicket, |
188 | - SourcePackageUpload, SubTicketWorkflowStep, |
189 | - SubTicketWorkflowStepStatus, Ticket, |
190 | - TicketWorkflowStep, TicketWorkflowStepStatus) |
191 | + SourcePackageUpload, MergeProposal, |
192 | + SubTicketWorkflowStep, SubTicketWorkflowStepStatus, |
193 | + Ticket, TicketWorkflowStep, |
194 | + TicketWorkflowStepStatus) |
195 | |
196 | |
197 | def create_sourcepackage(name='my-package'): |
198 | @@ -39,6 +40,21 @@ |
199 | return spu |
200 | |
201 | |
202 | +def create_merge_proposal(project='my-project', sourcepackage='my-package', |
203 | + lp_url='~foobar/my-project/my-branch/+merge/123456', |
204 | + target_branch='lp:~foobar/my-project/trunk', |
205 | + approved_revno=100, version='1.1'): |
206 | + merge_proposal = MergeProposal() |
207 | + merge_proposal.project = project |
208 | + merge_proposal.sourcepackage = sourcepackage |
209 | + merge_proposal.lp_url = lp_url |
210 | + merge_proposal.version = version |
211 | + merge_proposal.target_branch = target_branch |
212 | + merge_proposal.approved_revno = approved_revno |
213 | + merge_proposal.save() |
214 | + return merge_proposal |
215 | + |
216 | + |
217 | def create_ticket(title="This is my ticket", |
218 | description="this is my ticket description", |
219 | bug_id='12345', owner='test@example.com', |
220 | @@ -65,13 +81,15 @@ |
221 | def create_subticket(current_workflow_step=SubTicketWorkflowStep.PKG_BUILDING, |
222 | ticket=None, status=( |
223 | SubTicketWorkflowStepStatus.PKG_BUILDING_INPROGRESS), |
224 | - assignee='test@example.com', source_package_upload=None): |
225 | + assignee='test@example.com', source_package_upload=None, |
226 | + merge_proposal=None): |
227 | subticket = SubTicket() |
228 | subticket.current_workflow_step = current_workflow_step |
229 | subticket.status = status |
230 | subticket.ticket = ticket |
231 | subticket.assignee = assignee |
232 | subticket.source_package_upload = source_package_upload |
233 | + subticket.merge_proposal = merge_proposal |
234 | subticket.save() |
235 | return subticket |
236 | |
237 | @@ -100,13 +118,15 @@ |
238 | self.sourcepackage = create_sourcepackage() |
239 | self.spu = create_sourcepackageupload( |
240 | sourcepackage=self.sourcepackage) |
241 | + self.mp = create_merge_proposal(sourcepackage=self.sourcepackage) |
242 | self.ticket = create_ticket(owner='test@example.com') |
243 | - self.subticket = create_subticket(ticket=self.ticket, |
244 | - assignee='test@example.com', |
245 | - source_package_upload=self.spu) |
246 | |
247 | def test_creating_an_artifact_subticket(self): |
248 | - self.artifact_1 = create_subticketartifact(subticket=self.subticket) |
249 | + subticket = create_subticket(ticket=self.ticket, |
250 | + assignee='test@example.com', |
251 | + source_package_upload=self.spu) |
252 | + |
253 | + self.artifact_1 = create_subticketartifact(subticket=subticket) |
254 | artifact_in_database = SubTicketArtifact.objects.exclude( |
255 | subticket=None) |
256 | self.assertEquals(len(artifact_in_database), 1) |
257 | @@ -135,11 +155,46 @@ |
258 | self.assertEquals(only_ticket_in_database.added_binaries, "foo,bar") |
259 | self.assertEquals(only_ticket_in_database.removed_binaries, "baz") |
260 | |
261 | - def test_creating_a_subticket(self): |
262 | - subticket_in_database = SubTicket.objects.all() |
263 | - self.assertEquals(len(subticket_in_database), 1) |
264 | - only_subticket_in_database = subticket_in_database[0] |
265 | - self.assertEquals(only_subticket_in_database, self.subticket) |
266 | + def test_creating_a_subticket_with_spu(self): |
267 | + subticket = create_subticket(ticket=self.ticket, |
268 | + assignee='test@example.com', |
269 | + source_package_upload=self.spu) |
270 | + subticket_in_database = SubTicket.objects.all() |
271 | + self.assertEquals(len(subticket_in_database), 1) |
272 | + only_subticket_in_database = subticket_in_database[0] |
273 | + self.assertEquals(only_subticket_in_database, subticket) |
274 | + |
275 | + self.assertEquals(only_subticket_in_database.assignee, |
276 | + "test@example.com") |
277 | + |
278 | + def test_creating_a_subticket_with_spu_and_mp(self): |
279 | + with self.assertRaises(IntegrityError) as cm: |
280 | + create_subticket(ticket=self.ticket, assignee='test@example.com', |
281 | + source_package_upload=self.spu, |
282 | + merge_proposal=self.mp) |
283 | + self.assertEquals(cm.exception.args[0], "Subtickets only accept a " |
284 | + "source package upload or a merge proposal at a " |
285 | + "time, you provided both.") |
286 | + subticket_in_database = SubTicket.objects.all() |
287 | + self.assertEquals(len(subticket_in_database), 0) |
288 | + |
289 | + def test_creating_a_subticket_with_no_spu_or_mp(self): |
290 | + with self.assertRaises(IntegrityError) as cm: |
291 | + create_subticket(ticket=self.ticket, assignee='test@example.com') |
292 | + self.assertEquals(cm.exception.args[0], "A subticket requires at " |
293 | + "least one source package upload or one merge " |
294 | + "proposal, you provided neither.") |
295 | + subticket_in_database = SubTicket.objects.all() |
296 | + self.assertEquals(len(subticket_in_database), 0) |
297 | + |
298 | + def test_creating_a_subticket_with_mp(self): |
299 | + subticket = create_subticket(ticket=self.ticket, |
300 | + assignee='test@example.com', |
301 | + merge_proposal=self.mp) |
302 | + subticket_in_database = SubTicket.objects.all() |
303 | + self.assertEquals(len(subticket_in_database), 1) |
304 | + only_subticket_in_database = subticket_in_database[0] |
305 | + self.assertEquals(only_subticket_in_database, subticket) |
306 | |
307 | self.assertEquals(only_subticket_in_database.assignee, |
308 | "test@example.com") |
309 | @@ -153,6 +208,20 @@ |
310 | self.assertEquals(only_spu_in_database.sourcepackage.name, |
311 | "my-package") |
312 | |
313 | + def test_creating_a_mergeproposal(self): |
314 | + mp_in_database = MergeProposal.objects.all() |
315 | + self.assertEquals(len(mp_in_database), 1) |
316 | + only_mp_in_database = mp_in_database[0] |
317 | + self.assertEquals(only_mp_in_database, self.mp) |
318 | + |
319 | + self.assertEquals(only_mp_in_database.project, "my-project") |
320 | + self.assertEquals(only_mp_in_database.lp_url, |
321 | + "~foobar/my-project/my-branch/+merge/123456") |
322 | + self.assertEquals(only_mp_in_database.target_branch, |
323 | + "lp:~foobar/my-project/trunk") |
324 | + self.assertEquals(only_mp_in_database.proposed_branch, |
325 | + "lp:~foobar/my-project/my-branch") |
326 | + |
327 | def test_added_binary_list_invalid(self): |
328 | added_binaries = "foo bar" |
329 | self.assertRaises(IntegrityError, create_ticket, |
FAILED: Continuous integration, rev:492 /code.launchpad .net/~ursinha/ uci-engine/ ts-add- mp-support/ +merge/ 220275/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// s-jenkins. ubuntu- ci:8080/ job/uci- engine- ci/694/
Executed test runs:
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/uci- engine- ci/694/ rebuild
http://