Merge lp:~cjwatson/launchpad/snap-auto-build-ui into lp:launchpad
- snap-auto-build-ui
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18129 |
Proposed branch: | lp:~cjwatson/launchpad/snap-auto-build-ui |
Merge into: | lp:launchpad |
Prerequisite: | lp:~cjwatson/launchpad/snap-auto-build-archive-widget |
Diff against target: |
797 lines (+426/-43) 10 files modified
lib/lp/snappy/browser/snap.py (+58/-5) lib/lp/snappy/browser/tests/test_snap.py (+77/-1) lib/lp/snappy/configure.zcml (+2/-0) lib/lp/snappy/help/snap-build-frequency.html (+42/-0) lib/lp/snappy/javascript/snap.edit.js (+25/-6) lib/lp/snappy/javascript/tests/test_snap.edit.html (+90/-1) lib/lp/snappy/javascript/tests/test_snap.edit.js (+35/-2) lib/lp/snappy/templates/snap-edit.pt (+36/-18) lib/lp/snappy/templates/snap-index.pt (+25/-0) lib/lp/snappy/templates/snap-new.pt (+36/-10) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/snap-auto-build-ui |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Approve | ||
Launchpad code reviewers | Pending | ||
Review via email: mp+297962@code.launchpad.net |
Commit message
Add UI for auto-building snap packages.
Description of the change
Add UI for auto-building snap packages. It's a little basic and could probably use more JS niceties in a few places, but it's functional.
To post a comment you must log in.
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/snappy/browser/snap.py' | |||
2 | --- lib/lp/snappy/browser/snap.py 2016-07-05 10:20:51 +0000 | |||
3 | +++ lib/lp/snappy/browser/snap.py 2016-07-12 13:40:07 +0000 | |||
4 | @@ -179,6 +179,13 @@ | |||
5 | 179 | self.context, field, format_link(self.context.owner), | 179 | self.context, field, format_link(self.context.owner), |
6 | 180 | header='Change owner', step_title='Select a new owner') | 180 | header='Change owner', step_title='Select a new owner') |
7 | 181 | 181 | ||
8 | 182 | @property | ||
9 | 183 | def build_frequency(self): | ||
10 | 184 | if self.context.auto_build: | ||
11 | 185 | return 'Built automatically' | ||
12 | 186 | else: | ||
13 | 187 | return 'Built on request' | ||
14 | 188 | |||
15 | 182 | 189 | ||
16 | 183 | def builds_for_snap(snap): | 190 | def builds_for_snap(snap): |
17 | 184 | """A list of interesting builds. | 191 | """A list of interesting builds. |
18 | @@ -303,6 +310,7 @@ | |||
19 | 303 | 'name', | 310 | 'name', |
20 | 304 | 'private', | 311 | 'private', |
21 | 305 | 'require_virtualized', | 312 | 'require_virtualized', |
22 | 313 | 'auto_build', | ||
23 | 306 | 'store_upload', | 314 | 'store_upload', |
24 | 307 | ]) | 315 | ]) |
25 | 308 | store_distro_series = Choice( | 316 | store_distro_series = Choice( |
26 | @@ -315,8 +323,13 @@ | |||
27 | 315 | branch = copy_field(ISnap['branch'], required=True) | 323 | branch = copy_field(ISnap['branch'], required=True) |
28 | 316 | git_ref = copy_field(ISnap['git_ref'], required=True) | 324 | git_ref = copy_field(ISnap['git_ref'], required=True) |
29 | 317 | 325 | ||
32 | 318 | # These are only required if store_upload is True. Later validation | 326 | # These are only required if auto_build is True. Later validation takes |
33 | 319 | # takes care of adjusting the required attribute. | 327 | # care of adjusting the required attribute. |
34 | 328 | auto_build_archive = copy_field(ISnap['auto_build_archive'], required=True) | ||
35 | 329 | auto_build_pocket = copy_field(ISnap['auto_build_pocket'], required=True) | ||
36 | 330 | |||
37 | 331 | # This is only required if store_upload is True. Later validation takes | ||
38 | 332 | # care of adjusting the required attribute. | ||
39 | 320 | store_name = copy_field(ISnap['store_name'], required=True) | 333 | store_name = copy_field(ISnap['store_name'], required=True) |
40 | 321 | 334 | ||
41 | 322 | 335 | ||
42 | @@ -350,10 +363,14 @@ | |||
43 | 350 | 'owner', | 363 | 'owner', |
44 | 351 | 'name', | 364 | 'name', |
45 | 352 | 'store_distro_series', | 365 | 'store_distro_series', |
46 | 366 | 'auto_build', | ||
47 | 367 | 'auto_build_archive', | ||
48 | 368 | 'auto_build_pocket', | ||
49 | 353 | 'store_upload', | 369 | 'store_upload', |
50 | 354 | 'store_name', | 370 | 'store_name', |
51 | 355 | ] | 371 | ] |
52 | 356 | custom_widget('store_distro_series', LaunchpadRadioWidget) | 372 | custom_widget('store_distro_series', LaunchpadRadioWidget) |
53 | 373 | custom_widget('auto_build_archive', SnapArchiveWidget) | ||
54 | 357 | 374 | ||
55 | 358 | def initialize(self): | 375 | def initialize(self): |
56 | 359 | """See `LaunchpadView`.""" | 376 | """See `LaunchpadView`.""" |
57 | @@ -417,6 +434,8 @@ | |||
58 | 417 | 'processors': [ | 434 | 'processors': [ |
59 | 418 | p for p in getUtility(IProcessorSet).getAll() | 435 | p for p in getUtility(IProcessorSet).getAll() |
60 | 419 | if p.build_by_default], | 436 | if p.build_by_default], |
61 | 437 | 'auto_build_archive': series.main_archive, | ||
62 | 438 | 'auto_build_pocket': PackagePublishingPocket.UPDATES, | ||
63 | 420 | } | 439 | } |
64 | 421 | 440 | ||
65 | 422 | @property | 441 | @property |
66 | @@ -425,6 +444,13 @@ | |||
67 | 425 | 444 | ||
68 | 426 | def validate_widgets(self, data, names=None): | 445 | def validate_widgets(self, data, names=None): |
69 | 427 | """See `LaunchpadFormView`.""" | 446 | """See `LaunchpadFormView`.""" |
70 | 447 | if self.widgets.get('auto_build') is not None: | ||
71 | 448 | # Set widgets as required or optional depending on the | ||
72 | 449 | # auto_build field. | ||
73 | 450 | super(SnapAddView, self).validate_widgets(data, ['auto_build']) | ||
74 | 451 | auto_build = data.get('auto_build', False) | ||
75 | 452 | self.widgets['auto_build_archive'].context.required = auto_build | ||
76 | 453 | self.widgets['auto_build_pocket'].context.required = auto_build | ||
77 | 428 | if self.widgets.get('store_upload') is not None: | 454 | if self.widgets.get('store_upload') is not None: |
78 | 429 | # Set widgets as required or optional depending on the | 455 | # Set widgets as required or optional depending on the |
79 | 430 | # store_upload field. | 456 | # store_upload field. |
80 | @@ -441,9 +467,15 @@ | |||
81 | 441 | kwargs = {'branch': self.context} | 467 | kwargs = {'branch': self.context} |
82 | 442 | private = not getUtility( | 468 | private = not getUtility( |
83 | 443 | ISnapSet).isValidPrivacy(False, data['owner'], **kwargs) | 469 | ISnapSet).isValidPrivacy(False, data['owner'], **kwargs) |
84 | 470 | if not data.get('auto_build', False): | ||
85 | 471 | data['auto_build_archive'] = None | ||
86 | 472 | data['auto_build_pocket'] = None | ||
87 | 444 | snap = getUtility(ISnapSet).new( | 473 | snap = getUtility(ISnapSet).new( |
88 | 445 | self.user, data['owner'], | 474 | self.user, data['owner'], |
89 | 446 | data['store_distro_series'].distro_series, data['name'], | 475 | data['store_distro_series'].distro_series, data['name'], |
90 | 476 | auto_build=data['auto_build'], | ||
91 | 477 | auto_build_archive=data['auto_build_archive'], | ||
92 | 478 | auto_build_pocket=data['auto_build_pocket'], | ||
93 | 447 | private=private, store_upload=data['store_upload'], | 479 | private=private, store_upload=data['store_upload'], |
94 | 448 | store_series=data['store_distro_series'].snappy_series, | 480 | store_series=data['store_distro_series'].snappy_series, |
95 | 449 | store_name=data['store_name'], processors=data['processors'], | 481 | store_name=data['store_name'], processors=data['processors'], |
96 | @@ -502,6 +534,14 @@ | |||
97 | 502 | self.widgets['git_ref'].context.required = True | 534 | self.widgets['git_ref'].context.required = True |
98 | 503 | else: | 535 | else: |
99 | 504 | raise AssertionError("Unknown branch type %s" % vcs) | 536 | raise AssertionError("Unknown branch type %s" % vcs) |
100 | 537 | if self.widgets.get('auto_build') is not None: | ||
101 | 538 | # Set widgets as required or optional depending on the | ||
102 | 539 | # auto_build field. | ||
103 | 540 | super(BaseSnapEditView, self).validate_widgets( | ||
104 | 541 | data, ['auto_build']) | ||
105 | 542 | auto_build = data.get('auto_build', False) | ||
106 | 543 | self.widgets['auto_build_archive'].context.required = auto_build | ||
107 | 544 | self.widgets['auto_build_pocket'].context.required = auto_build | ||
108 | 505 | if self.widgets.get('store_upload') is not None: | 545 | if self.widgets.get('store_upload') is not None: |
109 | 506 | # Set widgets as required or optional depending on the | 546 | # Set widgets as required or optional depending on the |
110 | 507 | # store_upload field. | 547 | # store_upload field. |
111 | @@ -538,9 +578,15 @@ | |||
112 | 538 | self.context.setProcessors( | 578 | self.context.setProcessors( |
113 | 539 | new_processors, check_permissions=True, user=self.user) | 579 | new_processors, check_permissions=True, user=self.user) |
114 | 540 | del data['processors'] | 580 | del data['processors'] |
115 | 581 | if not data.get('auto_build', False): | ||
116 | 582 | if 'auto_build_archive' in data: | ||
117 | 583 | del data['auto_build_archive'] | ||
118 | 584 | if 'auto_build_pocket' in data: | ||
119 | 585 | del data['auto_build_pocket'] | ||
120 | 541 | store_upload = data.get('store_upload', False) | 586 | store_upload = data.get('store_upload', False) |
121 | 542 | if not store_upload: | 587 | if not store_upload: |
123 | 543 | data['store_name'] = None | 588 | if 'store_name' in data: |
124 | 589 | del data['store_name'] | ||
125 | 544 | need_store_reauth = self._needStoreReauth(data) | 590 | need_store_reauth = self._needStoreReauth(data) |
126 | 545 | self.updateContextFromData(data) | 591 | self.updateContextFromData(data) |
127 | 546 | if need_store_reauth: | 592 | if need_store_reauth: |
128 | @@ -592,15 +638,19 @@ | |||
129 | 592 | 'owner', | 638 | 'owner', |
130 | 593 | 'name', | 639 | 'name', |
131 | 594 | 'store_distro_series', | 640 | 'store_distro_series', |
132 | 595 | 'store_upload', | ||
133 | 596 | 'store_name', | ||
134 | 597 | 'vcs', | 641 | 'vcs', |
135 | 598 | 'branch', | 642 | 'branch', |
136 | 599 | 'git_ref', | 643 | 'git_ref', |
137 | 644 | 'auto_build', | ||
138 | 645 | 'auto_build_archive', | ||
139 | 646 | 'auto_build_pocket', | ||
140 | 647 | 'store_upload', | ||
141 | 648 | 'store_name', | ||
142 | 600 | ] | 649 | ] |
143 | 601 | custom_widget('store_distro_series', LaunchpadRadioWidget) | 650 | custom_widget('store_distro_series', LaunchpadRadioWidget) |
144 | 602 | custom_widget('vcs', LaunchpadRadioWidget) | 651 | custom_widget('vcs', LaunchpadRadioWidget) |
145 | 603 | custom_widget('git_ref', GitRefWidget) | 652 | custom_widget('git_ref', GitRefWidget) |
146 | 653 | custom_widget('auto_build_archive', SnapArchiveWidget) | ||
147 | 604 | 654 | ||
148 | 605 | def setUpFields(self): | 655 | def setUpFields(self): |
149 | 606 | """See `LaunchpadFormView`.""" | 656 | """See `LaunchpadFormView`.""" |
150 | @@ -624,6 +674,9 @@ | |||
151 | 624 | initial_values['vcs'] = VCSType.GIT | 674 | initial_values['vcs'] = VCSType.GIT |
152 | 625 | else: | 675 | else: |
153 | 626 | initial_values['vcs'] = VCSType.BZR | 676 | initial_values['vcs'] = VCSType.BZR |
154 | 677 | if self.context.auto_build_pocket is None: | ||
155 | 678 | initial_values['auto_build_pocket'] = ( | ||
156 | 679 | PackagePublishingPocket.UPDATES) | ||
157 | 627 | return initial_values | 680 | return initial_values |
158 | 628 | 681 | ||
159 | 629 | def validate(self, data): | 682 | def validate(self, data): |
160 | 630 | 683 | ||
161 | === modified file 'lib/lp/snappy/browser/tests/test_snap.py' | |||
162 | --- lib/lp/snappy/browser/tests/test_snap.py 2016-07-05 10:20:51 +0000 | |||
163 | +++ lib/lp/snappy/browser/tests/test_snap.py 2016-07-12 13:40:07 +0000 | |||
164 | @@ -42,6 +42,7 @@ | |||
165 | 42 | from lp.buildmaster.enums import BuildStatus | 42 | from lp.buildmaster.enums import BuildStatus |
166 | 43 | from lp.buildmaster.interfaces.processor import IProcessorSet | 43 | from lp.buildmaster.interfaces.processor import IProcessorSet |
167 | 44 | from lp.code.errors import GitRepositoryScanFault | 44 | from lp.code.errors import GitRepositoryScanFault |
168 | 45 | from lp.code.interfaces.githosting import IGitHostingClient | ||
169 | 45 | from lp.registry.enums import PersonVisibility | 46 | from lp.registry.enums import PersonVisibility |
170 | 46 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 47 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
171 | 47 | from lp.registry.interfaces.series import SeriesStatus | 48 | from lp.registry.interfaces.series import SeriesStatus |
172 | @@ -72,6 +73,7 @@ | |||
173 | 72 | time_counter, | 73 | time_counter, |
174 | 73 | ) | 74 | ) |
175 | 74 | from lp.testing.fakemethod import FakeMethod | 75 | from lp.testing.fakemethod import FakeMethod |
176 | 76 | from lp.testing.fixture import ZopeUtilityFixture | ||
177 | 75 | from lp.testing.layers import ( | 77 | from lp.testing.layers import ( |
178 | 76 | DatabaseFunctionalLayer, | 78 | DatabaseFunctionalLayer, |
179 | 77 | LaunchpadFunctionalLayer, | 79 | LaunchpadFunctionalLayer, |
180 | @@ -220,11 +222,23 @@ | |||
181 | 220 | "Source:\n%s\nEdit snap package" % source_display, | 222 | "Source:\n%s\nEdit snap package" % source_display, |
182 | 221 | MatchesTagText(content, "source")) | 223 | MatchesTagText(content, "source")) |
183 | 222 | self.assertThat( | 224 | self.assertThat( |
184 | 225 | "Build schedule:\n(?)\nBuilt on request\nEdit snap package\n", | ||
185 | 226 | MatchesTagText(content, "auto_build")) | ||
186 | 227 | self.assertThat( | ||
187 | 228 | "Source archive for automatic builds:\n\nEdit snap package\n", | ||
188 | 229 | MatchesTagText(content, "auto_build_archive")) | ||
189 | 230 | self.assertThat( | ||
190 | 231 | "Pocket for automatic builds:\n\nEdit snap package", | ||
191 | 232 | MatchesTagText(content, "auto_build_pocket")) | ||
192 | 233 | self.assertThat( | ||
193 | 223 | "Builds of this snap package are not automatically uploaded to " | 234 | "Builds of this snap package are not automatically uploaded to " |
194 | 224 | "the store.\nEdit snap package", | 235 | "the store.\nEdit snap package", |
195 | 225 | MatchesTagText(content, "store_upload")) | 236 | MatchesTagText(content, "store_upload")) |
196 | 226 | 237 | ||
197 | 227 | def test_create_new_snap_git(self): | 238 | def test_create_new_snap_git(self): |
198 | 239 | hosting_client = FakeMethod() | ||
199 | 240 | hosting_client.getBlob = FakeMethod(result="") | ||
200 | 241 | self.useFixture(ZopeUtilityFixture(hosting_client, IGitHostingClient)) | ||
201 | 228 | [git_ref] = self.factory.makeGitRefs() | 242 | [git_ref] = self.factory.makeGitRefs() |
202 | 229 | source_display = git_ref.display_name | 243 | source_display = git_ref.display_name |
203 | 230 | browser = self.getViewBrowser( | 244 | browser = self.getViewBrowser( |
204 | @@ -244,6 +258,15 @@ | |||
205 | 244 | "Source:\n%s\nEdit snap package" % source_display, | 258 | "Source:\n%s\nEdit snap package" % source_display, |
206 | 245 | MatchesTagText(content, "source")) | 259 | MatchesTagText(content, "source")) |
207 | 246 | self.assertThat( | 260 | self.assertThat( |
208 | 261 | "Build schedule:\n(?)\nBuilt on request\nEdit snap package\n", | ||
209 | 262 | MatchesTagText(content, "auto_build")) | ||
210 | 263 | self.assertThat( | ||
211 | 264 | "Source archive for automatic builds:\n\nEdit snap package\n", | ||
212 | 265 | MatchesTagText(content, "auto_build_archive")) | ||
213 | 266 | self.assertThat( | ||
214 | 267 | "Pocket for automatic builds:\n\nEdit snap package", | ||
215 | 268 | MatchesTagText(content, "auto_build_pocket")) | ||
216 | 269 | self.assertThat( | ||
217 | 247 | "Builds of this snap package are not automatically uploaded to " | 270 | "Builds of this snap package are not automatically uploaded to " |
218 | 248 | "the store.\nEdit snap package", | 271 | "the store.\nEdit snap package", |
219 | 249 | MatchesTagText(content, "store_upload")) | 272 | MatchesTagText(content, "store_upload")) |
220 | @@ -309,6 +332,34 @@ | |||
221 | 309 | extract_text(find_tag_by_id(browser.contents, "privacy")) | 332 | extract_text(find_tag_by_id(browser.contents, "privacy")) |
222 | 310 | ) | 333 | ) |
223 | 311 | 334 | ||
224 | 335 | def test_create_new_snap_auto_build(self): | ||
225 | 336 | # Creating a new snap and asking for it to be automatically built | ||
226 | 337 | # sets all the appropriate fields. | ||
227 | 338 | branch = self.factory.makeAnyBranch() | ||
228 | 339 | archive = self.factory.makeArchive() | ||
229 | 340 | browser = self.getViewBrowser( | ||
230 | 341 | branch, view_name="+new-snap", user=self.person) | ||
231 | 342 | browser.getControl(name="field.name").value = "snap-name" | ||
232 | 343 | browser.getControl( | ||
233 | 344 | "Automatically build when branch changes").selected = True | ||
234 | 345 | browser.getControl("PPA").click() | ||
235 | 346 | browser.getControl(name="field.auto_build_archive.ppa").value = ( | ||
236 | 347 | archive.reference) | ||
237 | 348 | browser.getControl("Pocket for automatic builds").value = ["SECURITY"] | ||
238 | 349 | browser.getControl("Create snap package").click() | ||
239 | 350 | |||
240 | 351 | content = find_main_content(browser.contents) | ||
241 | 352 | self.assertThat( | ||
242 | 353 | "Build schedule:\n(?)\nBuilt automatically\nEdit snap package\n", | ||
243 | 354 | MatchesTagText(content, "auto_build")) | ||
244 | 355 | self.assertThat( | ||
245 | 356 | "Source archive for automatic builds:\n%s\nEdit snap package\n" % | ||
246 | 357 | archive.displayname, | ||
247 | 358 | MatchesTagText(content, "auto_build_archive")) | ||
248 | 359 | self.assertThat( | ||
249 | 360 | "Pocket for automatic builds:\nSecurity\nEdit snap package", | ||
250 | 361 | MatchesTagText(content, "auto_build_pocket")) | ||
251 | 362 | |||
252 | 312 | def test_create_new_snap_store_upload(self): | 363 | def test_create_new_snap_store_upload(self): |
253 | 313 | # Creating a new snap and asking for it to be automatically uploaded | 364 | # Creating a new snap and asking for it to be automatically uploaded |
254 | 314 | # to the store sets all the appropriate fields and redirects to SSO | 365 | # to the store sets all the appropriate fields and redirects to SSO |
255 | @@ -441,7 +492,7 @@ | |||
256 | 441 | view = create_initialized_view(git_ref, "+new-snap") | 492 | view = create_initialized_view(git_ref, "+new-snap") |
257 | 442 | with mock.patch('yaml.load') as unsafe_load: | 493 | with mock.patch('yaml.load') as unsafe_load: |
258 | 443 | with mock.patch('yaml.safe_load') as safe_load: | 494 | with mock.patch('yaml.safe_load') as safe_load: |
260 | 444 | initial_values = view.initial_values | 495 | view.initial_values |
261 | 445 | self.assertEqual(0, unsafe_load.call_count) | 496 | self.assertEqual(0, unsafe_load.call_count) |
262 | 446 | self.assertEqual(1, safe_load.call_count) | 497 | self.assertEqual(1, safe_load.call_count) |
263 | 447 | 498 | ||
264 | @@ -574,6 +625,7 @@ | |||
265 | 574 | new_snappy_series = self.factory.makeSnappySeries( | 625 | new_snappy_series = self.factory.makeSnappySeries( |
266 | 575 | usable_distro_series=[new_series]) | 626 | usable_distro_series=[new_series]) |
267 | 576 | [new_git_ref] = self.factory.makeGitRefs() | 627 | [new_git_ref] = self.factory.makeGitRefs() |
268 | 628 | archive = self.factory.makeArchive() | ||
269 | 577 | 629 | ||
270 | 578 | browser = self.getViewBrowser(snap, user=self.person) | 630 | browser = self.getViewBrowser(snap, user=self.person) |
271 | 579 | browser.getLink("Edit snap package").click() | 631 | browser.getLink("Edit snap package").click() |
272 | @@ -585,6 +637,12 @@ | |||
273 | 585 | browser.getControl("Git repository").value = ( | 637 | browser.getControl("Git repository").value = ( |
274 | 586 | new_git_ref.repository.identity) | 638 | new_git_ref.repository.identity) |
275 | 587 | browser.getControl("Git branch").value = new_git_ref.path | 639 | browser.getControl("Git branch").value = new_git_ref.path |
276 | 640 | browser.getControl( | ||
277 | 641 | "Automatically build when branch changes").selected = True | ||
278 | 642 | browser.getControl("PPA").click() | ||
279 | 643 | browser.getControl(name="field.auto_build_archive.ppa").value = ( | ||
280 | 644 | archive.reference) | ||
281 | 645 | browser.getControl("Pocket for automatic builds").value = ["SECURITY"] | ||
282 | 588 | browser.getControl("Update snap package").click() | 646 | browser.getControl("Update snap package").click() |
283 | 589 | 647 | ||
284 | 590 | content = find_main_content(browser.contents) | 648 | content = find_main_content(browser.contents) |
285 | @@ -598,6 +656,16 @@ | |||
286 | 598 | "Source:\n%s\nEdit snap package" % new_git_ref.display_name, | 656 | "Source:\n%s\nEdit snap package" % new_git_ref.display_name, |
287 | 599 | MatchesTagText(content, "source")) | 657 | MatchesTagText(content, "source")) |
288 | 600 | self.assertThat( | 658 | self.assertThat( |
289 | 659 | "Build schedule:\n(?)\nBuilt automatically\nEdit snap package\n", | ||
290 | 660 | MatchesTagText(content, "auto_build")) | ||
291 | 661 | self.assertThat( | ||
292 | 662 | "Source archive for automatic builds:\n%s\nEdit snap package\n" % | ||
293 | 663 | archive.displayname, | ||
294 | 664 | MatchesTagText(content, "auto_build_archive")) | ||
295 | 665 | self.assertThat( | ||
296 | 666 | "Pocket for automatic builds:\nSecurity\nEdit snap package", | ||
297 | 667 | MatchesTagText(content, "auto_build_pocket")) | ||
298 | 668 | self.assertThat( | ||
299 | 601 | "Builds of this snap package are not automatically uploaded to " | 669 | "Builds of this snap package are not automatically uploaded to " |
300 | 602 | "the store.\nEdit snap package", | 670 | "the store.\nEdit snap package", |
301 | 603 | MatchesTagText(content, "store_upload")) | 671 | MatchesTagText(content, "store_upload")) |
302 | @@ -1083,6 +1151,10 @@ | |||
303 | 1083 | Owner: Test Person | 1151 | Owner: Test Person |
304 | 1084 | Distribution series: Ubuntu Shiny | 1152 | Distribution series: Ubuntu Shiny |
305 | 1085 | Source: lp://dev/~test-person/\\+junk/snap-branch | 1153 | Source: lp://dev/~test-person/\\+junk/snap-branch |
306 | 1154 | Build schedule: \(\?\) | ||
307 | 1155 | Built on request | ||
308 | 1156 | Source archive for automatic builds: | ||
309 | 1157 | Pocket for automatic builds: | ||
310 | 1086 | Builds of this snap package are not automatically uploaded to | 1158 | Builds of this snap package are not automatically uploaded to |
311 | 1087 | the store. | 1159 | the store. |
312 | 1088 | Latest builds | 1160 | Latest builds |
313 | @@ -1106,6 +1178,10 @@ | |||
314 | 1106 | Owner: Test Person | 1178 | Owner: Test Person |
315 | 1107 | Distribution series: Ubuntu Shiny | 1179 | Distribution series: Ubuntu Shiny |
316 | 1108 | Source: ~test-person/\\+git/snap-repository:master | 1180 | Source: ~test-person/\\+git/snap-repository:master |
317 | 1181 | Build schedule: \(\?\) | ||
318 | 1182 | Built on request | ||
319 | 1183 | Source archive for automatic builds: | ||
320 | 1184 | Pocket for automatic builds: | ||
321 | 1109 | Builds of this snap package are not automatically uploaded to | 1185 | Builds of this snap package are not automatically uploaded to |
322 | 1110 | the store. | 1186 | the store. |
323 | 1111 | Latest builds | 1187 | Latest builds |
324 | 1112 | 1188 | ||
325 | === modified file 'lib/lp/snappy/configure.zcml' | |||
326 | --- lib/lp/snappy/configure.zcml 2016-05-06 16:34:21 +0000 | |||
327 | +++ lib/lp/snappy/configure.zcml 2016-07-12 13:40:07 +0000 | |||
328 | @@ -14,6 +14,8 @@ | |||
329 | 14 | <include package=".browser" /> | 14 | <include package=".browser" /> |
330 | 15 | <include file="vocabularies.zcml" /> | 15 | <include file="vocabularies.zcml" /> |
331 | 16 | 16 | ||
332 | 17 | <lp:help-folder folder="help" name="+help-snappy" /> | ||
333 | 18 | |||
334 | 17 | <!-- Snap --> | 19 | <!-- Snap --> |
335 | 18 | <class class="lp.snappy.model.snap.Snap"> | 20 | <class class="lp.snappy.model.snap.Snap"> |
336 | 19 | <require | 21 | <require |
337 | 20 | 22 | ||
338 | === added directory 'lib/lp/snappy/help' | |||
339 | === added file 'lib/lp/snappy/help/snap-build-frequency.html' | |||
340 | --- lib/lp/snappy/help/snap-build-frequency.html 1970-01-01 00:00:00 +0000 | |||
341 | +++ lib/lp/snappy/help/snap-build-frequency.html 2016-07-12 13:40:07 +0000 | |||
342 | @@ -0,0 +1,42 @@ | |||
343 | 1 | <html> | ||
344 | 2 | <head> | ||
345 | 3 | <title>Snap package build schedule</title> | ||
346 | 4 | <link rel="stylesheet" type="text/css" | ||
347 | 5 | href="/+icing/yui/cssreset/reset.css" /> | ||
348 | 6 | <link rel="stylesheet" type="text/css" | ||
349 | 7 | href="/+icing/yui/cssfonts/fonts.css" /> | ||
350 | 8 | <link rel="stylesheet" type="text/css" | ||
351 | 9 | href="/+icing/yui/cssbase/base.css" /> | ||
352 | 10 | <style type="text/css"> | ||
353 | 11 | dt { font-weight: bold } | ||
354 | 12 | dd p { margin-bottom: 0.5em } | ||
355 | 13 | </style> | ||
356 | 14 | </head> | ||
357 | 15 | <body> | ||
358 | 16 | <h1>Snap package build schedule</h1> | ||
359 | 17 | |||
360 | 18 | <p>There are two options for when snap packages get built:</p> | ||
361 | 19 | <dl> | ||
362 | 20 | <dt>Built automatically</dt> | ||
363 | 21 | <dd> | ||
364 | 22 | <p>A build will be scheduled automatically once a change to the | ||
365 | 23 | top-level source branch for the snap package is detected.</p> | ||
366 | 24 | <p>If there has been a build of the snap package within the previous | ||
367 | 25 | hour from the source archive, the build will not be scheduled | ||
368 | 26 | until an hour since the last build from the source archive.</p> | ||
369 | 27 | <p>If the snap package has been built within the last hour from a | ||
370 | 28 | different archive using the "Request builds" action, this will not | ||
371 | 29 | delay the automatic build.</p> | ||
372 | 30 | <p>If you really want the build to happen before the one-hour period | ||
373 | 31 | is up, you can use the "Request builds" action.</p> | ||
374 | 32 | </dd> | ||
375 | 33 | <dt>Built on request</dt> | ||
376 | 34 | <dd> | ||
377 | 35 | <p>Builds of the snap package have to be manually requested using | ||
378 | 36 | the "Request builds" action.</p> | ||
379 | 37 | </dd> | ||
380 | 38 | </dl> | ||
381 | 39 | |||
382 | 40 | </body> | ||
383 | 41 | </html> | ||
384 | 42 | |||
385 | 0 | 43 | ||
386 | === modified file 'lib/lp/snappy/javascript/snap.edit.js' | |||
387 | --- lib/lp/snappy/javascript/snap.edit.js 2015-09-09 14:17:46 +0000 | |||
388 | +++ lib/lp/snappy/javascript/snap.edit.js 2016-07-12 13:40:07 +0000 | |||
389 | @@ -1,7 +1,8 @@ | |||
391 | 1 | /* Copyright 2015 Canonical Ltd. This software is licensed under the | 1 | /* Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
392 | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). |
393 | 3 | * | 3 | * |
395 | 4 | * Control enabling/disabling form elements on the Snap:+edit page. | 4 | * Control enabling/disabling form elements on the {Branch,GitRef}:+new-snap |
396 | 5 | * and Snap:+edit pages. | ||
397 | 5 | * | 6 | * |
398 | 6 | * @module Y.lp.snappy.snap.edit | 7 | * @module Y.lp.snappy.snap.edit |
399 | 7 | * @requires node, DOM | 8 | * @requires node, DOM |
400 | @@ -12,7 +13,9 @@ | |||
401 | 12 | 13 | ||
402 | 13 | module.set_enabled = function(field_id, is_enabled) { | 14 | module.set_enabled = function(field_id, is_enabled) { |
403 | 14 | var field = Y.DOM.byId(field_id); | 15 | var field = Y.DOM.byId(field_id); |
405 | 15 | field.disabled = !is_enabled; | 16 | if (field !== null) { |
406 | 17 | field.disabled = !is_enabled; | ||
407 | 18 | } | ||
408 | 16 | }; | 19 | }; |
409 | 17 | 20 | ||
410 | 18 | module.onclick_vcs = function(e) { | 21 | module.onclick_vcs = function(e) { |
411 | @@ -22,15 +25,31 @@ | |||
412 | 22 | selected_vcs = node.get('value'); | 25 | selected_vcs = node.get('value'); |
413 | 23 | } | 26 | } |
414 | 24 | }); | 27 | }); |
418 | 25 | module.set_enabled('field.branch', selected_vcs === 'BZR'); | 28 | if (selected_vcs !== null) { |
419 | 26 | module.set_enabled('field.git_ref.repository', selected_vcs === 'GIT'); | 29 | module.set_enabled('field.branch', selected_vcs === 'BZR'); |
420 | 27 | module.set_enabled('field.git_ref.path', selected_vcs === 'GIT'); | 30 | module.set_enabled( |
421 | 31 | 'field.git_ref.repository', selected_vcs === 'GIT'); | ||
422 | 32 | module.set_enabled('field.git_ref.path', selected_vcs === 'GIT'); | ||
423 | 33 | } | ||
424 | 34 | }; | ||
425 | 35 | |||
426 | 36 | module.onclick_auto_build = function(e) { | ||
427 | 37 | var auto_build = Y.one( | ||
428 | 38 | 'input[name="field.auto_build"]').get('checked'); | ||
429 | 39 | module.set_enabled( | ||
430 | 40 | 'field.auto_build_archive.option.primary', auto_build); | ||
431 | 41 | module.set_enabled('field.auto_build_archive.option.ppa', auto_build); | ||
432 | 42 | module.set_enabled('field.auto_build_archive.ppa', auto_build); | ||
433 | 43 | module.set_enabled('field.auto_build_pocket', auto_build); | ||
434 | 28 | }; | 44 | }; |
435 | 29 | 45 | ||
436 | 30 | module.setup = function() { | 46 | module.setup = function() { |
437 | 31 | Y.all('input[name="field.vcs"]').on('click', module.onclick_vcs); | 47 | Y.all('input[name="field.vcs"]').on('click', module.onclick_vcs); |
438 | 48 | Y.all('input[name="field.auto_build"]').on( | ||
439 | 49 | 'click', module.onclick_auto_build); | ||
440 | 32 | 50 | ||
441 | 33 | // Set the initial state. | 51 | // Set the initial state. |
442 | 34 | module.onclick_vcs(); | 52 | module.onclick_vcs(); |
443 | 53 | module.onclick_auto_build(); | ||
444 | 35 | }; | 54 | }; |
445 | 36 | }, '0.1', {'requires': ['node', 'DOM']}); | 55 | }, '0.1', {'requires': ['node', 'DOM']}); |
446 | 37 | 56 | ||
447 | === modified file 'lib/lp/snappy/javascript/tests/test_snap.edit.html' | |||
448 | --- lib/lp/snappy/javascript/tests/test_snap.edit.html 2015-09-09 14:17:46 +0000 | |||
449 | +++ lib/lp/snappy/javascript/tests/test_snap.edit.html 2016-07-12 13:40:07 +0000 | |||
450 | @@ -1,6 +1,6 @@ | |||
451 | 1 | <!DOCTYPE html> | 1 | <!DOCTYPE html> |
452 | 2 | <!-- | 2 | <!-- |
454 | 3 | Copyright 2015 Canonical Ltd. This software is licensed under the | 3 | Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
455 | 4 | GNU Affero General Public License version 3 (see the file LICENSE). | 4 | GNU Affero General Public License version 3 (see the file LICENSE). |
456 | 5 | --> | 5 | --> |
457 | 6 | 6 | ||
458 | @@ -133,6 +133,95 @@ | |||
459 | 133 | </div> | 133 | </div> |
460 | 134 | </td> | 134 | </td> |
461 | 135 | </tr> | 135 | </tr> |
462 | 136 | <tr> | ||
463 | 137 | <td colspan="2"> | ||
464 | 138 | <div> | ||
465 | 139 | <label for="field.auto_build">Automatically build when branch changes</label> | ||
466 | 140 | <input class="checkboxType" | ||
467 | 141 | id="field.auto_build" | ||
468 | 142 | name="field.auto_build" | ||
469 | 143 | type="checkbox" | ||
470 | 144 | value="" /> | ||
471 | 145 | </div> | ||
472 | 146 | </td> | ||
473 | 147 | </tr> | ||
474 | 148 | <tr> | ||
475 | 149 | <td> | ||
476 | 150 | <table class="subordinate"> | ||
477 | 151 | <tr> | ||
478 | 152 | <td colspan="2"> | ||
479 | 153 | <div> | ||
480 | 154 | <label for="field.auto_build_archive">Source archive for automatic builds:</label> | ||
481 | 155 | <div> | ||
482 | 156 | <table> | ||
483 | 157 | <tr> | ||
484 | 158 | <td colspan="2"> | ||
485 | 159 | <label> | ||
486 | 160 | <input class="radioType" | ||
487 | 161 | id="field.auto_build_archive.option.primary" | ||
488 | 162 | name="field.auto_build_archive" | ||
489 | 163 | type="radio" | ||
490 | 164 | value="primary" /> | ||
491 | 165 | Primary Archive for Ubuntu | ||
492 | 166 | </label> | ||
493 | 167 | </td> | ||
494 | 168 | </tr> | ||
495 | 169 | <tr> | ||
496 | 170 | <td> | ||
497 | 171 | <label> | ||
498 | 172 | <input class="radioType" | ||
499 | 173 | id="field.auto_build_archive.option.ppa" | ||
500 | 174 | name="field.auto_build_archive" | ||
501 | 175 | type="radio" | ||
502 | 176 | value="ppa" /> | ||
503 | 177 | PPA | ||
504 | 178 | </label> | ||
505 | 179 | </td> | ||
506 | 180 | <td> | ||
507 | 181 | <input type="text" | ||
508 | 182 | value="" | ||
509 | 183 | id="field.auto_build_archive.ppa" | ||
510 | 184 | name="field.auto_build_archive.ppa" | ||
511 | 185 | size="20" | ||
512 | 186 | maxlength="" | ||
513 | 187 | onKeyPress="" | ||
514 | 188 | style="" | ||
515 | 189 | class="" /> | ||
516 | 190 | </td> | ||
517 | 191 | </tr> | ||
518 | 192 | </table> | ||
519 | 193 | </div> | ||
520 | 194 | </div> | ||
521 | 195 | </td> | ||
522 | 196 | </tr> | ||
523 | 197 | <tr> | ||
524 | 198 | <td colspan="2"> | ||
525 | 199 | <div> | ||
526 | 200 | <label for="field.auto_build_pocket">Pocket for automatic builds:</label> | ||
527 | 201 | <div> | ||
528 | 202 | <div> | ||
529 | 203 | <div class="value"> | ||
530 | 204 | <select id="field.auto_build_pocket" | ||
531 | 205 | name="field.auto_build_pocket" | ||
532 | 206 | size="1"> | ||
533 | 207 | <option value="RELEASE">Release</option> | ||
534 | 208 | <option value="SECURITY">Security</option> | ||
535 | 209 | <option selected="selected" value="UPDATES">Updates</option> | ||
536 | 210 | <option value="PROPOSED">Proposed</option> | ||
537 | 211 | <option value="BACKPORTS">Backports</option> | ||
538 | 212 | </select> | ||
539 | 213 | </div> | ||
540 | 214 | <input name="field.auto_build_pocket-empty-marker" | ||
541 | 215 | type="hidden" | ||
542 | 216 | value="1" /> | ||
543 | 217 | </div> | ||
544 | 218 | </div> | ||
545 | 219 | </div> | ||
546 | 220 | </td> | ||
547 | 221 | </tr> | ||
548 | 222 | </table> | ||
549 | 223 | </td> | ||
550 | 224 | </tr> | ||
551 | 136 | </table> | 225 | </table> |
552 | 137 | 226 | ||
553 | 138 | <input type="submit" id="field.actions.update" | 227 | <input type="submit" id="field.actions.update" |
554 | 139 | 228 | ||
555 | === modified file 'lib/lp/snappy/javascript/tests/test_snap.edit.js' | |||
556 | --- lib/lp/snappy/javascript/tests/test_snap.edit.js 2015-09-09 14:17:46 +0000 | |||
557 | +++ lib/lp/snappy/javascript/tests/test_snap.edit.js 2016-07-12 13:40:07 +0000 | |||
558 | @@ -1,4 +1,4 @@ | |||
560 | 1 | /* Copyright 2015 Canonical Ltd. This software is licensed under the | 1 | /* Copyright 2015-2016 Canonical Ltd. This software is licensed under the |
561 | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). |
562 | 3 | * | 3 | * |
563 | 4 | * Test driver for snap.edit.js. | 4 | * Test driver for snap.edit.js. |
564 | @@ -14,9 +14,10 @@ | |||
565 | 14 | setUp: function() { | 14 | setUp: function() { |
566 | 15 | this.tbody = Y.one('#snap.edit'); | 15 | this.tbody = Y.one('#snap.edit'); |
567 | 16 | 16 | ||
569 | 17 | // Get the individual VCS type radio buttons. | 17 | // Get the widgets with event handlers attached. |
570 | 18 | this.vcs_bzr = Y.DOM.byId('field.vcs.Bazaar'); | 18 | this.vcs_bzr = Y.DOM.byId('field.vcs.Bazaar'); |
571 | 19 | this.vcs_git = Y.DOM.byId('field.vcs.Git'); | 19 | this.vcs_git = Y.DOM.byId('field.vcs.Git'); |
572 | 20 | this.auto_build = Y.DOM.byId('field.auto_build'); | ||
573 | 20 | 21 | ||
574 | 21 | // Get the input widgets. | 22 | // Get the input widgets. |
575 | 22 | this.input_branch = Y.DOM.byId('field.branch'); | 23 | this.input_branch = Y.DOM.byId('field.branch'); |
576 | @@ -45,6 +46,7 @@ | |||
577 | 45 | 46 | ||
578 | 46 | check_handler(this.vcs_bzr, module.onclick_vcs); | 47 | check_handler(this.vcs_bzr, module.onclick_vcs); |
579 | 47 | check_handler(this.vcs_git, module.onclick_vcs); | 48 | check_handler(this.vcs_git, module.onclick_vcs); |
580 | 49 | check_handler(this.auto_build, module.onclick_auto_build); | ||
581 | 48 | }, | 50 | }, |
582 | 49 | 51 | ||
583 | 50 | test_select_vcs_bzr: function() { | 52 | test_select_vcs_bzr: function() { |
584 | @@ -73,7 +75,38 @@ | |||
585 | 73 | 'git_ref.repository field disabled'); | 75 | 'git_ref.repository field disabled'); |
586 | 74 | Y.Assert.isFalse(this.input_git_path.disabled, | 76 | Y.Assert.isFalse(this.input_git_path.disabled, |
587 | 75 | 'git_ref.path field disabled'); | 77 | 'git_ref.path field disabled'); |
588 | 78 | }, | ||
589 | 79 | |||
590 | 80 | test_check_auto_build: function() { | ||
591 | 81 | var fields = [ | ||
592 | 82 | 'auto_build_archive.option.primary', | ||
593 | 83 | 'auto_build_archive.option.ppa', | ||
594 | 84 | 'auto_build_archive.ppa', | ||
595 | 85 | 'auto_build_pocket' | ||
596 | 86 | ]; | ||
597 | 87 | var field; | ||
598 | 88 | module.setup(); | ||
599 | 89 | for (i = 0; i < fields.length; i++) { | ||
600 | 90 | field = Y.DOM.byId('field.' + fields[i]); | ||
601 | 91 | Y.Assert.isTrue( | ||
602 | 92 | field.disabled, fields[i] + ' field not disabled'); | ||
603 | 93 | } | ||
604 | 94 | this.auto_build.checked = true; | ||
605 | 95 | module.onclick_auto_build(); | ||
606 | 96 | for (i = 0; i < fields.length; i++) { | ||
607 | 97 | field = Y.DOM.byId('field.' + fields[i]); | ||
608 | 98 | Y.Assert.isFalse( | ||
609 | 99 | field.disabled, fields[i] + ' field disabled'); | ||
610 | 100 | } | ||
611 | 101 | this.auto_build.checked = false; | ||
612 | 102 | module.onclick_auto_build(); | ||
613 | 103 | for (i = 0; i < fields.length; i++) { | ||
614 | 104 | field = Y.DOM.byId('field.' + fields[i]); | ||
615 | 105 | Y.Assert.isTrue( | ||
616 | 106 | field.disabled, fields[i] + ' field not disabled'); | ||
617 | 107 | } | ||
618 | 76 | } | 108 | } |
619 | 109 | |||
620 | 77 | })); | 110 | })); |
621 | 78 | }, '0.1', { | 111 | }, '0.1', { |
622 | 79 | requires: ['lp.testing.runner', 'test', 'test-console', | 112 | requires: ['lp.testing.runner', 'test', 'test-console', |
623 | 80 | 113 | ||
624 | === modified file 'lib/lp/snappy/templates/snap-edit.pt' | |||
625 | --- lib/lp/snappy/templates/snap-edit.pt 2016-05-24 05:15:50 +0000 | |||
626 | +++ lib/lp/snappy/templates/snap-edit.pt 2016-07-12 13:40:07 +0000 | |||
627 | @@ -29,24 +29,6 @@ | |||
628 | 29 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | 29 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
629 | 30 | </tal:widget> | 30 | </tal:widget> |
630 | 31 | 31 | ||
631 | 32 | <tr tal:condition="view/has_snappy_distro_series"> | ||
632 | 33 | <td> | ||
633 | 34 | <tal:widget define="widget nocall:view/widgets/store_upload"> | ||
634 | 35 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
635 | 36 | </tal:widget> | ||
636 | 37 | <table class="subordinate"> | ||
637 | 38 | <tal:widget define="widget nocall:view/widgets/store_name"> | ||
638 | 39 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
639 | 40 | </tal:widget> | ||
640 | 41 | </table> | ||
641 | 42 | <p class="formHelp"> | ||
642 | 43 | If you change any settings related to automatically uploading | ||
643 | 44 | builds of this snap to the store, then the login service will | ||
644 | 45 | prompt you to authorize this request. | ||
645 | 46 | </p> | ||
646 | 47 | </td> | ||
647 | 48 | </tr> | ||
648 | 49 | |||
649 | 50 | <tr> | 32 | <tr> |
650 | 51 | <td> | 33 | <td> |
651 | 52 | <div> | 34 | <div> |
652 | @@ -78,6 +60,42 @@ | |||
653 | 78 | </td> | 60 | </td> |
654 | 79 | </tr> | 61 | </tr> |
655 | 80 | 62 | ||
656 | 63 | <tal:widget define="widget nocall:view/widgets/auto_build"> | ||
657 | 64 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
658 | 65 | </tal:widget> | ||
659 | 66 | <tr> | ||
660 | 67 | <td> | ||
661 | 68 | <table class="subordinate"> | ||
662 | 69 | <tal:widget define="widget nocall:view/widgets/auto_build_archive"> | ||
663 | 70 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
664 | 71 | </tal:widget> | ||
665 | 72 | <tal:widget define="widget nocall:view/widgets/auto_build_pocket"> | ||
666 | 73 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
667 | 74 | </tal:widget> | ||
668 | 75 | </table> | ||
669 | 76 | </td> | ||
670 | 77 | </tr> | ||
671 | 78 | |||
672 | 79 | <tal:has-sds tal:condition="view/has_snappy_distro_series"> | ||
673 | 80 | <tal:widget define="widget nocall:view/widgets/store_upload"> | ||
674 | 81 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
675 | 82 | </tal:widget> | ||
676 | 83 | <tr> | ||
677 | 84 | <td> | ||
678 | 85 | <table class="subordinate"> | ||
679 | 86 | <tal:widget define="widget nocall:view/widgets/store_name"> | ||
680 | 87 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
681 | 88 | </tal:widget> | ||
682 | 89 | </table> | ||
683 | 90 | <p class="formHelp"> | ||
684 | 91 | If you change any settings related to automatically uploading | ||
685 | 92 | builds of this snap to the store, then the login service will | ||
686 | 93 | prompt you to authorize this request. | ||
687 | 94 | </p> | ||
688 | 95 | </td> | ||
689 | 96 | </tr> | ||
690 | 97 | </tal:has-sds> | ||
691 | 98 | |||
692 | 81 | <tal:widget define="widget nocall:view/widgets/processors"> | 99 | <tal:widget define="widget nocall:view/widgets/processors"> |
693 | 82 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | 100 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
694 | 83 | </tal:widget> | 101 | </tal:widget> |
695 | 84 | 102 | ||
696 | === modified file 'lib/lp/snappy/templates/snap-index.pt' | |||
697 | --- lib/lp/snappy/templates/snap-index.pt 2016-05-28 00:21:40 +0000 | |||
698 | +++ lib/lp/snappy/templates/snap-index.pt 2016-07-12 13:40:07 +0000 | |||
699 | @@ -61,6 +61,31 @@ | |||
700 | 61 | <a tal:replace="structure view/menu:overview/edit/fmt:icon"/> | 61 | <a tal:replace="structure view/menu:overview/edit/fmt:icon"/> |
701 | 62 | </dd> | 62 | </dd> |
702 | 63 | </dl> | 63 | </dl> |
703 | 64 | |||
704 | 65 | <dl id="auto_build"> | ||
705 | 66 | <dt>Build schedule: | ||
706 | 67 | <a href="/+help-snappy/snap-build-frequency.html" target="help" | ||
707 | 68 | class="sprite maybe action-icon">(?)</a> | ||
708 | 69 | </dt> | ||
709 | 70 | <dd> | ||
710 | 71 | <span tal:replace="view/build_frequency"/> | ||
711 | 72 | <a tal:replace="structure view/menu:overview/edit/fmt:icon"/> | ||
712 | 73 | </dd> | ||
713 | 74 | </dl> | ||
714 | 75 | <dl id="auto_build_archive"> | ||
715 | 76 | <dt>Source archive for automatic builds:</dt> | ||
716 | 77 | <dd> | ||
717 | 78 | <a tal:replace="structure context/auto_build_archive/fmt:link"/> | ||
718 | 79 | <a tal:replace="structure view/menu:overview/edit/fmt:icon"/> | ||
719 | 80 | </dd> | ||
720 | 81 | </dl> | ||
721 | 82 | <dl id="auto_build_pocket"> | ||
722 | 83 | <dt>Pocket for automatic builds:</dt> | ||
723 | 84 | <dd> | ||
724 | 85 | <span tal:replace="context/auto_build_pocket/title|nothing"/> | ||
725 | 86 | <a tal:replace="structure view/menu:overview/edit/fmt:icon"/> | ||
726 | 87 | </dd> | ||
727 | 88 | </dl> | ||
728 | 64 | </div> | 89 | </div> |
729 | 65 | 90 | ||
730 | 66 | <div id="store_upload" class="two-column-list" | 91 | <div id="store_upload" class="two-column-list" |
731 | 67 | 92 | ||
732 | === modified file 'lib/lp/snappy/templates/snap-new.pt' | |||
733 | --- lib/lp/snappy/templates/snap-new.pt 2016-06-30 19:19:20 +0000 | |||
734 | +++ lib/lp/snappy/templates/snap-new.pt 2016-07-12 13:40:07 +0000 | |||
735 | @@ -35,26 +35,52 @@ | |||
736 | 35 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | 35 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
737 | 36 | </tal:widget> | 36 | </tal:widget> |
738 | 37 | 37 | ||
740 | 38 | <tr tal:condition="view/has_snappy_distro_series"> | 38 | <tal:widget define="widget nocall:view/widgets/auto_build"> |
741 | 39 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
742 | 40 | </tal:widget> | ||
743 | 41 | <tr> | ||
744 | 39 | <td> | 42 | <td> |
745 | 40 | <tal:widget define="widget nocall:view/widgets/store_upload"> | ||
746 | 41 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
747 | 42 | </tal:widget> | ||
748 | 43 | <table class="subordinate"> | 43 | <table class="subordinate"> |
750 | 44 | <tal:widget define="widget nocall:view/widgets/store_name"> | 44 | <tal:widget define="widget nocall:view/widgets/auto_build_archive"> |
751 | 45 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
752 | 46 | </tal:widget> | ||
753 | 47 | <tal:widget define="widget nocall:view/widgets/auto_build_pocket"> | ||
754 | 45 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | 48 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
755 | 46 | </tal:widget> | 49 | </tal:widget> |
756 | 47 | </table> | 50 | </table> |
757 | 48 | <p class="formHelp"> | ||
758 | 49 | If you ask Launchpad to automatically upload builds of this | ||
759 | 50 | snap to the store on your behalf, then the login service | ||
760 | 51 | will prompt you to authorize this request. | ||
761 | 52 | </p> | ||
762 | 53 | </td> | 51 | </td> |
763 | 54 | </tr> | 52 | </tr> |
764 | 53 | |||
765 | 54 | <tal:has-sds condition="view/has_snappy_distro_series"> | ||
766 | 55 | <tal:widget define="widget nocall:view/widgets/store_upload"> | ||
767 | 56 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
768 | 57 | </tal:widget> | ||
769 | 58 | <tr> | ||
770 | 59 | <td> | ||
771 | 60 | <table class="subordinate"> | ||
772 | 61 | <tal:widget define="widget nocall:view/widgets/store_name"> | ||
773 | 62 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> | ||
774 | 63 | </tal:widget> | ||
775 | 64 | </table> | ||
776 | 65 | <p class="formHelp"> | ||
777 | 66 | If you ask Launchpad to automatically upload builds of this | ||
778 | 67 | snap to the store on your behalf, then the login service | ||
779 | 68 | will prompt you to authorize this request. | ||
780 | 69 | </p> | ||
781 | 70 | </td> | ||
782 | 71 | </tr> | ||
783 | 72 | </tal:has-sds> | ||
784 | 55 | </table> | 73 | </table> |
785 | 56 | </metal:formbody> | 74 | </metal:formbody> |
786 | 57 | </div> | 75 | </div> |
787 | 76 | |||
788 | 77 | <script type="text/javascript"> | ||
789 | 78 | LPJS.use('lp.snappy.snap.edit', function(Y) { | ||
790 | 79 | Y.on('domready', function(e) { | ||
791 | 80 | Y.lp.snappy.snap.edit.setup(); | ||
792 | 81 | }, window); | ||
793 | 82 | }); | ||
794 | 83 | </script> | ||
795 | 58 | </div> | 84 | </div> |
796 | 59 | 85 | ||
797 | 60 | </body> | 86 | </body> |
LGTM, but it might be worth asking someone with more LP UI experience to take a look.