Making Packages



As part of the 1.4.4 release the concept of packages was introduced to the web dashboard. A package is a ZIP file that contains all the necessary files for a plug-in, plus instructions on installing the files.

Examples of files that can be in a package are:
  • NVelocity templates
  • XSL-T definitions
  • Images
  • Javascript
  • Binaries

As well as the content files, every package must contain a manifest file. This file contains the instructions for how to install the package. Generally a manifest will contain two sections: where to copy the files and the configuration changes to make.

Writing a Manifest

A manifest consists of three parts:
  1. Information about the package
  2. Included files and their destination
  3. Configuration changes

Package Information

The package information consists of a name, description and type. These are displayed in the admin plug-in to provide additional details on package.


2   <name>Package name</name>
3   <description>Package description</description>
4   <type>Plugin</type>
5   <!-- Other elements omitted -->


Element Description Type Required
name The name of the package. string Yes
description A description of the package and what it contains. string No
type The type of contents of the package. Currently this is only for informational purposes. enum
* Plugin
* Theme

Included Files

The ZIP file can contain one or more files that need to be copied to the dashboard. This section in the manifest provides the instructions to where to copy the folders.

Note:_ The ZIP file can contain files that are not referenced by the manifest. If there are non-referenced files, they will be ignored (i.e. not installed).


 2   <folders>
 3      <folder>
 4         <location>relativePath</location>
 5         <files>
 6            <file>nameInPackage</file>
 7         </files>
 8      </folder>
 9   </folders>
10   <!-- Other elements omitted -->


Element Description Type Required
folders Root element for the file references. container Yes
folder Defines a folder. Each file to be copied must be copied to a folder (files can be copied to multiple folders). This element defines the target folder for one or more files. There can be multiple folder elements under a folders element. \\ Note:_ Unlike a file system, this element cannot contain sub-folders. If sub-folders are required, they must have their own folder element. container No
location The location of the folder. Each folder must be a relative path. If the folder does not exist, then it will be created automatically by the installation process. string Yes
files The files to be copied into the folder. container No
file The name of the file to be copied. This must be the name of the file within the package, the target file will have the same file name. There can be multiple file elements under a files element. string No


The final section of the manifest contains the configuration elements to add.


 2   <configuration>
 3      <setting>
 4         <path>xPath</path>
 5         <name>settingName</name>
 6         <filter>xPathFilter</filter>
 7         <value>configValue</value>
 8         <attributes>
 9            <attribute name="attribName" value="attribValue" />
10         </attributes>
11      </setting>
12   </configuration>
13   <!-- Other elements omitted -->


Element Description Type Required
configuration The root element for the configuration. container Yes
setting A configuration setting. This will map to a single configuration element in dashboard.config. \\
There can be multiple setting elements under a configuration element.
container No
path An XPath statement to locate the configuration setting. This will be used to find the parent of the setting. string Yes
name The name of the configuration element. This is the name of the element that will be added to dashboard.config. string Yes
filter An optional filter to find an existing occurrence of the element. This is needed for elements that can have the same name (e.g. xslReportBuildPlugin, xslFile, etc.) Otherwise it is assumed that there will only be one element with the name in the parent. \\
If used, this is a standard XPath where statement (i.e. the value between \[ and \]).
string No
value The value to set. string No
attributes The root element for the attribute definitions. container No
attribute An attribute to add to the element. There can be multiple attribute elements under the attributes element. This element has two required attributes:
* name: the name of the attribute
* value: the value to set for the attribute 
element No

Testing a Package

Currently the only way to test a package and ensure that it works is to install it.

Note:_ Before installing, make sure you back up dashboard.config and any other important files. Alternately use a fresh install of the web dashboard.

Once the package has been built (including the manifest), go to the administrative plug-in and attempt to load and install the plug-in. If the plug-in installs without any problem, check the log to ensure everything occurred as planned. Then check to make sure the packaged contents are working as expected.

Finally, try to uninstall the package. In theory a package should cleanly uninstall, reverting the dashboard back to its previous state. However, in reality all an uninstall does is remove the new entries (either files or configuration settings or both.)

Including a Package in the Build

This section covers the process to add a new package to the CruiseControl.NET distribution. If the package will be distributed by an alternate route, then this section is not relevant.

Since the package will contain files that are normally included in the dashboard, there is no point in building the packages independently. Instead the best approach is to modify the build script to also generate the package.

To modify the script for a new package, use the following steps:
  1. Under the packages folder in the dashboard project add a folder for the new package
  2. Add an XML called Manifest.xml to this folder
  3. Add the configuration details (as above) to this file and save it
  4. Open and add a target for the new package
  5. In this target, use the <zip> command to compress all the required files (including the manifest)
  6. The <zip> command should output the file to $\{build.dir\}\WebDashboard\Packages folder
  7. Include the new target name in the depends attribute of the "build.packages" target
  8. Save the file and test the build

To modify an existing package just apply the relevant steps from the above process.

The following is an example of a target for generating a package:

 1<target name="build.serverLog.package" description="Generates the server log package">
 2  <mkdir dir="${build.dir}\WebDashboard\Packages\" verbose="${verbosity}"/>
 3  <zip zipfile="${build.dir}\WebDashboard\Packages\">
 4    <fileset basedir="${src.dir}\WebDashboard\Packages\ServerLog">
 5      <include name="*.*"/>
 6    </fileset>
 7    <fileset basedir="${src.dir}\WebDashboard\Templates">
 8      <include name="ServerLog.vm"/>
 9    </fileset>
10  </zip>

Make sure the relevant files are checked into source control, otherwise the package will build incorrectly.

Update packages.xml

Adjust project\WebDashboard\packages\packages.xml so that it knows about the new package.
The zip file name is the one specified in the build script.
Also make sure that the names are the same in the manifest files as in the packages.xml file. (attribute name)
The description attribute of packages.xml is used in the dashboard, not the description of the manifest file.
When changes are done to dashboard.config, standard inclusion of a package, be sure to set the installed to yes in this file.


The following are examples of manifest that have already been written:

Queue Status Display

This is a very simple package. It contains a single template (ServerQueueStatus.vm) and a single configuration change (adds the plug-in to the server plug-in list).

 2  <name>Queue Status Display</name>
 3  <description>Display the status of the queues.</description>
 4  <type>Plugin</type>
 5  <folders>
 6    <folder>
 7      <location>Templates</location>
 8      <files>
 9        <file>ServerQueueStatus.vm</file>
10      </files>
11    </folder>
12  </folders>
13  <configuration>
14    <setting>
15      <path>/dashboard/plugins/serverPlugins</path>
16      <name>queueStatusServerPlugin</name>
17    </setting>
18  </configuration>

Modification History

This example shows that a package does not always need to include files. Instead the package can just define configuration changes. In this example the manifest defines a single new plug-in.

 2  <name>Modification History</name>
 3  <description>Modification history for a project.</description>
 4  <type>Plugin</type>
 5  <folders />
 6  <configuration>
 7    <setting>
 8      <path>/dashboard/plugins/projectPlugins</path>
 9      <name>modificationHistoryProjectPlugin</name>
10    </setting>
11  </configuration>

NDepend Results

In this example, the package contains a single file that is used in multiple places. Additionally, the configuration changes involve both a filter and multiple attributes. The filter condition on each setting allows the installer to identify which element to modify out of several possibilities.

 2  <name>NDepend Results</name>
 3  <description>Display the results of a NDepend run.</description>
 4  <type>Plugin</type>
 5  <folders>
 6    <folder>
 7      <location>Xsl</location>
 8      <files>
 9        <file>ndependreport-ccnet.v2.xsl</file>
10      </files>
11    </folder>
12  </folders>
13  <configuration>
14    <setting>
15      <path>/dashboard/plugins/buildPlugins/buildReportBuildPlugin/xslFileNames</path>
16      <filter>.='xsl\ndependreport-ccnet.v2.xsl'</filter>
17      <name>xslFile</name>
18      <value>xsl\ndependreport-ccnet.v2.xsl</value>
19    </setting>
20    <setting>
21      <path>/dashboard/plugins/buildPlugins</path>
22      <filter>@xslFileName='xsl\ndependreport-ccnet.v2.xsl'</filter>
23      <name>xslReportBuildPlugin</name>
24      <attributes>
25        <attribute name="description" value="NDepend Details"/>
26        <attribute name="actionName" value="NDependDetailsBuildReport"/>
27        <attribute name="xslFileName" value="xsl\ndependreport-ccnet.v2.xsl"/>
28      </attributes>
29    </setting>
30  </configuration>

NUnit Results

This is a fairly complex example. Not only does it make multiple configuration changes, it also installs multiple files (although all to the same place). Again, the settings use filters to correctly identify the right element to modify and some of the settings have multiple attributes.

 2  <name>NUnit Results</name>
 3  <description>Display the results of a NUnit run.</description>
 4  <type>Plugin</type>
 5  <folders>
 6    <folder>
 7      <location>Xsl</location>
 8      <files>
 9        <file>unittests.xsl</file>
10        <file>tests.xsl</file>
11        <file>timing.xsl</file>
12      </files>
13    </folder>
14  </folders>
15  <configuration>
16    <setting>
17      <path>/dashboard/plugins/buildPlugins/buildReportBuildPlugin/xslFileNames</path>
18      <filter>.='xsl\unittests.xsl'</filter>
19      <name>xslFile</name>
20      <value>xsl\unittests.xsl</value>
21    </setting>
22    <setting>
23      <path>/dashboard/plugins/buildPlugins</path>
24      <filter>@xslFileName='xsl\tests.xsl'</filter>
25      <name>xslReportBuildPlugin</name>
26      <attributes>
27        <attribute name="description" value="NUnit Details"/>
28        <attribute name="actionName" value="NUnitDetailsBuildReport"/>
29        <attribute name="xslFileName" value="xsl\tests.xsl"/>
30      </attributes>
31    </setting>
32    <setting>
33      <path>/dashboard/plugins/buildPlugins</path>
34      <filter>@xslFileName='xsl\timing.xsl'</filter>
35      <name>xslReportBuildPlugin</name>
36      <attributes>
37        <attribute name="description" value="NUnit Timings"/>
38        <attribute name="actionName" value="NUnitTimingsBuildReport"/>
39        <attribute name="xslFileName" value="xsl\timing.xsl"/>
40      </attributes>
41    </setting>
42  </configuration>