Suppose you have project A and project B, where project B depends on project A - let's say A is a library. And project A and project B live in separate version control repositories - either because project A was created by a third party, or because you just decided to organise your repositories that way. You want to make some changes to project B, but in order to do so you have to make some changes to project A. So you make two pull requests, one for your changes to project B and one for your changes to project A - these PRs "have to" be applied together - although in practice, of course, one of them has to be merged first (logically, it has to be the PR for project A) and here's where the problem can come in.

We have our CI server (TeamCity) set up to build all feature branches, so we can easily see if an individual, standalone PR to project B breaks things in project B. But because code in feature branches doesn't get published to our artifact repository (Nexus) until it's merged to master, this doesn't work so well for pairs (or even chains) of PRs like the scenario described above. We can only see, in a valid way, if the PR for project B is going to build on the build server after we've already merged the PR for project A. And it just so happened recently that this dependent build failed... because of a problem that only occurred on the build server.

Thus, we ended up with a situation where project B's master wasn't building due to a tightly-bound pair of PRs only being half-merged - the PR for project A had been merged, but the PR for project B hadn't been yet, due to the unexpected issue on the build server.

How could we adjust our workflow to avoid this kind of problem in future?

  • You did not add a java tag, so .. in C# world, you would just create a NuGet package from A that is consumed by B. B would use the original (or latest compatible) NuGet until you updated B to use the new one. So B never breaks because it will still use the previous dependency until you actually update B. – Wilbert Nov 25 '15 at 17:11
  • @Wilbert I think this is the crux of the problem - how do you make B use the right version of A at all times? Given that you may have multiple feature branches under development at any one time. – Robin Green Nov 25 '15 at 17:25
  • well in .Net world you use NuGet, where every dependency package has a version that uses SemVer. So you only need to version your dependencies and everything 'just works'. – Wilbert Nov 25 '15 at 17:55
  • What you also sometimes see is just a github fork being used during the time that the library is not updated. Then later when updated it's switched back to the original source. – Luc Franken Nov 25 '15 at 19:47

In the situation described, if you want to ensure that the CI build doesn't get broken, you might need to split the changes into even smaller, or slightly different, chunks.

A successful workflow could be:

  1. Change project A such that the new functionality can be supported, but the existing API remains valid (at least for the time being).
  2. Wait until the new version of A is available in the artefact repository.
  3. Make the required changes to project B, using the newly introduced interfaces from project A.
  4. (Optionally) Remove from project A the interfaces that have become obsolete and are no longer used.

The major difference with your existing workflow is that you do not change both projects at the same time. First you make the required changes, in a backwards-compatible way, to the lower projects in the dependency graph and only when you have a "released" version of your dependencies that support what you need, only then do you make the update to the higher levels.

  • Some words on importance of versioning dependencies might help... B 2.1 needs A 3.11 and adding A 4.0 doesn't break B since B 2.1 still uses A 3.11 until it's updated. – Wilbert Nov 25 '15 at 17:13

Another option is to tie both (or any number of) projects together, side-by-side, to be managed in a monolithical manner:

  • no more worries about changeset dependencies, any combination of single or multi-repo changesets is supported, they're just like a regular changeset in a single repository
  • CI always works on all these tied-together repositories
  • no more waiting between teams working on different projects, everyone is on the same page

Effectively you're only dealing with a single project, not multiple inter-dependent ones.

See also this answer about how can this be achieved from the version control perspective: https://stackoverflow.com/a/30530140/4495081

  • Seems to me that if you wanted to treat two repos as one, you'd be better off just merging the repos into one. – Robin Green Dec 2 '15 at 6:35
  • Hm, I disagree, there can be many reasons for which you might not want/be able to do that: scalability (especially if using a VCS system which makes heavily use of locking or a centralized database system), 3rd party/vendor code, legacy code, different VCS systems, etc. – Dan Cornilescu Dec 2 '15 at 6:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.