Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dependency Management with Gradle (at Geektastik Connect Düsseldorf)

Dependency Management with Gradle (at Geektastik Connect Düsseldorf)

Managing dependencies is one of the most important features of every build tool. This talk gives an introduction to dependency management with Gradle and covers the following areas:

- Basics: why you should use the api & implementation configurations instead of compile
- Managing dependencies using pre-compiled script plugins
- Consuming managed dependencies using the platform keyword
- Defining your own platforms
- Gradle Module Metadata

The presentation is accompanied by a live demo, the code can be found at https://github.com/britter/dependency-management-with-gradle

Benedikt Ritter

October 17, 2019
Tweet

More Decks by Benedikt Ritter

Other Decks in Programming

Transcript

  1. Today’s Speaker: Benedikt Ritter • Senior Software Engineer at Gradle

    Inc. • Apache Commons PMC Member • Guilty Pleasure: I love Scala! • Podcaster autoweird.fm @BenediktRitter
  2. compile vs. api & implementation • Dependencies in configurations like

    compile leak into consuming projects • They have been deprecated • Use api and implementation instead implementation: Dependency only used internally api: Dependency is exposed via public API
  3. Analyzing problems ./gradlew dependencies \ --configuration compileClasspath ./gradlew dependencyInsight \

    --configuration compileClasspath \ --dependency com.google.guava:guava Build Scans: • https://scans.gradle.com/s/pobjsx3jv57na • https://scans.gradle.com/s/la2koegmjej2o
  4. Managing common configuration plugins { kotlin("jvm") version "1.3.50" } repositories

    { jcenter() } dependencies { implementation(kotlin("stdlib-jdk8")) implementation("com.google.guava:guava:28.1-jre") } tasks { compileKotlin { // compiler configuration } }
  5. Pre-compiled script plugins • Pre-compiled script plugins are Kotlin scripts

    that are compiled as part you the build • Located in a special folder ‘buildSrc’ • Can be used anywhere in the main build • Usually used for commons configuration • Can also declare dependencies
  6. Using Platforms dependencies { implementation(platform("org.springframework.boot:spring-boot-dependencies:2.1.9.RELEASE")) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-mustache") } • BOMs

    define a set of dependencies that work well together • Import the BOM using the platform keyword • Dependencies managed by the BOM can then be used without declaring the version Build Scan: https://scans.gradle.com/s/sa5rtp4rw55qa
  7. Managing Groups of Dependencies dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.2") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.2") testImplementation("org.assertj:assertj-core:3.11.1") testImplementation("io.mockk:mockk:1.9")

    } • Sometimes you have groups of dependencies you want to always use together • Redeclaring leads to nightmares on new release • Example: Testing dependencies Challenges: • Always use matching JUnit Jupiter API and Engine • Engine has to go to runtime classpath only • Mock library is optional
  8. Solution: Define your own Platform plugins { `java-platform` } javaPlatform

    { allowDependencies() } dependencies { api("org.junit.jupiter:junit-jupiter-api:5.5.2") runtime("org.junit.jupiter:junit-jupiter-engine:5.5.2") api("org.assertj:assertj-core:3.11.1") constraints { api("io.mockk:mockk:1.9") } }
  9. Using the custom Platform • Same as with Spring Platform,

    but using a project dependency • Pulls in everything from api and implementation • Optional dependencies are declared without version • Platforms can be published as Maven BOMS Build Scan: https://scans.gradle.com/s/s6pjnmpqst3pm dependencies { testImplementation(platform(project(":test-platform"))) testImplementation("io.mockk:mockk") }
  10. Problem: Test Support Code • Testing should be as easy

    as possible • We write support code that helps accelerate testing, e.g. ◦ Templates ◦ Builders ◦ Stubs ◦ Test environment ◦ … • Where to put this code? ◦ src/test → can not be used outside the project, leads to... ◦ Copy/paste → maintenance nightmare, leads to... ◦ Separate project → chicken and egg problem
  11. Solution: Test Fixtures Plugin plugins { `java-test-fixtures` } dependencies {

    testImplementation(testFixtures(project(":model"))) } Build Scan: https://scans.gradle.com/s/arw325f2yroxc
  12. Motivation • Authoring Gradle builds is really configuring a model

    of your software • The POM is too restricted to transport this information ◦ No separation of build description and dependency information ◦ Bad between compile and runtime dependencies ◦ No possibility to define variants ◦ Focused on Java projects
  13. Gradle Module Metadata • Serialization of dependencies part of the

    model • Separation between compile and runtime dependencies • Prevention of accidental dependency leaking • Publication of variants • Definition of capabilities • Gradle still produces Maven compatible publications • Gradle Builds benefit from GMM
  14. • Code: https://github.com/britter/dependency-management-with-gradle • Documentation: https://docs.gralde.org • Slack: gradl.es/slack-invite-2019 •

    Webinar ◦ https://gradle.com/blog/dependency-management-fundamentals/ ◦ https://gradle.com/blog/dependency-management-part-2-handling-conflicts/ ◦ https://gradle.com/training/dependency-management-publishing-and-release-stra tegies/ • eBook: https://gradle.com/developer-productivity-engineering/ Links