tags:

views:

53

answers:

2

In Hudson we have a job that deploys a specified subversion tag to a server. This tag is currently entered in a text field, but since that is just a typing mistake waiting to happen, we would like that text field to be replaced by a drop down list with the currently available tags. That is, we would like Hudson to go to <subversion repo url>/tags and fetch all tags found there.

I've searched for a Hudson plugin or some other way to accomplish this, with no success. This can't be the first time someone wants this, right? Or would this be considered bad practice for some reason that I can not think of at the moment?

EDIT

Someone else did have the same idea (only three weeks ago), but there is no posted solution right now: http://issues.hudson-ci.org/browse/HUDSON-6682?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel

+1  A: 

How about the batch task Plugin. This will allow you to go to any build in Hudson (current and old one) and run a batch on that build. The batches are predefined tasks.

This will only work for your purpose if Hudson is creating you official build and tagging it in subversion. And of course only for the builds that are not deleted yet. ;)

Peter Schuetze
At the moment we are tagging our builds manually, but I'll take a look on that plugin anyway.
Peter Jaric
I don't see exactly how I could use that plugin, but I am a Hudson newbie. Do you have a specific solution in mind?
Peter Jaric
If hudson is your build authority (which means hudson builds your project and creates the Hudson tag), than you can use either the archived artifacts (since they are the same than what's in subversion) or archive/generate the SVN tag and run your deployment. After installing the plugin, you can create batch tasks for your build job and when you decide later to actually deploy, you can call these tasks manually for a given build.
Peter Schuetze
What I don't see right now is how that will help me create a select box with the available tags in my Hudson deploy job. Could you expand a little on that? Ahhhh, you mean I should skip that approach and call the automatically created tasks instead (one for each tag)? Hmm, I will consider that.
Peter Jaric
You won't have a select box. You just choose a build from the build history and will find a link on the left side task. You Choose your deploy task and you are done. No need to enter any values.
Peter Schuetze
+1  A: 

Hello Peter,

In lieu of a Hudson plug-in (I do not know Java), how about some XSL (1.0)? In the following solution :

  1. We get a directory list of tags via svn list --xml, saved to svn-list.xml
  2. We run a transform to turn svn-list.xml into Hudson's internal schema for a choice drop-down, saved to hudson-list.xml
  3. We run another transform to join hudson-list.xml into the job's config.xml based on a specific name for the list we want to update, saved to new-config.xml, and update the Hudson job with the new config

1. svn list --xml

  svn list [path-to-svn-tag-directory] --xml > svn-list.xml

2. Convert SVN list to Hudson list

  xsltproc svn-to-hudson.xsl svn-list.xml > hudson-list.xml

svn-to-hudson.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/lists/list">
    <hudson.model.ChoiceParameterDefinition>
      <name>[Your Name for the List]</name>
      <description/>
      <choices class="java.util.Arrays$ArrayList">
        <a class="string-array">
          <xsl:apply-templates select="entry"/>
        </a>
      </choices>
    </hudson.model.ChoiceParameterDefinition>
  </xsl:template>

  <xsl:template match="entry">
    <string>
      <xsl:value-of select="name"/>
    </string>
  </xsl:template>
</xsl:stylesheet>

3. Join Hudson List with Job's config.xml

The following uses curl to get fetch the old config.xml, and to post the new one, utilizing Hudson's job API for modifying the config.

curl -o old-config.xml http://[your-hudson-server]/job/[job-name]/config.xml -u [username]:[password]
xsltproc join.xsl old-config.xml > new-config.xml
curl -X POST -d @new-config.xml http://[your-hudson-server]/job/[job-name]/config.xml -u [username]:[password]

join.xsl requires the presence of hudson-list.xml in the same directory:

<xsl:variable name="tag-list" select="document('hudson-list.xml')"/>

You will also need to modify

<xsl:variable name="list-name" select="string('Name')"/>

to the name of your list in the job (e.g., 'SVN tags', 'Tagged Builds', etc...).

join.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="xml" indent="yes"/>

  <xsl:variable name="tag-list" select="document('hudson-list.xml')"/>
  <xsl:variable name="list-name" select="string('Name')"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="hudson.model.ChoiceParameterDefinition">
    <xsl:choose>
      <xsl:when test="name = $list-name"> <!-- If the name matches, swap in new list -->
        <xsl:copy-of select="$tag-list"/>
      </xsl:when>
      <xsl:otherwise>                      <!-- If the name does not match, copy what's already there -->
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

I hope this end-to-end solution works for you.

Thank you,
Zachary

Zachary Young
Wow, impressive answer! This looks good, but I am missing how this will be run from Hudson. What I mean is: when a Hudson user navigates to the deploy job, I'd like the list of tags to be there already, with no need for the user to run your code.Do you mean that I should put it in another Hudson job, that is run automatically? That would work, wouldn't it?
Peter Jaric
Hi Peter. Yes, this could be run as a job in Hudson at regular intervals. This could also be implemented as a post-commit hook script in SVN which would only run when a new tag was created. Thank you.
Zachary Young
Thanks! I haven't tested this yet, but it seems very good.
Peter Jaric