[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [virgo-dev] Re: Running integration tests with maven

(My apologies for a long and bit rambling post)

First I would like to state that I have no religious association to any build/dependency management tool as long as it works and everyone on the project understands it :)

Let me try to explain how we use Maven in current project.

We also follow a system similar to Virgo layout and versioning.  We try to be modular and try to keep clear versioning dependency matrix.
Here is a simplified dependency tree in our project that uses Maven

* project-master (to lock down plugin/major 3rd party deps versions and common properties)
** third-party - this is our local BRITS like effort (osgified bundles for stuff missing from other sources)
*** core - base classes/utilities/major components used by all downstream components
**** runtime - "active" components that no other components reference directly during compile - i.e. db connection pooling (managed service factory), hibernate SF, Spring Batch, ActiveMQ, Snaps host webapp, ui styling themes
***** app-base - depends on version of core
****** app2 - depends on app-base services and types and transitively on core
****** app3 - same as app2
 etc...

What we decided to do early on is to version at the component level.  That is we lock versions at core/runtime/app-base/app2/etc level vs. an individual bundle or module within a component.  This will cause a version of a bundle to change even if there was no change to it - but that is life :).  I believe this is the same strategy that Virgo is using.

Each dependent component defines a version of upstream components that it depends on in a pom property (similar to build.version) and uses that to lock down version of dependency in dependencyManagement section of the pom.  This is done in the parent pom of the component and modules just inherit that version.  We are also locking down manifest imports for upstream components to version="[${version},=.=.+1]" because we consider minor version an API change where micro is just something in implementation (bug fix, etc).

With this system anything up the tree causes a "ripple" down to the dependencies.  One advantage is that once that "ripple" is identified, lets say we adding stuff to core to support a new feature, we can switch to SNAPSHOT in core and modify one property in dependent project to "ripple" the change down the tree.  This ripple does not have to happen right away, depend project can still use a prior version of core while core feature is worked on.

The process is similar to Virgo for a ripple where an aggregate build must be done once the "ripple" is created.  Ideally developer does it locally.  We have Hudson set-up to cascade builds upon checkin to dependent projects.  Our full build takes about 20-30 min a lot of that time is spent in GWT compile (if not skipped).

This system is not 100% perfect but it works fairly well for now.  We do releases every sprint and for now switch to SNAPSHOT on trunk with each sprint.  Once we are in production - it will become a bit more difficult to change core components.  We can potentially have multiple versions of the upstream components deployed, but care must be taken not to add incompatible API change and decorate or extend to provide extra functionality.

SNAPSHOT semantics are not perfect, but they are well known.  An issue I had while playing with dm-server and virgo code base was that disconnect where one component depends on medic 1.0.0.D-55 and another on 1.0.0.D-87 for example.  There is no way to tell from the version if there were any changes between builds, where SNAPSHOT at least gives a hint to "be careful, you are working with volatile code base".

We did have situations where SNAPSHOT usage did cause a breakage, but those breaks were seen as an early warning system vs. systematic bad behavior by developers.  There were also some SCM practices that we used to keep impact local, i.e. branching on major impact changes and changing artifact version to reflect a branch name but keeping SNAPSHOT qualifier.  
For example:
- trunk would be 1.0.1.BUILD-SNAPSHOT
- branch 1.0.1.BRANCH-SNAPSHOT

Hudson also spams everyone on build failure and has a very nice Chuck Norris plug in :)

To summarize, I think my current project and Virgo have a very similar structure and versioning approach.  Only difference is dependency management system and use of automatic vs. manual version management for artifacts on the HEAD^.

I understand your concern about GRs becoming a bit more brittle, but on the flip side if artifact-repository change to util with a different version and kernel still keeps util of old - how would that affect final assembly?  Wouldn't that introduce subtle bugs also?  This question could be a non started if I understood ivy resolution a bit better.

Regards,

Dmitry

On Fri, Jul 16, 2010 at 6:01 AM, Glyn Normington <gnormington@xxxxxxxxxx> wrote:
Steve and I discussed this and I agree with everything below. Breaking people's development environment in another timezone and not being available to provide a fix for several hours is something we must strive to avoid. I'd be interested in the perspective of seasoned Maven users on how these requirements can be addressed with Maven, although it is important to note that Virgo's modular GR structure may not be typical.

Glyn
On 16 Jul 2010, at 10:49, Steve Powell wrote:

> (My apologies for a long post.)
>
> In discussing the build mechanisms we currently use, and how they might be improved, I would like to be explicit
> about the advantages and disadvantages of the present dependency control. At least IMO.
>
> These might be viewed as potential requirements of inter-Git Repository dependency management.
>
> [I shall use the terms GR for a Git Repository and GRuB for a Git Repository Build (a potential bug, perhaps?).]
>
> The present build system has fixed version dependencies between GRuBs until they are explicitly updated (either
> manually with update_dependency.rb, or by means of Ripplor, etc.).
>
> The primary advantage of this is that a GR can be worked on (and pushed) and not affect the rest of the build tree.
> Even though a GRuB is successful, it doesn't follow that the GRuBs that depend on it will succeed.
>
> When we want to use the dependency on a successful GRuB in another GR, we can either make a manual update_dependency.rb
> change (and push the GR), or, more commonly, perform a "Ripple" of builds.
>
> If we make every GRuB automatically use the most recent (successful) GRuBs it depends on, we gain the advantage that
> we do not have to perform the dependency updates (no more Ripplor).  However, we make the set of GRs more brittle,
> subject to subtle breakage. This sort of breakage is infuriating when it happens in the same room. If the cause is
> potentially half-way round the world in another time-zone then solving it will be harder.
>
> When running a "ripple" of builds between GRuBs the complete (sub) tree is built locally before imposing the
> changes on every one else (before they are pushed). This means that the impact of a GRuB can be detected
> before the rest of the tree is broken.
>
> The drawbacks seem to be that ripples are time-consuming, and can be invalidated due to parallel changes (this is
> essentially the optimistic locking syndrome), which make them even longer. Furthermore, if a ripple detects a problem
> caused by a GRuB dependency, the cure may involve other people and further delay.
>
> Incidentally, the full power of a Ripple (or update_dependency) is rarely needed: often the Ripple actually just brings
> everything 'up-to-date'. If that is all it did (essentially a manual step to perform the automatic dependency management
> under discussion), then it would suffice.
>
> Under the automatic system, it is possible for users to perform full tree builds locally before pushing their single changes
> to a GR.  This would make a Ripple unnecessary. However, the overhead of this (about an hour-and-a-half minimum
> elapsed time) is high enough to mean that people (including me) just won't do it.  Also, I will not do it when it is most
> necessary: either when I think there is no impact, so "it can't hurt", or when I want to use the dependency in a later 'GR'
> urgently and I 'cannot afford' to wait.  These are the times that chaos can ensue.
>
> In Summary:
> A system that retains the protection of a private, manual, dependency update--or at least meant that
> updates to GRs that broke the tree were not adopted automatically--would be preferable to one that
> took the latest of everything all the time.  Latest isn't necessarily greatest.
>
> Regards,
> Steve Powell
> [W:+44-2380-111-528; M: +44-7815-838-558; H:+44-1962-775-598]
>
> Cannelloni n. A narrow boat for one. [SPD]
> Verisimilitude adj. Extremely evenly masticated. [SPD]
> Decrepit v. To muck-out Royal stables. [SPD]
> _______________________________________________
> virgo-dev mailing list
> virgo-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/virgo-dev

_______________________________________________
virgo-dev mailing list
virgo-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/virgo-dev