Using Prototype / Ajax in Hudson

Triggered by the stackoverflow question Hudson: Running all jobs in a view by pressing one button, I played a bit with Ajax on Hudson using the Hudson API. The nice thing is: Hudson ships with the prototype api (but unfortunately with an ancient version, 1.5.x ), so that makes it easy to develop either quick inline scripts or bookmarklets.

The problem in the question was to create a button or link that triggers all jobs in a build with one click. Now there are several ways to do this using javascript / ajax:

  1. Use a browser bookmarklet
  2. Edit the site description

Generally, what we’ll do is work with the view’s api from within a view. So if your view has the URL http://myhudson/view/myview, the api is at http://myhudson/view/myview/api (try it)

What we’ll use is a script that queries the current view for it’s jobs and for each of those jobs, sends an Ajax get request to <job url>/build to trigger a new build. (Consult a job’s api by looking up http://myhudson/job/myjobname/api ).

So the basic script is this:

<script type="text/javascript">
<!--
function triggerBuilds(obj){
    obj.responseText.evalJSON()['jobs'].each(
            function(i){
                new Ajax.Request(i['url']+'build',{method:'GET'});
            }
    );
}

function buildAll(){
    new Ajax.Request(
            document.URL.replace(/[\W]+$/,'') + '/api/json',
            {
                onSuccess : triggerBuilds,
                method : 'GET'
            }
    );
}

Now we can either compress it and use it in a bookmarklet like this one:
javascript:var%20f%3dfunction(obj)%7bobj.responseText.evalJSON()%5b%27jobs%27%5d.each(function(i)%7bnew%20Ajax.Request(i%5b%27url%27%5d%2b%27build%27%2c%7bmethod%3a%27GET%27%7d)%3b%7d)%3b%7d%3bnew%20Ajax.Request(document.URL.replace(%2f%5b%5cW%5d%2b%24%2f%2c%27%27)%2b%27%2fapi%2fjson%27%2c%7bonSuccess%3af%2cmethod%3a%27GET%27%7d)%3bvoid(0)
(Triple-click the code to select it, copy it to the clipboard and create a new bookmark with this URL. Unfortunately I can’t provide the link here, due to restrictive javascript settings on wordpress)

Or edit the view’s description and paste the full code inside (including a link that calls the function):

<script type="text/javascript">
<!--
function triggerBuilds(obj){
    obj.responseText.evalJSON()['jobs'].each(
            function(i){
                new Ajax.Request(i['url']+'build',{method:'GET'});
            }
    );
}

function buildAll(){
    new Ajax.Request(
            document.URL.replace(/[\W]+$/,'') + '/api/json',
            {
                onSuccess : triggerBuilds,
                method : 'GET'
            }
    );
}

//-->
</script>
<a href="javascript:buildAll();void(0)">Build all Jobs in this view</a>

Another way to do it is to add links to all view tabs from the main page. Edit the main page description and post this code:

<style type="text/css">
a.buildLink {
display:inline-block !important;
text-decoration:none;
color:black;
}</style>
<script type="text/javascript">
<!--
function triggerBuilds(obj){
 obj.responseText.evalJSON()['jobs'].each(
 function(i){
 new Ajax.Request(i['url']+'build',{method:'GET'});
 }
 );
}

function buildAll(url){
 new Ajax.Request(
 (url?url:document.URL).replace(/[\W]+$/,'') + '/api/json',
 {
 onSuccess : triggerBuilds,
 method : 'GET'
 }
 );
}
function addlinks(){
$$('#viewList a').filter(function(item){return item.href.indexOf('/view/')>0;}).each(function(item){
item.setAttribute("style","display:inline");
new Insertion.After(item,
  '<a href="javascript:buildAll(\'' + item.href + '\');void(0)" title="Build all jobs in this view">[Build]</a>');
});
$$('#viewList .active').each(function(item){
new Insertion.Bottom(item,'<a href="javascript:buildAll();void(0)" title="Build all jobs">[Build]</a>');
});
}

Event.observe(window,'load', addlinks);
//-->
</script>

Now all view tabs on the main page will contain a [build] link that will launch all builds of this view.

Posted in Hudson, JavaScript | Leave a comment