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

Gradlin': Plugging it in for Build Success v2

NeiL saitug
September 03, 2015

Gradlin': Plugging it in for Build Success v2

Gradle is a cool (not so) new tool that everyone should learn how to use and love. But figuring out how to build a plugin or where to start is difficult.

This talk will walk you through the building a Gradle plugin for versioning an Android application.

We start with a simple premise -- keeping track of versions for an Android application. We build up from this task at an application level, into multi-project build logic, and finally encapsulate the build logic into a Gradle plugin for versioning.

This is a (slightly) updated version of the same talk that I gave at DroidCon UK last year.

http://droidcon.se/events/stockholm-2015/

NeiL saitug

September 03, 2015
Tweet

More Decks by NeiL saitug

Other Decks in Programming

Transcript

  1. build.gradle android { compileSdkVersion 23 buildToolsVersion "23.0000000" defaultConfig { applicationId

    "neigut.lisa.gradlepractice" minSdkVersion 16 targetSdkVersion 21 versionCode 200 versionName "200.0.1" } }
  2. build.gradle android { compileSdkVersion 23 buildToolsVersion "23.0000000" defaultConfig { applicationId

    "neigut.lisa.gradlepractice" minSdkVersion 16 targetSdkVersion 21 versionCode lookupVersionCode() versionName lookupVersionName() } }
  3. build.java project.tasks.create("bumpVersion") { doLast { project.versionCode += 1; project.versionName =

    String.valueOf(project.versionCode + ".0") project.android.applicationVariants.all { variant -> variant.mergedFlavor.versionCode project.versionCode variant.mergedFlavor.versionName project.versionName } } }
  4. android { compileSdkVersion 23 buildToolsVersion "23.0000000" defaultConfig { applicationId "neigut.lisa.gradlepractice"

    minSdkVersion 16 targetSdkVersion 21 versionCode project.versionCode versionName project.versionName } }
  5. build.gradle project.ext.set("versionCode", 1); project.ext.set("versionName", "1.0"); android { compileSdkVersion 23 buildToolsVersion

    "23.0000000" defaultConfig { applicationId "neigut.lisa.gradlepractice" minSdkVersion 16 targetSdkVersion 21 versionCode project.versionCode versionName project.versionName } } project.tasks.create("bumpVersion") { doLast { project.versionCode += 1; project.versionName = String.valueOf(project.versionCode + ".0") project.android.applicationVariants.all { variant -> variant.mergedFlavor.versionCode project.versionCode variant.mergedFlavor.versionName project.versionName } } }
  6. build.gradle old defaultConfig { versionCode lookupVersionCode() versionName lookupVersionName() ... }

    build.gradle new defaultConfig { versionCode project.versionCode versionName project.versionName ... }
  7. build.gradle loadVersion() { def versionFile = new File(project.projectDir, VERSION_FILE_NAME) versionFile.eachLine()

    { line -> def (key, value) = line.split("=").collect { it.trim() } if ("majorVersion".equals(key)) { project.majorVersion = Integer.parseInt(value) } ... } }
  8. //TODO: - Create 3 tasks (one for each version 'type')

    - Each task increments the appropriate project property - Write out the new values to verisons.gradle
  9. build.gradle def VERSIONS = ["majorVersion", "minorVersion", "bugFixVersion"] ... VERSIONS.each {

    versionType -> projects.tasks.create(name: "bump$versionType") { doLast { project.ext[versionType] += 1 ... } }
  10. build.gradle def VERSIONS = ["majorVersion", "minorVersion", "bugFixVersion"] ... VERSIONS.each {

    versionType -> projects.tasks.create(name: "bump$versionType") { doLast { project.ext[versionType] += 1 // write to versions.gradle file // update the applicationVariants values } }
  11. build.gradle def VERSIONS = ["majorVersion", "minorVersion", "bugFixVersion"] ... VERSIONS.each {

    versionType -> projects.tasks.create(name: "bump$versionType") { doLast { project.ext[versionType] += 1 new File(project.projectDir, VERSIONS_FILE_NAME).withWriter { out -> out.write { """majorVersion=${project.majorVersion} minorVersion=${project.minorVersion} bugFixVersion=${project.bugFixVersion} """ } } // update the applicationVariants values } }
  12. build.gradle def VERSIONS = ["majorVersion", "minorVersion", "bugFixVersion"] ... VERSIONS.each {

    versionType -> projects.tasks.create(name: "bump$versionType") { doLast { project.ext[versionType] += 1 new File(project.projectDir, VERSIONS_FILE_NAME).withWriter { out -> out.write { """majorVersion=${project.majorVersion} minorVersion=${project.minorVersion} bugFixVersion=${project.bugFixVersion} """ } } // update the applicationVariants values } }
  13. build.gradle def VERSIONS = ["majorVersion", "minorVersion", "bugFixVersion"] afterEvaluate { VERSIONS.each

    { versionType -> projects.tasks.create(name: "bump$versionType") { doLast { project.ext[versionType] += 1 new File(project.projectDir, VERSIONS_FILE_NAME).withWriter { out -> out.write { """majorVersion=${project.majorVersion} minorVersion=${project.minorVersion} bugFixVersion=${project.bugFixVersion} """ } } // update the applicationVariants values } }
  14. beforeEvaluate { project -> // set up project properties //

    load the versions from disk } afterEvaluate { project -> // create tasks to bump versions }
  15. Versioning 1. Stateful versions 2. Gradle tasks to change the

    version number 3. Build server (Jenkins) can easily manage version numbers 4. Can be checked into source control (Git)
  16. AndroidApp - build.gradle (root) - app/ -- src/ -- build.gradle

    (app1) - app2/ -- src/ -- build.gradle (app2)
  17. build.gradle (root) def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion'] subprojects {

    project.afterEvaluate { // create bump version tasks here, dynamically } }
  18. build.gradle (root) def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion'] subprojects {

    project.afterEvaluate { // create bump version tasks here, dynamically } project.beforeEvaluate { VERSIONS.each { version -> project.ext.set(version, 0) } } }
  19. build.gradle (root) def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion'] subprojects {

    project.afterEvaluate { // create bump version tasks here, dynamically } project.beforeEvaluate { VERSIONS.each { version -> project.ext.set(version, 0) } loadVersions(project) } }
  20. app/build.gradle (app1/app2) defaultConfig { versionCode project.majorVersion * 10 + project.minorVersion

    // etc versionName project.majorVersion + " " + project.minorVersion // etc // ... }
  21. VersionExtension.groovy class VersionExtension { // ... def releaseString() { majorVersion

    + DOT + minorVersion + DOT + bugFixVersion } def code() { majorVersion * 10**6 + minorVersion * 10**4 + bugFixVersion } // 1.4.1 // 1040001 }
  22. build.gradle (root) subprojects { project.afterEvaluate { ... } } VersionsPlugin.groovy

    void apply(Project project) { project.afterEvaluate { ... } }
  23. VersionsPlugin.groovy class VersionPlugin implements Plugin<Project> { void apply(Project project) {

    project.extensions.create("appVersion", VersionExtension) project.appVersion.loadVersions(project) project.afterEvaluate { VERSIONS.each { version -> project.tasks.create(name: "bump$version") { doLast { project.appVersion.bump(version) // Write out to file // Update `android` plugin values } } } } } }