Showing posts with label CruiseControl. Show all posts
Showing posts with label CruiseControl. Show all posts

SVNLabelIncrementer in CruiseControl

SVNLabelIncrementer in CruiseControl is supposed to get the latest revision number for the project, and use this revision number as part of the cruisecontrol build number.

Unfortunately, we always got the revision number from the last successful build as the new label. For example, if the local working copy has revision-10 before CruiseControl build, and the current SVN repository revision is 12. We will get 10 as the revision number even if we get revision 12 code in the build. It's kind of annoying, isn't it?

After some investigation, we found that the SVNLabelIncrementer class was using "svnversion" command to get the revision number. Let's look at the definition of "svnversion":

svnversion — Summarize the local revision(s) of a working copy.

Apparently, that's not what we want. We want the revision number of the remote repository.

In the end, we modified the code to use "svn info" to get the remote svn repository revision. I have attached the code here, hope this helps other folks.


package net.sourceforge.cruisecontrol.labelincrementers;

import org.jdom.Element;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/*
To properly set this up put the following in your cruise config.xml




*/

public class SVNLabelIncrementer extends DefaultLabelIncrementer {

private String targetURL;

private String username="";

private String password="";



public String incrementLabel(String oldLabel, Element buildLog) {

String SVNRev = "";

try {
SVNRev = getSvnRevision();
} catch (IOException e) {
e.printStackTrace();
}

String label = getNonSubversionPartOfLabel(oldLabel);
if (SVNRev == null || SVNRev.equals(""))
return oldLabel;

return label + "." + SVNRev;
}

protected String getSvnRevision() throws IOException {
Process p = null;
try {
String[] commands = new String[]{"svn", "info", targetURL, "--username", username, "--password", password};
p = Runtime.getRuntime().exec(commands);

BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String thisLine = stdInput.readLine();
while (thisLine != null) {
if (thisLine.startsWith("Revision:")) {
return thisLine.split(":")[1].trim();
}
thisLine = stdInput.readLine();
}
} finally {
if (p != null)
p.destroy();
}
return "";
}

public boolean isValidLabel(String label) {
return super.isValidLabel(getNonSubversionPartOfLabel(label));
}

private String getNonSubversionPartOfLabel(String label) {
int index = label.lastIndexOf(".");
if (index == -1)
index = label.length();
return label.substring(0, index);
}

public String getTargetURL() {
return targetURL;
}

public void setTargetURL(String targetURL) {
this.targetURL = targetURL;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}



Timeout in CruiseControl

In my Cruisecontrol setup, I need to make an ant call to ruby scripts. Originally, I setup CruiseControl timeout in AntBuilder, somehow it could not kill ruby process. CruiseControl will wait till the end of ruby process, and show timeout error in the report.

I started looking at Ant exec task timeout, which I expect the process times out after 5 hours, but the build always times out within one minute.

What's wrong?

Don't laugh at me. Cruisecontrol AntBuilder use seconds to measure timeout, but Ant Exec task uses milliseconds!