Disclaimer
First a word of warning. I am not an employee of Telelogic, nor have I received any formal training with these tools. All of my knowledge comes from hard-fought experience. The concepts I present here are not necessarily the absolute truth. They represent how things have seemed to work for me in practice and in a real world environment - sometimes overly simplified to attempt to ease understanding. I offer no warranty, expressed or implied, as to the accuracy of this information. I take no responsibility for any damages that may result from the use of this information. Use at your own risk.
Introduction
As with most things in life, there are many ways to accomplish the same task. This page will attempt to document my own experiences using Cruise Control with Telelogic's CM Synergy, and what has worked well for me. Please feel free to add your own thoughts and experiences.
If you are new to CM Synergy, it might not be a bad idea to browse through the CMSynergyConcepts page to brush up on the basic concepts behind the tool. If the contents of that page sound like Greek to you, please stop now, get your hands on the Telelogic documentation, and spend some quality time experimenting with the tool. CM Synergy has a pretty steep learning curve, and you really don't want to start automating CM activities without a thorough understanding of what is going on behind the scenes.
Still with us? Then let's get started!
The Goal
The benefits of continuous integration are well known. However, my primary reason for using Cruise Control is to distribute reliable code to various development teams as quickly as possible, and this priority will no doubt be reflected throughout this document.
In my experience, development efforts are generally broken down into teams working with a common technology, or on a common subcomponent of a product. There are generally many dependencies among these teams, where one or more teams depend upon the software created by another.
Over the years, I have found that the majority of my Configuration Management efforts have been spent trying to understand and manage these dependencies - to ensure that every developer has what they need to accomplish their work as quickly as possible, without having to worry about anything beyond the scope of that work. They can rest assured that they will always be using the correct version of every library. The same version as everyone else on the project.
How can this be accomplished? Through continuous integration. Please read on.
Designing your Project Hierarchy
Perhaps the most critical aspect of a successful integration with Cruise Control is how you choose to lay out your projects.
 | Best Practices
- Create a project hierarchy which allows you to check out and build at any meaningful level.
- Use "container projects" to group individual projects into logical components of the system.
- Know your tools, know your constraints.
|
CM Synergy allows you to link one project within another. You should take advantage of this fact by creating a project hierarchy which represents the real world organization of the software you produce.
Note: The Telelogic Build Managers Guide presents the idea of using "external" projects to expose the API of one project to another. In my experience, this really only works if you are in an all-Unix environment, and the projects involved are very loosely coupled. I do not recommend taking that approach.
Take a moment to think about the different development teams in your own company. How closely linked are they? Do you build software for each team, or do you build for several teams at the same time? Now think in terms of CM Synergy projects. At what level is it meaningful to say "these projects make up component X"?
For this example, I'm going to use a J2EE development effort. Let's imagine that we have four development teams:
- The Common API Team is responsible for developing the architectural foundation of the product - a set of utility jars and ejbs used throughout the product.
- The Business Team is responsible for the bulk of the business logic.
- The Web Team would develop the web interface into the product.
- The Legacy Team maintains a legacy COBOL based system. They must work with the both the business logic and web teams to provide an integration into the new system.
In this case, our team dependencies would look something like this:
Looking at this diagram, it would seem natural to create one CM Synergy project for each of these teams, and that's not a bad place to start. However, we must also consider the practical implications of the tools we will be using.
On this project, our Java developers will be using IBM's Websphere Studio Application Developer (WSAD) IDE for development. The CM Synergy integration into this product demands that there be a 1:1 mapping between WSAD projects and CM Synergy projects. Additionally WSAD itself demands that there be exactly one product produced by each project. This means that each target within WSAD - utility jars, ejbs, web apps, ears, etc. - will need its own CM Synergy project. That can mean a lot of projects.
Does this mean that we should have an instance of a Cruise Control project for each and every CM Synergy project? Absolutely not! We must consider at what level it makes sense to call a group of CM Synergy projects a "component" of the system, and at what level it makes sense to build and integrate these components using Cruise Control.
Okay. So far we know that we will need several projects - one for each J2EE target. We also know that each development team will have their own set of these projects, and won't be concerned with the code contained in the projects of other teams. We can begin to imagine a CM Synergy project hierarchy such as the following. Note that names in [italics] represent CM Synergy projects.
This looks pretty good, and we could almost imagine adding build scripts to these 4 top level projects, creating an entry in our Cruise Control config file for each one, and calling it a day. In the real world, however, it's never quite that simple.
Notice how each of the 3 J2EE top level projects contain *_test_war and *_test_ear sub-projects? These allow the individual teams to test their code outside the system as a whole, and tell us that they are a part of something bigger. Clearly none of these three projects can stand alone in any meaningful way. In a situation like this, we would want to create a "container project" which would encompass all of the J2EE projects and provide a convenient entry point for the build. But what if we want to build and deploy the entire product from end to end? You guessed it, we would simply add one final container project to encompass the entire system. Our final structure, then, would look something like this:
Mapping CM Synergy Projects to Cruise Control Projects
Now that we have our project layout defined, how do we map these projects into Cruise Control?
The bad news is that there is no certain answer to this question. The good news is that by laying our projects out in a hierarchical fashion, we have given ourselves a lot of flexibility.
An argument could be made for creating a Cruise Control project to build and integrate any and all of the CM Synergy projects denoted with a colored font in the previous diagram. How do we choose? It's all a matter of time and risk. The projects in red signify the most risk, while the top level project (in green) signifies the least.
Remember, our primary goal is to get new code to the developers as quickly as possible. We would also like to ensure that the new code is reliable. What do we mean by reliable? Well, that is a matter for discussion.
Let's face it, it's probably not practical to run a continuous build and test for the entire product. On the other hand, it really wouldn't do us much good to run a continuous build and test at too low a level either.
Imagine if we were to define a Cruise Control project for each of the three CM Synergy J2EE container projects - common, business, and web. Now, imagine that a developer checks in a task which affects one of the subprojects of common. Cruise Control detects the change, and fires off a build of the common project. The build succeeds, all unit tests pass, and the change is made available to developers (more on how this is done later). Suddenly, every developer on the business and web team finds that their build is broken! The change made to common is not compatible with the code further upstream. While it is certainly true that finding such problems quickly is a desirable aspect of continuous integration, it is certainly not true that development should have to come to a halt to achieve this.
Let's try another approach. What if we were to define a Cruise Control project at the level of the CM Synergy j2ee project (the project called j2ee)? Our developer again submits her task. The build is again fired off. This time, however, the build will fail while attempting to compile the code in one of the business subprojects. The build failure is published, and everyone is made aware of the problem. However, in this case the change is not made available to other developers, so everyone else can continue to work uninterrupted.
 | Best Practices
- Build and integrate at the highest possible level which will allow new code to be made available to developers in an acceptable amount of time and with an acceptable amount of risk.
|
This definitely seems the better approach. But what if the j2ee project was
much larger. What if it contained a hundred subprojects? This would certainly make it impractical to run a continuous build and test cycle at this level. Wouldn't it?
In my own experience, builds can be expensive - but running tests can be very expensive. Fortunately, Cruise Control provides us with a lot of flexibility in that regard. Here is where we can compromise on our definition of reliable code. We could, for example, schedule a continuous build which only compiles the code - skipping all tests. This would allow us to integrate at the desired level while ensuring that, at the very least, the build will always work for each developer - unless, of course, they broke it themselves!
For safety's sake we could also schedule the tests to run at less frequent intervals - say three or four times a day.
What about the legacy project? Because no other project depends upon it (from a code dependency perspective) I would argue that it should receive its own Cruise Control project.
Of course, this would mean that there is no level of automated integration which could catch a problem with the interface between the J2EE applications and the legacy applications. There are a few ways in which we might mitigate that risk.
- We could depend on the J2EE developers to conscientiously test their code against the latest version of the legacy application.
- If we provide a drop (release) to our Quality Assurance group frequently enough, we can rely on them to discover such problems.
- We could create an automated smoke test for the end to end system. In this case we would add the tests to the top level CM Synergy project, and define a Cruise Control project which would build, deploy, and test at the product level. This is bound to be expensive, and would probably only run nightly, or perhaps even less frequently.
Clearly number three would be the best solution, but in my experience very few companies actually achieve this level of automation. If yours does, give youself a well deserved pat on the back!
Let's assume that our example company is really on the ball and has managed to create an end to end, automated, test. This gives us three Cruise Control projects in total.
So far we have only the bare skeleton of a configuration file:
<cruisecontrol>
<project name="legacy">
<!-- Do legacy stuff here -->
</project>
<project name="j2ee">
<!-- Do j2ee stuff here -->
</project>
<project name="product">
<!-- Do end to end product stuff here -->
</project>
</cruisecontrol>
CM Synergy Projects and Release Values
Now that we have our CM Synergy projects mapped out, and have decided at what levels we will be running our Cruise Control builds, it's time to throw another wrench into the works.
As we read on the CMSynergyConcepts page, the reconfigure process depends upon several things:
- The baseline project version
- The release value of the project version
- The contents of the folders within the project version's reconfigure properties
If you are using reconfigure templates to generate your reconfigure properties (and I have never worked in an environment where this was not the case), then all projects which share the same purpose and are targeted to the same release will have an identical list of tasks in their reconfigure properties. This has some implications when it comes to integrating with Cruise Control.
Let's consider another example. Imagine that all of our projects are targeted to the same release, and therefore have identical reconfigure properties. Just to be clear, let's assume that we are running Cruise Control against a set of project versions which were checked out for the purpose of "Integration Testing", are targeted to release "product/1.0", and contain a folder which queries for "All completed tasks targeted to release product/1.0".
Now imagine that a developer checks in a task which fixes a bug within the legacy project. Unfortunately, CM Synergy doesn't know that the task only affects the legacy project. It is only concerned with its release value. Because the task is now in the reconfigure properties of all of our project versions, Cruise Control will detect the change in both the legacy and j2ee projects, and both builds will be launched!
Now, fast forward a bit and imagine what would happen when both builds complete successfully. Several times in the previous section I have mentioned "making changes available to developers". In CM Synergy, this is typically accomplished in one of two ways
- The new tasks are copied into a shared folder, which is included in the reconfigure properties of each developer's project version.
- An intermediate baseline is created (only supported in version 6.3 and later).
There are publishers available to handle both of these scenarios, and we will cover them in more detail later. For now, let's concentrate on what this means for our project hierarchy.
If we were using the CMSynergyTaskPublisher, each build stream would attempt to copy the same tasks into the same folder. Fortunately for us, no harm would be done. It would simply be a wasted effort.
If, on the other hand, we were using the CMSynergyBaselinePublisher, things are a bit worse. Each build would produce a new intermediate baseline which includes only the projects at and below the level of the build. However, CM Synergy expects a baseline to encompass all projects which are targeted to the same release. While it is not illegal to baseline only a subset of projects, the fact that a different set of baselines exist for different projects within the same release could very well cause some troubles with the algorithm used by the newer versions of CM Synergy to select the appropriate baseline for a project. Developers are bound to get some frightening warning messages when reconfiguring projects, and you are bound to get some phone calls.
The moral of this section is that, when running Cruise Control builds on CM Synergy projects at the same level within the project hierarchy, those projects should follow different loadlines - in other words, they should target different releases. If you picked your Cruise Control to CM Synergy project mappings carefully, you should notice that this dividing line falls on a logical separation of components and/or technologies within the product and seems perfectly natural.
Let's have another look at our hypothetical project hierarchy - this time including the release values.
Details, Details...
Before we take a look at how to configure our CM Synergy plugins, we should really go over a few of the technical details of using the CM Synergy plugins with Cruise Control.
Dealing with Version Delimiters
Each CM Synergy database defines a special character to be used as a version delimiter. This character is used when specifying objects in two or four part name format (name<delimiter>version, and name<delimiter>version:type:instance respectively).
 | Use That Two part name!
All of the CM Synergy plugins for Cruise Control expect projects to be specified using their two part names. |
Telelogic, for whatever reason, has decided to make the dash ("-") character the default version delimiter. I have never come across an installation where this was not changed. In my experience, the two most popular choices are the tilda ("
") and the pound ("#"). Throughout this document, I will use the tilde ("") character as the version delimiter - simply because this is my favorite choice.
If you are not certain what delimiter your database uses, simply run the "ccm delimiter" command to find out.
CM Synergy Roles
While it is certainly possible for any CM Synergy user to set up a continuous build using Cruise Control, this document deals with continuous integration. The goal here is not only to build the software, but also to deliver the changes to development teams on an ongoing basis. For this you will need permissions to either:
- Add tasks to a shared folder used in the reconfigure properties of the developer's projects.
- Create an intermediate baseline of the affected projects.
I'm not going to go into the intimate details of security within CM Synergy. I'm simply going to assume for the remainder of this document that we will be running Cruise Control as a user who has been granted the "build_mgr" role within CM Synergy, and that we have started our CM Synergy sessions using that role. If this is not the case for you, you will need to do a bit of reading up and, probably, some negotiating with your CM team to set things up for your specific needs.
Hint: Shared folders can be setup to be writable by any user. Custom project purposes can be created to use reconfigure templates which include custom folder templates (to collect the appropriate tasks from developers). I'll say no more.
CM Synergy Project Purposes
The standard way to integrate software using CM Synergy is to check out a set of projects with the "Integration Testing" purpose. This should, by default, use a reconfigure template which will result in a very special folder being added to the reconfigure properties of each newly created project version. This folder is associated with a query which will automatically add all tasks which are checked in with the same release value as the project version itself.
If you do not use this strategy in your organization, then you must find a way to ensure that any tasks you want included in the build will make their way into some folder within the reconfigure properties of the CM Synergy project referenced by the Cruise Control plugins.
Checking Out your CM Synergy Projects
In order for Cruise Control to build your CM Synergy projects, you must actually have a set of CM Synergy project versions checked out. Pretty obvious and straight forward stuff, right? I just wanted to take a second to give you a couple of pointers which have saved me allot of grief over the years.
- Use a version name which is meaningful at a glance. When using CM Synergy, project versions tend to multiply like rabbits. This is especially true when making use of the new intermediate baseline feature. While Cruise Control could care less what version name you give to your integration testing projects, I would recommend using a naming schema which is easy to spot in a list. I like to use the release value of the project followed by "_int".
- When checking out projects on Windows platforms, always always always use relative work areas. You might not have thought about how you are going to lay out your build scripts yet, but when you do you'll thank me for this!
 | Working with Work Area Properties
When checking out CM Synergy projects, there is no need to use a work area location relative to your installation of Cruise Control. Our builders will automatically be given the absolute path to our project's work area. |
Keeping an Eye on Your CM Synergy Sessions
The <cmsynergysessionmonitor> listener will monitor and start CM Synergy sessions as needed. It is triggered with each build loop (before the bootstrappers are run) and can monitor any number of CM Synergy sessions. The <cmsynergysessionmonitor> also provides a mapping between a simple "nick-name" for a session (which will be used by the other CM Synergy plugins) and the full CM Synergy session ID. This map is persisted in a simple properties file which I refer to in this document as the "session file".
Each time the <cmsynergysessionmonitor> runs, it will load the persisted information from the session file and attempt to verify that each monitored session is, in fact, still running. It does this according to the following rules:
- If the session file does not exist, it will be created.
- If an entry for the session name (nick-name) does not exist in the session file, a new CM Synergy session will be started and an entry recorded in the file.
- If an entry for the session name does exist in the file, it will check that the CM Synergy session ID associated with the session name is still running. If it is, no further action is taken. If it is not, a new CM Synergy session is started, and the new ID recorded in the file.
Within the listener, this process of reading this file, checking the sessions, starting any new sessions, and updating the file is atomic, and the code used to perform this operation is synchronized. In other words, you may use as many build threads as you like without worry. (At least this is true in my test environment. If you are using multiple build threads and notice any strange behavior, please let me know.)
Although you should never have to maintain the session file manually, it is worth having a quick look at its format. In this example "legacy_session" would be a session name, while "server:55647:192.168.1.117" would be the corresponding session ID
#CM Synergy session map
#Fri May 06 13:19:11 EDT 2005
legacy_session=server\:55647\:192.168.1.117
j2ee_session=server\:55692\:192.168.1.117
Let's run through the syntax of the listener:
ccmexe
By default, the plugin will search the system path for an executable called "ccm" (or "ccm.exe" for Windows). If you wish, you may override this by supplying the full path to the CM Synergy command line client here.
sessionfile
As mentioned above, this defaults to a file called ".ccmsessionmap" in your home directory. If you wish to override this, you may do so by setting this attribute.
Note: If you change the location of the file, you must remember to set the sessionfile attribute in each of the other CM Synergy plugins as well.
The <session> element
You must provide a <session> element for each CM Synergy session you wish to monitor. The session information may be provided in one of two ways.
- You may provide each individual attribute directly in the config file
- You may specify the name and an "attributefile" which contains the remainder of the required attributes. This allows you to place sensitive information - such as the password - into an external file with the appropriate permissions. The file referenced here should use the standard properties file format of "attribute=value" pairs.
Let's look at each attribute in turn:
|
name
This is the session name (or "nick-name") by which you will reference the session from the other CM Synergy plugins. This attribute is required, and must always be provided in the config file.
database
The CM Synergy database with which this session will communicate (e.g. /ccmdb/mydb). This attribute is required, and may be specified either in the config file, or in the attribute file.
role
The role under which the CM Synergy session will run (e.g. build_mgr). This attribute is required, and may be specified either in the config file, or in the attribute file.
user
The CM Synergy user account under which the session will run. This attribute is required, and may be specified either in the config file, or in the attribute file.
password
The password for the specified user. This attribute is required, and may be specified either in the config file, or in the attribute file.
host
If you wish the CM Synergy session to run on a host other than the current machine, you may set the host name here. This attribute is not required, and may be specified either in the config file, or in the attribute file.
attributefile
Sets the name of the properties file which will be read to set the <session> attributes. |
Example
Let's return to our fictitious company and have a look at how they would configure Cruise Control to monitor their CM Synergy sessions. For this example, I'm making the following assumptions:
- They are using a version delimiter of "~".
- They have checked out a series of CM Synergy projects for the purpose of "Integration Testing". They have given these projects version names made up of the release number of the project followed by "_int".
- They are using 2 CM Synergy sessions - one earmarked for the legacy project, the other for the j2ee project.
- They are using a single database located at /ccmdb/product.
For the sake of this example, we will use an attributefile to monitor one session, and simply provide all required attributes directly for the other. Notice that the "product" project does not contain a <cmsynergysessionmonitor> at all. This is because this project is intended to run only once per day. As such, our example company did not feel that it was necessary for it to have its own dedicated session. They have chosen to simply reuse one of the others.
Here is the attributefile we will use:
#CM Synergy session attributes
database=/ccmdb/product
role=build_mgr
user=buildmgr
password=P@ssW0rd!
And here is the full example:
<cruisecontrol>
<project name="legacy">
<listeners>
<cmsynergysessionmonitor>
<session name="legacy_session"
database="/ccmdb/product"
role="build_mgr"
user="buildmgr"
password="P@ssW0rd!"/>
</cmsynergysessionmonitor>
</listeners>
<!-- Do legacy stuff here -->
</project>
<project name="j2ee">
<cmsynergysessionmonitor>
<session name="j2ee_session"
attributefile="j2ee_session.properties"/>
</cmsynergysessionmonitor>
<!-- Do j2ee stuff here -->
</project>
<project name="product">
<!-- Do end to end product stuff here -->
</project>
</cruisecontrol>
Of course this is not the only way in which you can use the <cmsynergysessionmonitor>. If you are running CruiseControl in a very stable environment (i.e. your CM Synergy sessions rarely die), you may choose, instead, to create a seperate CruiseControl project whose sole purpose is to monitor your CM Synergy sessions. In this case you would add a <session> object for each and every session, and schedule the build loop to run on some regular interval.
Using the <cmsynergy> Sourcecontrol Plugin
The <cmsynergy> sourcecontrol plugin is used to detect changes within a CM Synergy project. More accurately, it queries for all tasks contained within all folders contained within a project's reconfigure properties which were checked in after the last build. Wow! That's quite a mouthful. You might want to read that last sentence again.
The plugin also has the ability to reconfigure the CM Synergy project (and all of its subprojects) if changes were detected.
Let's quickly run through the list of options. This information, along with a few additional examples, is also summarized on the configuration reference page.
project
This is the only mandatory attribute. You must supply the 2 part name of the CM Synergy project in which you wish to search for changes. The value you give here will be made available to the builders in the property "cc.ccm.project".
instance
Used to set the project's instance value. As CM Synergy only allows a single instance of a project object in any given database, this attribute defaults to "1", and should not need to be changed by most users. You might, however, need to set this value when using the DCM (Distributed Change Management) feature of the tool - which appends the DB name to the instance value.
ccmexe
By default, the plugin will search the system path for an executable called "ccm" (or "ccm.exe" for Windows). If you wish, you may override this by supplying the full path to the CM Synergy command line client here.
sessionfile
As discussed in the previous section, the session file is a simple properties file used to persist your CM Synergy session information. If this attribute is not set, it defaults to the file ".ccmsessionmap" in your home directory.
sessionname
The "nick-name" for the CM Synergy session you wish to use. This name must appear in the session file. If not set, the plugin will attempt to use the default (current) session as returned by the "ccm status" command. Regardless of whether or not you use this option, the actual CM Synergy session ID used will be passed to your builders in the property "cc.ccm.session".
ccmdateformat
The default (output) date format used by CM Synergy is "EEE MMM dd HH:mm:ss yyyy" If you have customized this for your installation, you must provide the correct format here. The format should follow the standard defined in Java's SimpleDateFormat class. If you have provided a date format here, it may be accessed from within your builders in the property "cc.ccm.dateformat".
updatefolders
By default, the plugin will always refresh the reconfigure properties of the given project before searching for changes. This allows any query based folders to update themselves with new tasks. If you wish to disable this feature (not recommended), you may set this attribute to false.
Note: It has been pointed out to me that this feature will only work with CM Synergy version 6.3 and above. If you are using an older version, you must set this option to false. In this case, you'll want to use the <cmsynergybootstrapper> as a workaround. Please see the next section for details.
reconfigure
Disabled by default. If you set this option to true, the project (and optionally any subprojects) will be automatically reconfigured when changes are detected. This eliminates the need to handle this from within your build scripts.
Note: In some rare instances, using this option can cause the project(s) to be reconfigured multiple times. This can happen when tasks are checked in during the "quiet time" as set in the Cruise Control config file. While harmless, this will increase the build time when it does occur.
recurse
Used in conjunction with the reconfigure option. If set to true, which is the default, all subprojects will also be reconfigured.
ignoreworkarea
By default, the plugin will query CM Synergy to determine the work area location of the project. This location is then passed to the builders in the property "cc.ccm.workarea". If you wish to disable this feature (not recommended), you can set this attribute to true.
changesynergyurl and ccmdb
These attributes should always be used together. If you are using Telelogic's Change Synergy for change management and/or defect tracking, then setting these attributes will create a hot link from the modifications section of the build results page directly into Change Synergy.
The changesynergyurl should be specified as the hostname and port number of the server (e.g. "http://192.168.1.17:8600").
The ccmdb should be specified as the absolute path to the appropriate database on your CM Synergy server (e.g. /ccmdb/mydb).
language and country
By default, the plugin will use the en_US locale when parsing the dates returned by CM Synergy. This allows you to use a non-English default locale for your JVM without conflicting with CM Synergy.
If you have a non English installation of CM Synergy (and please let me know if you do as I have never seen one, and am beginning to wonder if such a thing exists) you may override the locale used by the plugin by supplying the country and language attributes in ISO format.
property
Added for compliance with the CruiseControl API. A property of this name will be provided to the builders if any CM Synergy object has changed since the last build. The default is cc.ccm.haschanged, and probably shouldn't be altered.
Example
Let's return once more to our fictitious company and have a look at how they would configure Cruise Control to detect changes in their CM Synergy projects. For this example, I'm adding the following assumptions:
- Because there is no code dependency between the two projects, they would like the legacy and j2ee builds to proceed in parallel.
- They would prefer to allow the plugin to handle the reconfigure process for their CM Synergy projects, rather than dealing with this from within their build scripts.
Here is the config file. Notice that the <modificationset> tag used in the "product" project contains three entries. This is necessary to detect all possible changes. Also notice that these <cmsynergy> tags do not have the reconfigure attribute set to true (for clarification on one <cmsynergy> it is set to false). In order to avoid the cost of (potentially) reconfiguring the entire project hierarchy twice, our example company has decided to handle this one exception within their build script.
<cruisecontrol>
<system>
<configuration>
<!-- Allow up to two builds to run in parallel-->
<threads count="2"/>
</configuration>
</system>
<project name="legacy">
<listeners>
<cmsynergysessionmonitor>
<session name="legacy_session"
database="/ccmdb/product"
role="build_mgr"
user="buildmgr"
password="P@ssW0rd!"/>
</cmsynergysessionmonitor>
</listeners>
<modificationset quietperiod="120">
<cmsynergy project="legacy~1.0_int"
sessionname="legacy_session"
reconfigure="true"/>
</modificationset>
<!-- Do legacy stuff here -->
</project>
<project name="j2ee">
<listeners>
<cmsynergysessionmonitor>
<session name="j2ee_session"
attributefile="j2ee_session.properties"/>
</cmsynergysessionmonitor>
</listeners>
<modificationset quietperiod="120">
<cmsynergy project="j2ee~1.0_int"
sessionname="j2ee_session"
reconfigure="true"/>
</modificationset>
<!-- Do j2ee stuff here -->
</project>
<project name="product">
<modificationset quietperiod="120">
<cmsynergy project="product~1.0_int"
sessionname="legacy_session"
reconfigure="false"/> <!-- false is default -->
<cmsynergy project="legacy~1.0_int"
sessionname="legacy_session"/>
<cmsynergy project="j2ee~1.0_int"
sessionname="legacy_session"/>
</modificationset>
<!-- Do end to end product stuff here -->
</project>
</cruisecontrol>
Bootstrapping your CM Synergy projects
This probably seems like a strange place to introduce bootstrapping. A bit late in the game, you might say. Please let me explain. The <cmsynergybootstrapper> is really a holdover from the days before the "updatefolders" and "reconfigure" features were added to the <cmsynergy> plugin, and is rarely needed any longer - as you might have guessed from its complete absence thus far.
The <cmsynergybootstrapper> is used to reconfigure a project (and optionally all of its subprojects) before we check for modifications.
The one case where this comes in very handy is when you are using a version of CM Synergy prior to 6.3 (and thus cannot make use of the "updatefolders" option). In this situation, you will want to use the bootstapper to reconfigure only your top level projects (i.e. set the recurse attribute false). This allows your project's folders to be updated with the minimum of overhead.
The bootstrapper is quite simple. Let's run through its options:
project
This is the only mandatory attribute. You must supply the 2 part name of the CM Synergy project to reconfigure.
ccmexe
By default, the plugin will search the system path for an executable called "ccm" (or "ccm.exe" for Windows). If you wish, you may override this by supplying the full path to the CM Synergy command line client here.
sessionfile
As discussed in previous sections, the session file is a simple properties file used to persist your CM Synergy session information. If this attribute is not set, it defaults to the file ".ccmsessionmap" in your home directory.
sessionname
The "nick-name" for the CM Synergy session you wish to use. This name must appear in the session file. If not set, the plugin will attempt to use the default (current) session as returned by the "ccm status" command.
recurse
If set to true, which is the default, all subprojects will also be reconfigured.
Note: If you are using the bootstrapper simply to update your project's folders, be certain to set this attribute to false!
Example
Here is an example for all of our pre 6.3 users. Note that we have disabled the "updatefolders" option in the <cmsynergy> plugin.
<cruisecontrol>
<project name="j2ee">
<listeners>
<cmsynergysessionmonitor>
<session name="j2ee_session"
attributefile="j2ee_session.properties"/>
</cmsynergysessionmonitor>
</listeners>
<bootstrappers>
<cmsynergybootstrapper project="j2ee~1.0_int"
sessionname="j2ee_session"
recurse="false"/>
</bootstrappers>
<modificationset quietperiod="120">
<cmsynergy project="j2ee~1.0_int"
sessionname="j2ee_session"
updatefolders="false"
reconfigure="true"/>
</modificationset>
<!-- Do j2ee stuff here -->
</project>
</cruisecontrol>
Launching Builds from Cruise Control
While much of this topic is beyond the scope of this document, I wanted to cover some of the basics which are relevant to using CM Synergy with CruiseControl. My apologies to those of you who use Maven (or some other technology) to perform their builds. I'm only going to cover Ant here. Hopefully some of this information will still prove to be of use.
In addition to the standard properties passed to the builder by CruiseControl, the <cmsynergy> plugin provides us with several additional properties which can be put to use in our builds. Probably the most useful of these properties is the location of the project's work area, which we'll cover in a moment. Let's have a quick look:
| Property |
Description |
Always Defined? |
| cc.ccm.project |
The two part name of the project |
Yes |
| cc.ccm.dateformat |
The date format used to convert CM Synergy dates into Java dates |
Yes |
| cc.ccm.session |
The CM Synergy session ID used to check for modifications |
No. Only set if a session name was provided |
| cc.ccm.workarea |
The file system location of the CM Synergy work area for the project |
Yes, unless the ignoreworkarea was set |
| cc.ccm.haschanged (or the value specified by the property attribute) |
Set to true if any CM Synergy objects have changed since the last build |
No. Only set if at least one object has changed |
Of course, these properties only work within the builder - they cannot be used within the CruiseControl configuration file itself. In practical terms, this means that we will need to create a simple wrapper script between CruiseControl and our project's actual build script. This script should be placed into the same directory from which CruiseControl was launched.
The simplest possible script would be something like this, which will simply call the default target in the file called build.xml in the root directory of the project's work area. For more details on the use of the ant task, please see the Apache Ant website:
<project name="build-wrapper" default="launch">
<target name="launch">
<ant dir="${cc.ccm.workarea}"/>
</target>
</project>
Example
Let's return once more to our running example and add Ant builders to our projects. In this case, I am making the following assumptions:
- Each CM Synergy project which is mapped to a CruiseControl project (product, legacy, and j2ee) contains an Ant build script called build.xml in its root directory.
- Each of these build.xml files defines a default target which is an appropriate entry point for our CruiseControl build.
- The version of Ant that we will use is installed at /opt/apache-ant-1.6.2.
- The legacy and j2ee projects will run every 10 minutes, pausing long enough so as not to interfere with the full product build.
- The product project will run once daily at 10:00 p.m.
<cruisecontrol>
<system>
<configuration>
<!-- Allow up to two builds to run in parallel-->
<threads count="2"/>
</configuration>
</system>
<project name="legacy">
<listeners>
<cmsynergysessionmonitor>
<session name="legacy_session"
database="/ccmdb/product"
role="build_mgr"
user="buildmgr"
password="P@ssW0rd!"/>
</cmsynergysessionmonitor>
</listeners>
<modificationset quietperiod="120">
<cmsynergy project="legacy~1.0_int"
sessionname="legacy_session"
reconfigure="true"/>
</modificationset>
<schedule interval="10">
<pause starttime="2030" stoptime="2330"/>
<ant antscript="/opt/apache-ant-1.6.2/bin/ant"
buildfile="build-wrapper.xml"
uselogger="false"/>
</schedule>
</project>
<project name="j2ee">
<listeners>
<cmsynergysessionmonitor>
<session name="j2ee_session"
attributefile="j2ee_session.properties"/>
</cmsynergysessionmonitor>
</listeners>
<modificationset quietperiod="120">
<cmsynergy project="j2ee~1.0_int"
sessionname="j2ee_session"
reconfigure="true"/>
</modificationset>
<schedule interval="10">
<pause starttime="2030" stoptime="2330"/>
<ant antscript="/opt/apache-ant-1.6.2/bin/ant"
buildfile="build-wrapper.xml"
uselogger="false"/>
</schedule>
</project>
<project name="product">
<modificationset quietperiod="120">
<cmsynergy project="product~1.0_int"
sessionname="legacy_session"/>
<cmsynergy project="legacy~1.0_int"
sessionname="legacy_session"/>
<cmsynergy project="j2ee~1.0_int"
sessionname="legacy_session"/>
</modificationset>
<schedule>
<ant time="2200"
antscript="/opt/apache-ant-1.6.2/bin/ant"
buildfile="build-wrapper.xml"
uselogger="false"/>
</schedule>
</project>
</cruisecontrol>
Making Changes Available to Developers
After a successful build, we will want to make the changes available to the developers. As has been mentioned previously, this can be done in one of two ways:
- The new tasks can be copied into a shared folder, which is included in the reconfigure properties of each developer's project version. This is supported by the <cmsynergytaskpublisher>.
- An intermediate baseline can be created (only supported in version 6.3 and later). This can be accomplished using the <cmsynergybaselinepublisher>.
Both of these publishers enforce a single, simple, rule: the publisher will only run if the build was successful and the modification set contains at least one new CM Synergy task.
Using the <cmsynergytaskpublisher>
The <cmsynergytaskpublisher> is used to copy tasks into a shared folder, which is included in the reconfigure properties of each developer's project version. The folder may be specified by number, or by providing the 2 part name of the project and a substring of the folder's name. Let's have a look at the syntax.
ccmexe
By default, the plugin will search the system path for an executable called "ccm" (or "ccm.exe" for Windows). If you wish, you may override this by supplying the full path to the CM Synergy command line client here.
sessionfile
As discussed in previous sections, the session file is a simple properties file used to persist your CM Synergy session information. If this attribute is not set, it defaults to the file ".ccmsessionmap" in your home directory.
sessionname
The "nick-name" for the CM Synergy session you wish to use. This name must appear in the session file. If not set, the plugin will attempt to use the default (current) session as returned by the "ccm status" command.
foldernumber
The number of the target folder.
foldername
A substring of the name of the target folder (i.e. "Integration tested tasks"). If this attribute is set, you must also set the project attribute.
project
If you wish to specify the target folder by name, rather than by number, you must also provide the two part name of the project which contains that folder.
Examples
Publish all new tasks into folder number 203 using the CM Synergy session named "j2ee_session".
Publish all new tasks into the folder called "Integration tested tasks for release j2ee/1.0" found in the project "j2ee~1.0_int" using the CM Synergy session named "j2ee_session".
Using the <cmsynergybaselinepublisher>
The <cmsynergybaselinepublisher> is used to create an intermediate baseline which will include the specified project and all subprojects. This publisher will only work with CM Synergy version 6.3 or later. Let's have a look at the syntax.
ccmexe
By default, the plugin will search the system path for an executable called "ccm" (or "ccm.exe" for Windows). If you wish, you may override this by supplying the full path to the CM Synergy command line client here.
sessionfile
As discussed in previous sections, the session file is a simple properties file used to persist your CM Synergy session information. If this attribute is not set, it defaults to the file ".ccmsessionmap" in your home directory.
sessionname
The "nick-name" for the CM Synergy session you wish to use. This name must appear in the session file. If not set, the plugin will attempt to use the default (current) session as returned by the "ccm status" command.
project
This attribute is mandatory. You must specify the 2 part name of the project which will form the top level project of the baseline. Note that all subprojects will also be included.
purpose
The purpose of the baseline. If not specified, this will default to "Integration Testing".
description
An optional description of the baseline
baselinename
An optional name for the baseline. If not provided, CM Synergy will assign a default name based upon the current date. You may incorporate the value of any property set by CruiseControl (in the "info" section of the log) by using the macro "@{property}".
Example
Create a baseline with the name "BUILD_" followed by the CC timestamp for the purpose of "Integration Testing" using the session called "j2ee_session" incorporating the "j2ee~1.0_int" project and all subprojects.
Question,
A cmsynergysessionlistener was created with the appropriate parameters. When CC builds the following command is displayed on the dos window:
ccm start -q -nogui -m -d -r -n -pw -h
Is there a means to modify the ccm start parameters so to remove the multi-thread parameter (-m). Thank you.
Antonio