Multiple Project Summary Reporting Standard - cctray xml feed

CCTray.xml is an RSS-like CI server build status xml feed, which is originally developed for CruiseControl.net.
ThoughtWorks declared it in a standard called “Multiple Project Summary Reporting Standard”, which now have become some kind of unofficial standard of CI server feed that is widely supported by all kind of popular CI servers.

You can find the feed as described below:

And according to cc_dashboard, there are some exceptions that are not included in the document.

  • An additional “Pending” activity
  • An additional “Unknown” status. I’ve seen Unknown reported by CruiseControl.rb when project builds are serialized (“Configuration.serialize_builds = true” set in .cruise/site_config.rb) and one build is waiting for another build to finish. I’ve seen Unknown reported by Hudson when a project is disabled.

The following is a patched version of Multiple Project Summary Reporting Standard.

Multiple Project Summary Reporting Standard

Introduction

Various Continuous Integration monitoring / reporting tools exist. Examples are:

These tools work by polling Continuous Integration servers for summary information and presenting it appropriately to users.

If a Continuous Integration server can offer a standard summary format, and a reporting tool can consume the same, then we get interoperability between reporting tools and CI Servers.

Description

Summary information will be available as a plain XML string retrievable through an http GET request.

The format of the XML will be as follows:

Summary

A single node, the document root, which contains 0 or many node.

Each may have the following attributes:






































































































name description type required
name The name of the project string yes
activity The current state of the project string enum : Sleeping, Building, CheckingModifications
yes
lastBuildStatus A brief description of the last build string enum : Pending, Success, Failure, Exception, Unknown yes
lastBuildLabel A referential name for the last build string no
lastBuildTime When the last build occurred DateTime yes
nextBuildTime When the next build is scheduled to occur (or when the next check to see whether a build should be performed is scheduled to occur) DateTime no
webUrl A URL for where more detail can be found about this project string (URL) yes

Clients that consume this XML should not rely on any optional attribute being present, and should degrade their functionality gracefully.

Example

CCTray.xml Sample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<Projects>
<Project
name="SvnTest"
activity="Sleeping"
lastBuildStatus="Exception"
lastBuildLabel="8"
lastBuildTime="2005-09-28T10:30:34.6362160+01:00"
nextBuildTime="2005-10-04T14:31:52.4509248+01:00"
webUrl="http://mrtickle/ccnet/"/>
<Project
name="HelloWorld"
activity="Sleeping"
lastBuildStatus="Success"
lastBuildLabel="13"
lastBuildTime="2005-09-15T17:33:07.6447696+01:00"
nextBuildTime="2005-10-04T14:31:51.7799600+01:00"
webUrl="http://mrtickle/ccnet/"/>
</Projects>

Schema

cctray.xml Schema
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Projects">
<xs:complexType>
<xs:sequence>
<xs:element name="Project" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="activity" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="Sleeping" />
<xs:enumeration value="Building" />
<xs:enumeration value="CheckingModifications" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="lastBuildStatus" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="pending"/>
<xs:enumeration value="Exception"/>
<xs:enumeration value="Success"/>
<xs:enumeration value="Failure"/>
<xs:enumeration value="Unknown"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="lastBuildLabel" type="xs:NMTOKEN" use="required" />
<xs:attribute name="lastBuildTime" type="xs:dateTime" use="required" />
<xs:attribute name="nextBuildTime" type="xs:dateTime" use="optional" />
<xs:attribute name="webUrl" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Powershell Script for Environment Provision and Auto Deploy

I’ve been working on MetaPaas project for a while. And composing deploy script is one of the my major tasks.
Here are some script snippets I found or I compose, which could be very useful in my daily work.

Download File from Web

This piece of script is useful when the script need to download package from CI server or configuration from configuration server etc.
Especially when wget or curl available.

NOTICE: This piece of script enable you to download the file from web in Powershell without any 3rd party dependences. But its performance is not as good as wget. Wget is still recommended if there are quite a lot of files to be downloaded.

Original Source

Get-WebFile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
## Get-WebFile (aka wget for PowerShell)
##############################################################################################################
## Downloads a file or page from the web
## History:
## v3.6 - Add -Passthru switch to output TEXT files
## v3.5 - Add -Quiet switch to turn off the progress reports ...
## v3.4 - Add progress report for files which don't report size
## v3.3 - Add progress report for files which report their size
## v3.2 - Use the pure Stream object because StreamWriter is based on TextWriter:
## it was messing up binary files, and making mistakes with extended characters in text
## v3.1 - Unwrap the filename when it has quotes around it
## v3 - rewritten completely using HttpWebRequest + HttpWebResponse to figure out the file name, if possible
## v2 - adds a ton of parsing to make the output pretty
## added measuring the scripts involved in the command, (uses Tokenizer)
##############################################################################################################
function Get-WebFile {
param(
$url = (Read-Host "The URL to download"),
$fileName = $null,
[switch]$Passthru,
[switch]$quiet
)
$req = [System.Net.HttpWebRequest]::Create($url);
$res = $req.GetResponse();
if($fileName -and !(Split-Path $fileName)) {
$fileName = Join-Path (Get-Location -PSProvider "FileSystem") $fileName
}
elseif((!$Passthru -and ($fileName -eq $null)) -or (($fileName -ne $null) -and (Test-Path -PathType "Container" $fileName)))
{
[string]$fileName = ([regex]'(?i)filename=(.*)$').Match($res.Headers["Content-Disposition"] ).Groups[1].Value
$fileName = $fileName.trim("\/""'")
if(!$fileName) {
$fileName = $res.ResponseUri.Segments[-1]
$fileName = $fileName.trim("\/")
if(!$fileName) {
$fileName = Read-Host "Please provide a file name"
}
$fileName = $fileName.trim("\/")
if(!([IO.FileInfo]$fileName).Extension) {
$fileName = $fileName + "." + $res.ContentType.Split(";")[0].Split("/")[1]
}
}
$fileName = Join-Path (Get-Location -PSProvider "FileSystem") $fileName
}
if($Passthru) {
$encoding = [System.Text.Encoding]::GetEncoding($res.CharacterSet )
[string]$output = ""
}
if($res.StatusCode -eq 200) {
[int]$goal = $res.ContentLength
$reader = $res.GetResponseStream()
if($fileName) {
$writer = new-object System.IO.FileStream $fileName, "Create"
}
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$count = 0
do
{
$count = $reader.Read($buffer, 0, $buffer.Length);
if($fileName) {
$writer.Write($buffer, 0, $count);
}
if($Passthru){
$output += $encoding.GetString($buffer,0,$count)
} elseif(!$quiet) {
$total += $count
if($goal -gt 0) {
Write-Progress "Downloading $url" "Saving $total of $goal" -id 0 -percentComplete (($total/$goal)*100)
} else {
Write-Progress "Downloading $url" "Saving $total bytes..." -id 0
}
}
} while ($count -gt 0)
$reader.Close()
if($fileName) {
$writer.Flush()
$writer.Close()
}
if($Passthru){
$output
}
}
$res.Close();
if($fileName) {
ls $fileName
}
}

Extract File with Windows Explorer

This piece of code enable you to extract zip package without any 3rd party dependencies. It is useful environment provision script, which is usually executed on a Windows without anything being installed.

Extract-Zip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function Extract-Zip ([string] $zipPath, [string]$destination) {
$progressbar = 4
$shellApplication = New-Object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipPath)
$destinationFolderName = Join-Path $destination "tiger"
if (Test-Path $destinationFolderName ) {
Remove-Item $destinationFolderName -Recurse -Force
}
New-Item $destinationFolderName -type directory
$destinationFolder = $shellApplication.NameSpace($destinationFolderName)
$destinationFolder.CopyHere($zipPackage.Items(), $progressbar)
}

Interpolate value into configuration

This piece of script enable you to replace the place-holders in configuration text with actual values.

Apply-Config
1
2
3
4
5
6
7
8
9
10
Function Apply-Config([hashtable]$config) {
foreach($line in $input) {
foreach($key in $config.Keys) {
$line = $line -replace $key, $config[$key]
}
$line
}
}

This piece of script can be used in different scenarios:

Prepare Configuration

Config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$configuration = @{
"initialCatalog" = "lion"
"logInitialCatalog" = "lion_log"
"webServers" = @("192.168.122.46")
"dbServer" = "192.168.122.65"
"SQLServerDataDir" = "C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA"
"SQLServerDataFileSize" = "10MB"
"dataset" = "prod"
"appPoolUser" = "$($env:COMPUTERNAME)\Lion"
"appPoolPassword" = "1zhlmcl..oostp"
"createAppPoolUser" = $true
}

Apply config to in-memory configuration template

Apply config to string in memory
1
2
3
$configurationText = $configurationTemplate | Apply-Config($configuration)

Create configuration file according to template

Apply config to file
1
2
3
cat $configurationTemplateFile | Apply-Config($configuration) > $configurationFile

Download and apply configuration from configuration server

Download and apply config
1
2
3
Get-WebFile -url $configTemplateUrl -Passthru | Apply-Config($configuration) > $configurationFile