At Atlassian we use Maven as part of our development process. The key with Maven is to set it up correctly as a process. In order to do that you need to understand who uses it, what they use it for and what they expect from it.
It’s quite common to read complaints about Maven, so in this four-part series I will show you how we have set up our process at Atlassian. I hope this will help you avoid some of the common pitfalls of setting up Maven.
Our Maven users
Atlassian’s Maven infrastructure has many users. To help understanding our requirements, we divide them into several categories.
Obviously Maven is used by the Atlassian teams. The core development team is in the Sydney office where we have over 50 people. All product work is done here. Apart from being in the office, quite often we work from home. (The significance of this, as far as Maven is concerned, will become apparent later.)
There are also a few, smaller, development teams around the world, for instance at our San Francisco office.
Then we have Atlassian customers. Customers receive source builds so they can make some modifications to the product. These builds are produced using Maven, of course.
Atlassian contributors (also called the Developer network, or DevNet) are external developers who contribute their code to Atlassian, such as plugins for our products. These developers are also users of our Maven infrastructure.
Types of libraries managed by Maven
To simplify the discussion of libraries at Atlassian, we divide them into categories: public, contributed, closed-source, private and third-party.
The majority of libraries written by Atlassian and shared between the teams are public libraries. These are released under a BSD license. Atlassian’s plugin framework is a good example of this kind of library. Some people outside Atlassian use it in their projects.
Contributed libraries are mainly plugins for our products written by external developers.
There are some libraries for which the source is not freely available. We call these closed source libraries. We ship the source code of closed source libraries only to our commercially-licensed customers as part of product source builds. These are primarily the libraries which make up a product like JIRA or Confluence.
Some internal libraries we keep to ourselves. These are private libraries. They are not part of any product and are used for our own needs. The source code for the Atlassian website is private, for instance.
Then there are various types of third-party libraries we depend on. The open-source libraries we use include JUnit, Log4J and Spring. We also use several Sun libraries which are actually not distributable, but still need to be available in a Maven repository when building our products.
So what do the differences in these libraries mean for our Maven configuration at Atlassian? Well, we have quite complex rules about how each kind of library can be accessed by different users. Here they are in brief:
- All Atlassian developers should have full access to read and deploy new versions of all types of libraries.
- All our users should have full access to read public and contributed libraries. This includes binaries, Javadoc and source code.
- Users should have access to read binaries and Javadoc for closed source libraries. This includes product code like JIRA and Confluence.
- Atlassian developers should have access to source code via Maven for all libraries produced internally, to make debugging easier.
- Customers – that often wish to modify and debug the product they purchased – should also be able to attach the sources of the closed source libraries in their IDEs.
- DevNet teams should be able to deploy new versions of their libraries. As above, this includes binaries, Javadoc and source code.
- Atlassian developers would like, wherever possible, to have binaries, Javadoc and source code available for the third-party libraries we use.
- Finally, the process should work regardless which office you work in and, more importantly, even if you roam in and out of the office. In other words, those who work from home every now and again should not need to change any settings for Maven to work properly.
When running lots of builds with Maven, you needs to see it as a process rather than just a build tool. As with any build process, it should be:
- Deterministic. A Maven build should execute as understood by the developer without random dependencies on the external factors.
- Repeatable. A Maven build should execute with the same result today, tomorrow, in a year, and so on. (Provided the code didn’t change, of course.) This is important for maintaining previous versions and reproducing problems when you have shared code.
Being the main tool our developers use on a daily basis – it also must be simple. Pretty much any operation you want to do to your project should be a single command away. Otherwise it will be degrading productivity and causing frustration.
So how does Maven meet these requirements? Stay tuned!
.. to be continued
Part 2 of this series will cover how our Maven infrastructure is organised to meet the above requirements.
Part 3 will describe you how our projects (all of those libraries I talked about) are configured to make their builds deterministic and repeatable.
Unfortunately, even after several years, our Maven infrastructure is not perfect. Part 4 will cover issues we hit every now and again and explain how we deal with them.