spilth edited this page Sep 13, 2010 · 4 revisions
Clone this wiki locally

CI Build Monitor


The immediate goal of this project is to create build monitors for use with Urban Code’s continuous build and deploy production AntHill Pro. Currently the project includes one implemented using Quartz Composer on the Mac and one using Processing.

Eventually I’d like to genereify/standardize this project to work with other CI servers such as Hudson and Cruise Control.

Getting Started


There is no “binary” release of the Processing implementation, so you need the following steps to make use of it:

  1. Install Processing
  2. Download the Processing source from this repository
  3. Create a text file containing the URL of your feed
  4. Load processing/ci_build_monitor/ci_build_monitor.pde from within Processing
  5. Run the app (full-screen recommended)
  6. Select your URL file
  7. The app should then load your feed and begin displaying your workflows.

Quartz Composer


Workflow Feed

In order for this build monitor to work it needs an XML feed in a particular format. The format is as such:

<?xml version="1.0"?>
		<project>Awesome Project</project>
		<title>Build 1.X</title>
		<stamp>1.0.0 [8]</stamp>
		<duration>32 s </duration>
		<project>Lame Project</project>
		<title>Build 1.X</title>
		<stamp>1.0.0 [18]</stamp>
		<duration>27 s </duration>

AntHill Pro

In AHP, create a Template Report with the following contents:

Meta-Data Script

import com.urbancode.anthill3.domain.reporting.*;
import java.text.*;
import java.util.*;

ReportMetaData rmd = new ReportMetaData();


return rmd;

Report Script

This report script gets the latest build (successful or not) of each workflow that has a property “radiate” set to “true”. It will skip any project that doesn’t have this property set or doesn’t have it set to “true”.

import com.urbancode.anthill3.domain.reporting.*;
import com.urbancode.anthill3.domain.project.*;
import com.urbancode.anthill3.domain.workflow.*;
import com.urbancode.anthill3.domain.project.prop.ProjectProperty;
import com.urbancode.anthill3.domain.property.Property;
import com.urbancode.anthill3.domain.summary.buildworkflow.*;

ReportOutput output = new ReportOutput(metaData);

Project[] projects = ProjectFactory.getInstance().restoreAll();

for (int i = 0; i < projects.length; i++) {

	Project project = projects[i];

	if (project.getProperty("radiate") != null) {
		if (project.getProperty("radiate").getValue().equals("true")) {
			Workflow[] workflows = project.getOriginatingWorkflowArray();

			for (int j = 0; j < workflows.length; j++) {
				Workflow workflow = workflows[j];
				BuildWorkflowSummary bws = BuildWorkflowSummaryFactory.getInstance().restoreLatestBuildWorkflowSummaryForProfile(workflow.getBuildProfile().getId());

				if (bws != null) {
					ReportRow row = new ReportRow(output, "Environment");
					row.setColumnValue("project", project.getName());
					row.setColumnValue("title", workflow.getName());
					row.setColumnValue("stamp", bws.getLatestStamp());
					row.setColumnValue("buildlifeid", bws.getBuildLifeId().toString());
					row.setColumnValue("duration", bws.getDuration());
					row.setColumnValue("changecount", bws.getNumberOfChanges().toString());
					if (bws.getStatus().isSuccess()) {
						row.setColumnValue("status", "success");
					} else {
						row.setColumnValue("status", "failure");