I have implemented a plug-in for our internal system that achieves most of the requirements. I need to seek approval from my management before contributing the code, but I can outline the process at this stage.
This is split into two processors, the SnapshotDependencyProcessor (implements CustomBuildProcessor) runs on the remote agent (i.e. the box that actually executed the build), and the SnapshotDependencyPostProcessor (implements CustomBuildProcessorServer) runs on the build manager (the central manager that apportions builds to the agents).
The process is split because the build agent doesn't have access to persist any data between builds, it can just send back a Map of metadata, whereas the manager doesn't have access to the POM (which was checked out from the SCM on the build manager)
1) The SnapshotDependencyProcessor that runs on the remote agent first uses the MavenXpp3Reader to read the POM, then extracts the groupId, artifactId, and version for the parent and all dependencies (at present the process doesn't handle dependencies defined within a profile, but that would be a case of beefing up the Maven POM parsing as mentioned above). I assume that if there are any snapshots in the parent, the parent will also be a snapshot, so the build can rely on the parent's build being triggered (transitive builds if you will).
The SnapshotDependencyProcessor persists data in the build plan to identify the current project's groupId, artifactId and version (the identifiers for a project in Maven, called GAV from now on). It also processes the project's dependencies and parent and persists the GAVs for any SNAPSHOTs found.
2) The SnapshotDependencyPostProcessor compares the GAVs of all snapshots for the latest build with the GAVs for the previous build and if there are any differences (additions/deletions), locates the corresponding build plans (if any) and registers/unregisters dependencies with the corresponding plan as required.
Identifying a corresponding build is managed by checking the GAV values persisted in the custom properties by the SnapshotDependencyProcessor
for (Iterator iter = allBuilds.iterator(); iter.hasNext()
{
Build projectBuild = (Build) iter.next();
Map customConfig =
projectBuild.getBuildDefinition().getCustomConfiguration();
if (groupId.equals(customConfig.get("custom.maven.groupId"))
&& artifactId.equals(
customConfig.get("custom.maven.artifactId"))
&& version.equals(customConfig.get("custom.maven.version")))
{
return projectBuild;
}
}
Registering the child build is handled by
dependentBuild.getChildBuilds().add(build);
getBuildManager().saveBuild(dependentBuild);
While the removal is handled by:
dependentBuild.getChildBuilds().remove(build);
getBuildManager().saveBuild(dependentBuild);
The custom properties are all copied from the CurrentBuildResult's custom data into the build definition's custom configuration to be used as the basis for the comparison for the next build (and to identify the plan as a dependency).
This approach means that, once each project has been built once, custom properties have been persisted so it can be identified as a dependency. Then subsequent builds will establish the full dependency tree over the next few builds.
Rafał,
Thanks for the update. We are glad you find Bamboo's Maven 2 support useful.
Cheers,
Anton