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

Gradlin': Plugging it in for Build Success

Gradlin': Plugging it in for Build Success

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.

Presented at DroidCon UK 2014, Oct 31, 2014
http://uk.droidcon.com/2014/sessions/4890/

NeiL saitug

October 31, 2014
Tweet

More Decks by NeiL saitug

Other Decks in Programming

Transcript

  1. build.gradle android { compileSdkVersion 20 buildToolsVersion "20.0.0" defaultConfig { applicationId

    "neigut.lisa.gradlepractice" minSdkVersion 15 targetSdkVersion 21 versionCode 1 versionName "1.0" } … }
  2. build.gradle … android { compileSdkVersion 20 buildToolsVersion "20.0.0" defaultConfig {

    applicationId "neigut.lisa.gradlepractice" minSdkVersion 15 targetSdkVersion 21 versionCode lookupVersionCode() versionName lookupVersionName() } … }
  3. build.gradle project.tasks.create('bumpVersion') { doLast { project.versionCode += 1; project.versionName =

    String.valueOf(project.versionCode + ".0"); project.android.applicationVariants.all { variant -> variant.mergedFlavor.versionName project.versionName variant.mergedFlavor.versionCode project.versionCode } } }
  4. build.gradle project.ext.set("versionCode", 1); project.ext.set("versionName", “1.0”); android { compileSdkVersion 20 buildToolsVersion

    "20.0.0" defaultConfig { applicationId "neigut.lisa.gradlepractice" minSdkVersion 15 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.versionName project.versionName variant.mergedFlavor.versionCode project.versionCode } } }
  5. build.gradle def String VERSION_FILE_NAME = "versions.gradle” project.ext.set(“majorVersion”, 0); project.ext.set(“minorVersion”, 0);

    project.ext.set(“bugFixVersion”, 0); project.ext.set(“alphaVersion”, 0); def loadVersions() { def versionsFile = new File(project.projectDir, VERSION_FILE_NAME) versionsFile.eachLine() { line -> if (line.contains('=')) { def (key, value) = line.split('=').collect { it.trim() } if (“majorVersion”.equals(key)) { project.majorVersion = Integer.parseInt(value) } else if (“minorVersion”.equals(key)) { project.minorVersion = Integer.parseInt(value) } else if (“bugFixVersion”.equals(key)) { project.bugFixVersion = Integer.parseInt(value) } else if (“alphaVersion”.equals(key)) { project.alphaVersion = Integer.parseInt(value) } } } }
  6. build.gradle def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] ... VERSIONS.each

    { targetName -> project.tasks.create(name: "bump$targetName") { doLast{ project.ext[targetName] += 1 // Write to versions.gradle file // Update applicationVariants stanza
  7. build.gradle def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] project.afterEvaluate {

    VERSIONS.each { targetName -> project.tasks.create(name: "bump$targetName") { doLast{ project.ext[targetName] += 1 new File(project.projectDir, VERSIONS_FILE_NAME).withWriter { out -> out.write( """majorVersion=${project.majorVersion} minorVersion=${project.minorVersion} bugFixVersion=${project.bugFixVersion} alphaVersion=${project.alphaVersion} """ // Update applicationVariants stanza
  8. build.gradle def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] project.afterEvaluate {

    VERSIONS.each { targetName -> project.tasks.create(name: "bump$targetName") { doLast{ project.ext[targetName] += 1 new File(project.projectDir, VERSIONS_FILE_NAME).withWriter { out -> out.write( """majorVersion=${project.majorVersion} minorVersion=${project.minorVersion} bugFixVersion=${project.bugFixVersion} alphaVersion=${project.alphaVersion} """ // Update applicationVariants stanza
  9. Project(Hooks project.beforeEvaluate { project -> // Set up the project

    properties // Load the versions from disk } project.afterEvaluate { project -> // Logic to create bump version tasks goes here. }
  10. build.gradle+(root) def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] subprojects {

    project.afterEvaluate { // Logic to create bump version tasks goes here. } }
  11. build.gradle+(root) def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] subprojects {

    project.afterEvaluate { // Logic to create bump version tasks goes here. } project.beforeEvaluate { VERSIONS.each { version -> project.ext.set(version, 0) } } }
  12. build.gradle+(root) def loadVersions(project) { ... } def VERSIONS = ['majorVersion',

    'minorVersion', 'bugFixVersion', 'alphaVersion'] subprojects { project.afterEvaluate { // Logic to create bump version tasks goes here. } project.beforeEvaluate { VERSIONS.each { version -> project.ext[version] = 0 } loadVersions(project) } }
  13. build.gradle+(-\app) defaultConfig { versionCode project.majorVersion * 10 + project.minorVersion //

    etc versionName project.majorVersion + “.” + project.minorVersion // etc }
  14. The$Plugin groovy/com.etsy.gradle/VersionsPlugin.groovy class VersionsPlugin implements Plugin<Project> { def String VERSION_FILE_NAME

    = "versions.gradle" def VERSIONS = ['majorVersion', 'minorVersion', 'bugFixVersion', 'alphaVersion'] void apply(Project project) { // plugin set up logic }
  15. groovy/com.etsy.gradle/VersionsPlugin.groovy void apply(Project project) { project.extensions.create("appVersion", VersionExtension) project.appVersion.loadVersions(project) project.afterEvaluate {

    VERSIONS.each { targetName -> project.tasks.create(name: "bump$targetName") { doLast { project.appVersion.bump(targetName) // Write out to file } } } }
  16. Project(Extension groovy/com.etsy.gradle/VersionsPlugin.groovy def alphaString() { major + DOT + minor

    + DOT + bugFix + DOT + alpha } def publicBetaString() { alphaString() + "-b" } def releaseString() { major + DOT + minor + DOT + bugFix } def code() { major * 10**6 + minor * 10**4 + bugFix * 10**2 + alpha }
  17. Version(Code def code() { major * 10**6 + minor *

    10**4 + bugFix * 10**2 + alpha } 1.0.3.1 -> 1000301
  18. Project(Extension groovy/com.etsy.gradle/VersionsPlugin.groovy def bump(versionPiece) { if (versionPiece.equals(VERSIONS[0])) { major +=

    1; minor = 0; bugFix = 0; alpha = 0; } else if (versionPiece.equals(VERSIONS[1])) { minor += 1; bugFix = 0; alpha = 0; } else if (versionPiece.equals(VERSIONS[2])) { bugFix += 1; alpha = 0; } else if (versionPiece.equals(VERSIONS[3])) { alpha += 1; } println "$versionPiece bumped " + code() }
  19. Use$the$Plugin android { compileSdkVersion 20 buildToolsVersion "20.0.0" defaultConfig { applicationId

    "neigut.lisa.gradlepractice" minSdkVersion 15 targetSdkVersion 21 versionCode appVersion.code() versionName appVersion.releaseString() } … }