Giter Site home page Giter Site logo

monorepo-sample's Introduction

Monorepo sample

This repo showcases how one could structure and build monorepos with either Apache Maven or Bazel.

The repo

A couple of toy applications under apps/ depend on shared code under libs/.

.

├── apps
│   ├── app1
│   └── app2
└── libs
    ├── lib1
    └── lib2

Continous integration

The ci/ sub folder contains a self-contained ci-stack for building the monorepo with Jenkins.

Maven and Bazel: a comparison of basic actions

Maven is really not a monorepo-native build tool (e.g. lacks trustworthy incremental builds, can only build java code natively, is recursive and struggles with partial repo checkouts) but can be made good use of with some tricks and usage of a couple of lesser known command line switches.

Action in working directory with Maven with Bazel
Build the world . mvn clean package -DskipTests bazel build //...:*
Run app1 . java -jar apps/app2/target/app1-1.0-SNAPSHOT.jar java -jar bazel-bin/apps/app1/app1_deploy.jar
Build and test the world . mvn clean package bazel test //...:*
Build the world ./apps/app1 mvn --file ../.. clean package -DskipTests bazel build //...:*
Build app1 and its dependencies . mvn --projects :app1 --also-make clean package -DskipTests bazel build //apps/app1:*
Build app1 and its dependencies ./apps/app1 mvn --file ../.. --projects :app1 --also-make clean package -DskipTests bazel build :*
Build lib1 and its dependents (aka. reverse dependencies or rdeps in Bazel parlance) . mvn --projects :lib1 --also-make-dependents clean package -DskipTests bazel build $(bazel query 'rdeps("//...", "//libs/lib1")')
Print dependencies of app1 ./apps/app1 mvn dependency:list bazel query 'deps(.)' --output package

Notes

  • Maven is a recursive build tool that needs an reference to the root module with --file when building from a sub folder. In contrast will Bazel discover the entire project from any sub folder and packages to be built can be specified both absolutely from root (//) and relative the current working directory.
  • Bazel doesn't build the so-called implicit deploy jar-target (:app1_deploy.jar) if we refrain from building with the :* suffix. Deploy jar is Bazel speak før über-/super-/fat-jar.
  • Maven has no trustworthy support for incremental builds, hence one typically always build from a clean state.

Sparse checkouts

A monorepo will naturally grow quite large quite fast and for many reasons engineers will for the most time prefer to only have a subset of the tree checked out at once. Git sparse checkouts provides a mechanism for archieving this.

Executing:

git config core.sparseCheckout true
echo '/*'           >  .git/info/sparse-checkout
echo '!/apps/*'     >> .git/info/sparse-checkout
echo '/apps/app1/*' >> .git/info/sparse-checkout

enables sparse checkouts and configures git to checkout the the whole tree except all apps other than app1. To make it happen, either run a checkout command or to update the work tree in-place:

git read-tree -mu HEAD

Notes for Maven

Sparse checkouts

While Bazel is fine with sparse checkouts, Maven struggles as a sparse checkout typically implies that there will be pom.xml-references to submodules that no longer are present on disc. A hack to work-around this is to use Maven profiles that only activates when the corresponding pom.xml-file is available on disc:

<profile>
  <id>app2</id>
  <activation>
    <file>
      <exists>app2/pom.xml</exists>
    </file>
  </activation>
  <modules>
    <module>app2</module>
  </modules>
</profile>

Build parallelization

Maven requires explicit setup to build modules in parallell. This can be provided as a switch on the command-line (--threads 2) or in .mvn/maven.config.

Versioning

Maven requires you to provide an version for every module in its Project Object Model. This is confusing and superflous in monorepos as the they are typically exclusively versioned by the version control system. This repo takes advantage of Maven's newish support for so-called CI Friendly Versions. This makes it possible to ensure that the version of all Maven modules are set to current git HEAD at build-time:

$ mvn clean install -Drevision=$(git rev-parse HEAD)

To ensure that no CI-friendly version placeholders (<version>${revision}</version>) are present in the pom-files that are installed, this repo utilizes the flatten-maven-plugin to resolve them to their values before install.

Partial builds

Maven's lack of incremental build support can lead to long build times in a large monorepo. The partial-build-plugin can be used to only build modules that has a diff against the trunk branch.

monorepo-sample's People

Contributors

nordstrand avatar agjendem avatar kwltrs avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.