Merge lp:~wallyworld/launchpad/recipe-request-builds-existing into lp:launchpad

Proposed by Ian Booth
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 12562
Proposed branch: lp:~wallyworld/launchpad/recipe-request-builds-existing
Merge into: lp:launchpad
Diff against target: 112 lines (+29/-23)
1 file modified
lib/lp/code/javascript/requestbuild_overlay.js (+29/-23)
To merge this branch: bzr merge lp:~wallyworld/launchpad/recipe-request-builds-existing
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Launchpad code reviewers code Pending
Leonard Richardson code Pending
Review via email: mp+52389@code.launchpad.net

Commit message

[r=thumper][bug=728789] Fix the mechanism used by the recipe request builds popup form to determine the currently pending builds for the recipe.

Description of the change

Fix the mechanism used by the recipe request builds popup form to determine the currently pending builds for the recipe. The currently pending builds are required so that the corresponding distro series checkboxes on the popup form can be disabled, preventing the user from asking for an already pending build.

== Implementation ==

The original implementation was broken - there was no web service api available to do the job and a crap implementation was done. Now, the pending_builds property on a recipe has been exported to the web service. This branch uses that api.

The web service is invoked as follows:

lp_client.get(LP.cache.context.pending_builds_collection_link, y_config);

The result is a list of build entries. We are interested in the build's "distro_series" and "archive" properties (which have been exported to the web service):
  build_record.get("distro_series_link")
  build_record.get("archive_link")

By way of example, the distro_series_link resolves to something like: "https://code.launchpad.dev/api/devel/ubuntu/warty"
We need to use the information we now have to figure out what checkboxes on the request build popup to disable. The checkboxes are labelled with the distro series name so that's what we need to match on. Strictly speaking, we would need to make yet another back end call to get the name of the distro series defined by the distro series link. However, this merge proposal uses the fact that the distro_series_link value ends with a segment corresponding to the distro series name. So we avoid having to make another back end call.

The same approach is used for the archive - the archive link value ends with a path segment which is sufficient to define which archive has been chosen from archive combo box.

I need advice as to whether the above approach is considered kosher. The alternative is to make 2 additional back end calls to fetch the distro series and archive names. However, as stated, the link values contain sufficient information so that these additional back end calls can be avoided.

In addition to the aboce changes, the invocation of the disable_existing_builds() function is now implemented using a Y.after() call so that it happens when the form is finished rendering.

== Tests==

Use the existing code.windmill.tests.test_recipe_request_build.py tests.

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Code looks reasonable.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/javascript/requestbuild_overlay.js'
2--- lib/lp/code/javascript/requestbuild_overlay.js 2011-02-28 22:49:50 +0000
3+++ lib/lp/code/javascript/requestbuild_overlay.js 2011-03-07 10:23:58 +0000
4@@ -80,6 +80,9 @@
5 form_submit_callback: do_request_builds,
6 visible: false
7 });
8+ Y.after(function() {
9+ disable_existing_builds(request_build_submit_button);
10+ }, request_build_overlay, "bindUI");
11 request_build_overlay.render();
12 request_build_submit_button =
13 Y.Node.one("[name='field.actions.request']");
14@@ -93,7 +96,6 @@
15 request_build_overlay.form_node.set("innerHTML", loading_spinner);
16 request_build_overlay.loadFormContentAndRender('+builds/++form++');
17 request_build_submit_button.show();
18- disable_existing_builds(request_build_submit_button);
19 request_build_overlay.show();
20 });
21
22@@ -410,13 +412,13 @@
23 Y.Array.each(last_known_pending_builds, function(distroarchive) {
24 var archive_parts = ppa_value.split("/");
25 var archive = archive_parts.pop();
26- if( archive != distroarchive[1] )
27+ if( archive.toLowerCase() != distroarchive[1].toLowerCase() )
28 return;
29
30 for (var i=0; i<distroseries_nodes.size(); i++) {
31 var distroseries_node = distroseries_nodes.item(i);
32 var distro = distroseries_node.get("text").trim();
33- if (distro == distroarchive[0] ) {
34+ if (distro.toLowerCase() == distroarchive[0].toLowerCase() ) {
35 nr_matches += 1;
36 var disabled_checkbox_html = Y.Lang.substitute(
37 DISABLED_DISTROSERIES_CHECKBOX_HTML, {distro: distro});
38@@ -438,19 +440,15 @@
39 // so that we can attempt to prevent the user from requesting builds
40 // which are already pending. It's not foolproof since a build may finish
41 // or be initiated after this initial lookup, but we do handle that
42- // situation in the error handling. We also have to do this work by
43- // parsing html but it's the best we have for now.
44-
45- var base_url = LP.cache.context.web_link;
46- var submit_url = base_url+"/+builds";
47+ // situation in the error handling.
48
49 distroseries_node_html = new Array();
50 last_known_pending_builds = new Array();
51 var y_config = {
52- headers: {'Accept': 'application/json; application/xhtml'},
53+ headers: {'Accept': 'application/json;'},
54 on: {
55 success:
56- function(id, response) {
57+ function(build_info) {
58 // We save the inner html of each distro series checkbox
59 // so we can restore it when required.
60 var distro_nodes = get_distroseries_nodes();
61@@ -459,22 +457,29 @@
62 distro_node.get("innerHTML"));
63 });
64
65- // We parse the build view html to extract the pending
66- // build info. Yuck. But there's no other api call to use
67- // at the moment.
68- var builds = Y.Node.create(response.responseText);
69- var build_rows = builds.all('tr.package-build');
70- build_rows.each(function(build_row) {
71- var distro = build_row.one(":nth-child(3) a");
72- var archive = build_row.one(":nth-child(4) a");
73- var href = archive.get("href");
74- var href_parts = href.split("/");
75+ //We have a json collection of the pending build records.
76+ var size = build_info.total_size;
77+ for( var i=0; i<size; i++ ) {
78+ var build_record = build_info.entries[i];
79+ var distro_link = build_record.get(
80+ "distro_series_link");
81+ var archive_link = build_record.get("archive_link");
82
83+ // The very last segment of the distro series and
84+ // archive links will be the bits we want to match on.
85+ // eg for distro series, the link will be like:
86+ // https://code.launchpad.dev/api/devel/ubuntu/warty
87+ // and "warty" is what we match on.
88+ var distro_parts = distro_link.split("/");
89+ var archive_parts = archive_link.split("/");
90 last_known_pending_builds.push(
91- [distro.get("text"), href_parts.pop()])
92- });
93+ [distro_parts.pop(), archive_parts.pop()])
94+ }
95 var ppa_selector = request_build_overlay.form_node.one(
96 "[name='field.archive']");
97+ if (ppa_selector == null) {
98+ return;
99+ }
100 ppa_selector.on("change", function(e) {
101 ppa_changed(ppa_selector.get("value"), submit_button);
102 });
103@@ -482,7 +487,8 @@
104 }
105 }
106 };
107- Y.io(submit_url, y_config);
108+ set_up_lp_client();
109+ lp_client.get(LP.cache.context.pending_builds_collection_link, y_config);
110 }
111 }, "0.1", {"requires": [
112 "dom", "node", "io-base", "lazr.anim", "lazr.formoverlay", "lp.client"