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

Automated library distribution to Maven

Jeroen Mols
February 16, 2016

Automated library distribution to Maven

Slides from my talk at GDG Brussels February 2016

Comprehensive talk about library distribution to either a public or private Maven repository, including topics such as:

- Introduction to Maven
- Maven adoption by Android
- Distributing to JCenter
- Distributing via JitPack
- Setting up your own Maven repository (Artifactory)
- Using Git as a Maven repository

Jeroen Mols

February 16, 2016
Tweet

More Decks by Jeroen Mols

Other Decks in Programming

Transcript

  1. AUTOMATED LIBRARY DISTRIBUTION TO MAVEN
    @MOLSJEROEN

    View Slide

  2. BEFORE SOFTWARE CAN BE REUSABLE
    IT FIRST HAS TO BE USABLE.
    Ralph Johnson

    View Slide

  3. MAVEN FUNDAMENTALS

    View Slide

  4. @MOLSJEROEN
    WHAT IS MAVEN
    ▸ Build automation tool
    1. Describes how software is built
    ‣ default conventions
    ‣ specify all exceptions
    2. Describes dependencies
    ‣ locally installed repository
    ‣ remote Maven repository

    View Slide

  5. @MOLSJEROEN
    HOW MAVEN HANDLES DEPENDENCIES
    ▸ Release identified by
    ▸ GroupId com.jeroenmols
    ▸ ArtifactId landscapevideocamera
    ▸ Version 1.1.3
    ▸ Multiple artifacts possible
    ▸ Library landscapevideocamera.aar
    ▸ Documentation javadoc.jar
    ▸ Sources sources.jar

    View Slide

  6. @MOLSJEROEN
    HOW MAVEN STORES DEPENDENCIES

    View Slide

  7. @MOLSJEROEN
    IMPORTANT CONSIDERATIONS
    ▸ Maven can only be used if:
    ▸ Repository reachable and online forever
    ▸ Existing artifacts never modified
    ▸ New versions come from same developer
    ▸ Code must always build immediately after checkout
    ▸ When doubt: add artifacts to version control

    View Slide

  8. @MOLSJEROEN
    ADOPTION BY ANDROID
    ▸ Gradle
    ▸ Specify Maven repositories to use
    ▸ Define dependencies (and configuration)
    ▸ Upload your own artifacts
    ▸ Local maven repository
    ▸ Support libraries
    ▸ Google play services

    View Slide

  9. @MOLSJEROEN
    GRADLE - USE MAVEN ARTIFACTS
    allprojects {

    repositories {

    jcenter()

    maven { url “http://mywebsite.com/mavenrepository" }

    }

    }
    dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile ‘com.android.support:appcompat-v7:23.1.0’

    compile ‘com.jeroenmols:landscapevideocamera:1.1.3'

    }

    View Slide

  10. @MOLSJEROEN
    GRADLE - USE MAVEN ARTIFACTS
    allprojects {

    repositories {

    jcenter()

    maven { url “http://mywebsite.com/mavenrepository" }

    }

    }
    dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile ‘com.android.support:appcompat-v7:23.1.0’

    compile ‘com.jeroenmols:landscapevideocamera:1.1.3'

    }

    View Slide

  11. @MOLSJEROEN
    GRADLE - USE MAVEN ARTIFACTS
    allprojects {

    repositories {

    jcenter()

    maven { url “http://mywebsite.com/mavenrepository" }

    }

    }
    dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile ‘com.android.support:appcompat-v7:23.1.0’

    compile ‘com.jeroenmols:landscapevideocamera:1.1.3'

    }

    View Slide

  12. @MOLSJEROEN
    GRADLE - USE MAVEN ARTIFACTS
    allprojects {

    repositories {

    jcenter()

    maven { url “http://mywebsite.com/mavenrepository" }

    }

    }
    dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile ‘com.android.support:appcompat-v7:23.1.0’

    compile ‘com.jeroenmols:landscapevideocamera:1.1.3’

    }
    GroupId ArtifactId Version

    View Slide

  13. @MOLSJEROEN
    GRADLE - UPLOAD MAVEN ARTIFACTS
    apply plugin: ‘maven'
    uploadArchives {

    repositories {

    mavenDeployer {

    repository(url: 'http://mywebsite/mavenrepository') {

    authentication(userName: 'myUsername',
    password: 'myPassword')

    }


    pom.project {

    groupId = ‘packageName’
    artifactId = 'libraryName'

    version = 'libraryVersion'

    packaging = 'aar'

    } } } }

    View Slide

  14. @MOLSJEROEN
    GRADLE - UPLOAD MAVEN ARTIFACTS
    apply plugin: ‘maven'
    uploadArchives {

    repositories {

    mavenDeployer {

    repository(url: 'http://mywebsite/mavenrepository') {

    authentication(userName: 'myUsername',
    password: 'myPassword')

    }


    pom.project {

    groupId = ‘packageName’
    artifactId = 'libraryName'

    version = 'libraryVersion'

    packaging = 'aar'

    } } } }

    View Slide

  15. @MOLSJEROEN
    GRADLE - UPLOAD MAVEN ARTIFACTS
    apply plugin: ‘maven'
    uploadArchives {

    repositories {

    mavenDeployer {

    repository(url: 'http://mywebsite/mavenrepository') {

    authentication(userName: 'myUsername',
    password: 'myPassword')

    }


    pom.project {

    groupId = ‘packageName’
    artifactId = 'libraryName'

    version = 'libraryVersion'

    packaging = 'aar'

    } } } }

    View Slide

  16. @MOLSJEROEN
    GRADLE - UPLOAD MAVEN ARTIFACTS
    apply plugin: ‘maven'
    uploadArchives {

    repositories {

    mavenDeployer {

    repository(url: 'http://mywebsite/mavenrepository') {

    authentication(userName: 'myUsername',
    password: 'myPassword')

    }


    pom.project {

    groupId = ‘packageName’
    artifactId = 'libraryName'

    version = 'libraryVersion'

    packaging = 'aar'

    } } } }

    View Slide

  17. THERE IS AN EASY WAY AND A HARD
    WAY. THE HARD PART IS FINDING THE
    EASY WAY.
    Dr. Lloyd

    View Slide

  18. PUBLIC DISTRIBUTION

    View Slide

  19. @MOLSJEROEN
    PUBLIC MAVEN REPOSITORIES
    repositories {

    jcenter()

    }
    ‣ Bintray
    ‣ Browse repository
    repositories {

    mavenCentral()

    }
    ‣ Sonatype
    ‣ Browse repository

    View Slide

  20. @MOLSJEROEN
    PUBLIC MAVEN REPOSITORIES
    repositories {

    jcenter()

    }
    ‣ Bintray
    ‣ Browse repository
    repositories {

    mavenCentral()

    }
    ‣ Sonatype
    ‣ Browse repository

    View Slide

  21. @MOLSJEROEN
    BINTRAY
    ▸ Attractive convenient UI
    ▸ Simple to use (no signing)
    ▸ Integrates with Github, Bitbucket, Twitter,…
    ▸ Download statistics
    ▸ Gradle/manual upload to staging
    ▸ Manually release to JCenter
    ▸ One click/automated sync to Maven Central

    View Slide

  22. @MOLSJEROEN

    View Slide

  23. @MOLSJEROEN

    View Slide

  24. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 1
    ‣ PROJECT_HOME/local.properties
    bintray.user=jeroenmols

    bintray.apikey=n1c3try
    ‣ PROJECT_HOME/build.gradle
    buildscript {

    dependencies {

    classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'

    classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'

    }

    }

    View Slide

  25. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 1
    ‣ PROJECT_HOME/local.properties
    bintray.user=jeroenmols

    bintray.apikey=n1c3try
    ‣ PROJECT_HOME/build.gradle
    buildscript {

    dependencies {

    classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'

    classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'

    }

    }

    View Slide

  26. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 1
    ‣ PROJECT_HOME/local.properties
    bintray.user=jeroenmols

    bintray.apikey=n1c3try
    ‣ PROJECT_HOME/build.gradle
    buildscript {

    dependencies {

    classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'

    classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'

    }

    }

    View Slide

  27. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    ext {

    bintrayRepo = 'maven'

    bintrayName = 'LandscapeVideoCamera'


    publishedGroupId = 'com.github.jeroenmols'

    libraryName = 'LandscapeVideoCamera'

    artifact = 'library'


    libraryDescription = 'Powerful custom Android Camera.’
    libraryVersion = '1.1.4'


    developerId = 'JeroenMols'

    developerName = 'Jeroen Mols'

    developerEmail = '[email protected]'

    }
    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/installv1.gradle'

    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/bintrayv1.gradle'

    View Slide

  28. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    ext {

    bintrayRepo = 'maven'

    bintrayName = 'LandscapeVideoCamera'


    publishedGroupId = 'com.github.jeroenmols'

    libraryName = 'LandscapeVideoCamera'

    artifact = 'library'


    libraryDescription = 'Powerful custom Android Camera.’
    libraryVersion = '1.1.4'


    developerId = 'JeroenMols'

    developerName = 'Jeroen Mols'

    developerEmail = '[email protected]'

    }
    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/installv1.gradle'

    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/bintrayv1.gradle'

    View Slide

  29. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    ext {

    bintrayRepo = 'maven'

    bintrayName = 'LandscapeVideoCamera'


    publishedGroupId = 'com.github.jeroenmols'

    libraryName = 'LandscapeVideoCamera'

    artifact = 'library'


    libraryDescription = 'Powerful custom Android Camera.’
    libraryVersion = '1.1.4'


    developerId = 'JeroenMols'

    developerName = 'Jeroen Mols'

    developerEmail = '[email protected]'

    }
    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/installv1.gradle'

    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/bintrayv1.gradle'

    View Slide

  30. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    ext {

    bintrayRepo = 'maven'

    bintrayName = 'LandscapeVideoCamera'


    publishedGroupId = 'com.github.jeroenmols'

    libraryName = 'LandscapeVideoCamera'

    artifact = 'library'


    libraryDescription = 'Powerful custom Android Camera.’
    libraryVersion = '1.1.4'


    developerId = 'JeroenMols'

    developerName = 'Jeroen Mols'

    developerEmail = '[email protected]'

    }
    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/installv1.gradle'

    apply from: 'https://raw.githubusercontent.com/attwellBrian/JCenter/master/bintrayv1.gradle'

    View Slide

  31. @MOLSJEROEN
    BINTRAY - UPLOAD ARTIFACTS 3
    ‣ $ ./gradlew assembleRelease bintrayUpload

    View Slide

  32. @MOLSJEROEN

    View Slide

  33. @MOLSJEROEN
    JITPACK.IO
    ▸ Zero configuration: no account, no set up, no opt-in
    ▸ Download statistics, Badges,…
    ▸ Supports snapshots
    ▸ No need to upload artifacts
    ▸ Builds any GitHub project (and more)
    ▸ Use Git tags to create a ‘formal’ release (optional)
    ▸ Gradle dependency on Jitpack repository

    View Slide

  34. @MOLSJEROEN
    JITPACK.IO - UPLOAD ARTIFACTS
    DO NOTHING

    View Slide

  35. @MOLSJEROEN
    JITPACK.IO - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    jcenter()

    maven { url "https://jitpack.io" }

    } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile 'com.github.JeroenMols:LandscapeVideoCamera:1.1.1'

    }

    View Slide

  36. @MOLSJEROEN
    JITPACK.IO - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    jcenter()

    maven { url "https://jitpack.io" }

    } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile 'com.github.JeroenMols:LandscapeVideoCamera:1.1.1'

    }

    View Slide

  37. @MOLSJEROEN
    JITPACK.IO - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    jcenter()

    maven { url "https://jitpack.io" }

    } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile 'com.github.JeroenMols:LandscapeVideoCamera:1.1.1'

    }

    View Slide

  38. @MOLSJEROEN
    JITPACK.IO - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    jcenter()

    maven { url "https://jitpack.io" }

    } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile ‘com.github.JeroenMols:LandscapeVideoCamera:
    3f900ec00b302f75f3d377cff0bdca37145fc89d'

    }

    View Slide

  39. @MOLSJEROEN
    JITPACK.IO - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    jcenter()

    maven { url "https://jitpack.io" }

    } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile ‘com.github.JeroenMols:LandscapeVideoCamera:
    develop-SNAPSHOT‘

    }

    View Slide

  40. I THINK, FUNDAMENTALLY, OPEN
    SOURCE DOES TEND TO BE MORE
    STABLE SOFTWARE.
    Linus Torvalds

    View Slide

  41. PRIVATE DISTRIBUTION

    View Slide

  42. @MOLSJEROEN
    ▸ Easy to set up Maven repository
    ▸ Cache remote repository artifacts
    ▸ Open source (free)
    ▸ Gradle plugin to do the upload
    ▸ Advanced features
    ▸ Backups?
    ▸ Cost/hassle of running a server?
    REPOSITORY MANAGER - ARTIFACTORY
    RELATED BLOGPOSTS

    View Slide

  43. @MOLSJEROEN

    View Slide

  44. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 1
    ‣ PROJECT_HOME/build.gradle
    buildscript {

    dependencies {
    classpath “org.jfrog.buildinfo:
    build-info-extractor-gradle:3.1.1"

    }

    }

    View Slide

  45. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 1
    ‣ PROJECT_HOME/build.gradle
    buildscript {

    dependencies {
    classpath “org.jfrog.buildinfo:
    build-info-extractor-gradle:3.1.1"

    }

    }

    View Slide

  46. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: 'maven-publish'
    def packageName = 'com.jeroenmols.awesomelibrary'

    def libraryVersion = '1.0.0'
    publishing {

    publications {

    aar(MavenPublication) {

    groupId = packageName

    version = libraryVersion

    artifactId = project.getName()

    artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

    } } }

    View Slide

  47. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: 'maven-publish'
    def packageName = 'com.jeroenmols.awesomelibrary'

    def libraryVersion = '1.0.0'
    publishing {

    publications {

    aar(MavenPublication) {

    groupId = packageName

    version = libraryVersion

    artifactId = project.getName()

    artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

    } } }

    View Slide

  48. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: 'maven-publish'
    def packageName = 'com.jeroenmols.awesomelibrary'

    def libraryVersion = '1.0.0'
    publishing {

    publications {

    aar(MavenPublication) {

    groupId = packageName

    version = libraryVersion

    artifactId = project.getName()

    artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

    } } }

    View Slide

  49. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: 'maven-publish'
    def packageName = 'com.jeroenmols.awesomelibrary'

    def libraryVersion = '1.0.0'
    publishing {

    publications {

    aar(MavenPublication) {

    groupId = packageName

    version = libraryVersion

    artifactId = project.getName()

    artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

    } } }

    View Slide

  50. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 2
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: 'maven-publish'
    def packageName = 'com.jeroenmols.awesomelibrary'

    def libraryVersion = '1.0.0'
    publishing {

    publications {

    aar(MavenPublication) {

    groupId = packageName

    version = libraryVersion

    artifactId = project.getName()

    artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

    } } }

    View Slide

  51. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 3
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: ‘com.jfrog.artifactory'
    artifactory {

    contextUrl = 'http://localhost:8081/artifactory'

    publish {

    repository {

    repoKey = 'libs-release-local'

    username = "admin"

    password = "password"

    }

    defaults {

    publications('aar')

    publishArtifacts = true

    publishPom = true

    }

    } }

    View Slide

  52. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 3
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: ‘com.jfrog.artifactory'
    artifactory {

    contextUrl = 'http://localhost:8081/artifactory'

    publish {

    repository {

    repoKey = 'libs-release-local'

    username = "admin"

    password = "password"

    }

    defaults {

    publications('aar')

    publishArtifacts = true

    publishPom = true

    }

    } }

    View Slide

  53. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 3
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: ‘com.jfrog.artifactory'
    artifactory {

    contextUrl = 'http://localhost:8081/artifactory'

    publish {

    repository {

    repoKey = 'libs-release-local'

    username = "admin"

    password = "password"

    }

    defaults {

    publications('aar')

    publishArtifacts = true

    publishPom = true

    }

    } }

    View Slide

  54. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 3
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: ‘com.jfrog.artifactory'
    artifactory {

    contextUrl = 'http://localhost:8081/artifactory'

    publish {

    repository {

    repoKey = 'libs-release-local'

    username = "admin"

    password = "password"

    }

    defaults {

    publications('aar')

    publishArtifacts = true

    publishPom = true

    }

    } }

    View Slide

  55. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 3
    ‣ LIBRARY_HOME/build.gradle
    apply plugin: ‘com.jfrog.artifactory'
    artifactory {

    contextUrl = 'http://localhost:8081/artifactory'

    publish {

    repository {

    repoKey = 'libs-release-local'

    username = "admin"

    password = "password"

    }

    defaults {

    publications('aar')

    publishArtifacts = true

    publishPom = true

    }

    } }

    View Slide

  56. @MOLSJEROEN
    ARTIFACTORY - UPLOAD ARTIFACTS 4
    ▸ $ gradle assembleRelease artifactoryPublish

    View Slide

  57. @MOLSJEROEN
    ARTIFACTORY - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {
    url “http://localhost:8081/artifactory/libs-release-local"
    } } }
    ‣ PROJECT_HOME/build.gradle
    dependencies {

    compile 'com.jeroenmols.awesomelibrary:1.0.0'

    }

    View Slide

  58. @MOLSJEROEN
    ARTIFACTORY - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {
    url “http://localhost:8081/artifactory/libs-release-local"
    } } }
    ‣ PROJECT_HOME/build.gradle
    dependencies {

    compile 'com.jeroenmols.awesomelibrary:1.0.0'

    }

    View Slide

  59. @MOLSJEROEN
    ARTIFACTORY - CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {
    url “http://localhost:8081/artifactory/libs-release-local"
    } } }
    ‣ PROJECT_HOME/build.gradle
    dependencies {

    compile 'com.jeroenmols.awesomelibrary:1.0.0'

    }

    View Slide

  60. @MOLSJEROEN
    WAGON-GIT
    ▸ Use a Git as a Maven repository
    ▸ Supports GitHub and BitBucket (public or private)
    ▸ Open source (free)
    ▸ Maven plugin to do the upload
    ▸ Inherent backups and remote access
    RELATED BLOGPOST

    View Slide

  61. @MOLSJEROEN

    View Slide

  62. @MOLSJEROEN

    View Slide

  63. @MOLSJEROEN
    WAGON-GIT - UPLOAD ARTIFACTS 1
    ▸ LIBRARY_HOME/gradle.properties
    ARTIFACT_VERSION=1.0.0

    ARTIFACT_NAME=landscapevideocamera

    ARTIFACT_PACKAGE=com.jeroenmols.landscapevideocamera
    ARTIFACT_PACKAGING=aar


    BITBUCKET_TEAM=jmolsmobile

    REPOSITORY_NAME=maven_repository
    ▸ PROJECT_HOME/gradle.properties
    USERNAME=

    PASSWORD=

    View Slide

  64. @MOLSJEROEN
    WAGON-GIT - UPLOAD ARTIFACTS 1
    ▸ LIBRARY_HOME/gradle.properties
    ARTIFACT_VERSION=1.0.0

    ARTIFACT_NAME=landscapevideocamera

    ARTIFACT_PACKAGE=com.jeroenmols.landscapevideocamera
    ARTIFACT_PACKAGING=aar


    BITBUCKET_TEAM=jmolsmobile

    REPOSITORY_NAME=maven_repository
    ▸ PROJECT_HOME/gradle.properties
    USERNAME=

    PASSWORD=

    View Slide

  65. @MOLSJEROEN
    WAGON-GIT - UPLOAD ARTIFACTS 1
    ▸ LIBRARY_HOME/gradle.properties
    ARTIFACT_VERSION=1.0.0

    ARTIFACT_NAME=landscapevideocamera

    ARTIFACT_PACKAGE=com.jeroenmols.landscapevideocamera
    ARTIFACT_PACKAGING=aar


    BITBUCKET_TEAM=jmolsmobile

    REPOSITORY_NAME=maven_repository
    ▸ PROJECT_HOME/gradle.properties
    USERNAME=

    PASSWORD=

    View Slide

  66. @MOLSJEROEN
    WAGON-GIT - UPLOAD ARTIFACTS 1
    ▸ LIBRARY_HOME/gradle.properties
    ARTIFACT_VERSION=1.0.0

    ARTIFACT_NAME=landscapevideocamera

    ARTIFACT_PACKAGE=com.jeroenmols.landscapevideocamera
    ARTIFACT_PACKAGING=aar


    BITBUCKET_TEAM=jmolsmobile

    REPOSITORY_NAME=maven_repository
    ▸ PROJECT_HOME/gradle.properties
    USERNAME=

    PASSWORD=

    View Slide

  67. @MOLSJEROEN
    WAGON-GIT - UPLOAD ARTIFACTS 2
    ▸ LIBRARY_HOME/build.gradle
    apply from: 'https://raw.githubusercontent.com/JeroenMols/
    GitAsMaven/master/publish-bitbucket.gradle'
    ▸ $ gradle assembleRelease uploadArchives

    View Slide

  68. @MOLSJEROEN
    CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {

    credentials {

    username ''

    password ‘'

    }

    url "https://api.bitbucket.org/1.0/repositories/"
    + “//raw/releases"

    } } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile "com.jeroenmols:landscapevideocamera:"

    }

    View Slide

  69. @MOLSJEROEN
    CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {

    credentials {

    username ''

    password ‘'

    }

    url "https://api.bitbucket.org/1.0/repositories/"
    + “//raw/releases"

    } } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile “com.jeroenmols:landscapevideocamera:"

    }

    View Slide

  70. @MOLSJEROEN
    CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {

    credentials {

    username ''

    password ‘'

    }

    url "https://api.bitbucket.org/1.0/repositories/"
    + “//raw/releases"

    } } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile “com.jeroenmols:landscapevideocamera:"

    }

    View Slide

  71. @MOLSJEROEN
    CONSUME ARTIFACTS
    ‣ PROJECT_HOME/build.gradle
    allprojects {

    repositories {

    maven {

    credentials {

    username ''

    password ‘'

    }

    url "https://api.bitbucket.org/1.0/repositories/"
    + “//raw/releases"

    } } }
    ‣ MODULE_HOME/build.gradle
    dependencies {

    compile "com.jeroenmols:landscapevideocamera:"

    }

    View Slide

  72. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT
    ▸ Dramatically simplifies configuration
    ▸ Check for existing artifacts
    ▸ Bitbucket authentication

    View Slide

  73. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 1
    ▸ PROJECT_HOME/build.gradle
    apply plugin: 'maven'

    uploadArchives {

    repositories.mavenDeployer {

    configuration = configurations.deployLibrary

    repository(url: 'git:releases://[email protected]:'
    + COMPANY + '/' + REPOSITORY_NAME + '.git ')


    pom.project {

    groupId = ARTIFACT_PACKAGE

    version = ARTIFACT_VERSION

    artifactId = ARTIFACT_NAME

    packaging = ARTIFACT_PACKAGING

    } } }

    View Slide

  74. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 1
    ▸ PROJECT_HOME/build.gradle
    apply plugin: 'maven'

    uploadArchives {

    repositories.mavenDeployer {

    configuration = configurations.deployLibrary

    repository(url: 'git:releases://[email protected]:'
    + COMPANY + '/' + REPOSITORY_NAME + '.git ')


    pom.project {

    groupId = ARTIFACT_PACKAGE

    version = ARTIFACT_VERSION

    artifactId = ARTIFACT_NAME

    packaging = ARTIFACT_PACKAGING

    } } }

    View Slide

  75. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 1
    ▸ PROJECT_HOME/build.gradle
    apply plugin: 'maven'

    uploadArchives {

    repositories.mavenDeployer {

    configuration = configurations.deployLibrary

    repository(url: 'git:releases://[email protected]:'
    + COMPANY + '/' + REPOSITORY_NAME + '.git ')


    pom.project {

    groupId = ARTIFACT_PACKAGE

    version = ARTIFACT_VERSION

    artifactId = ARTIFACT_NAME

    packaging = ARTIFACT_PACKAGING

    } } }

    View Slide

  76. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 1
    ▸ PROJECT_HOME/build.gradle
    apply plugin: 'maven'

    uploadArchives {

    repositories.mavenDeployer {

    configuration = configurations.deployLibrary

    repository(url: 'git:releases://[email protected]:'
    + COMPANY + '/' + REPOSITORY_NAME + '.git ')


    pom.project {

    groupId = ARTIFACT_PACKAGE

    version = ARTIFACT_VERSION

    artifactId = ARTIFACT_NAME

    packaging = ARTIFACT_PACKAGING

    } } }

    View Slide

  77. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 2
    task androidJavadocs(type: Javadoc) {

    failOnError false

    source = android.sourceSets.main.java.sourceFiles

    }


    task androidSourcesJar(type: Jar) {

    classifier = 'sources'

    from android.sourceSets.main.java.sourceFiles

    }


    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {

    classifier = 'javadoc'

    from androidJavadocs.destinationDir

    }


    artifacts {

    archives androidSourcesJar

    archives androidJavadocsJar

    }

    View Slide

  78. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 2
    task androidJavadocs(type: Javadoc) {

    failOnError false

    source = android.sourceSets.main.java.sourceFiles

    }


    task androidSourcesJar(type: Jar) {

    classifier = 'sources'

    from android.sourceSets.main.java.sourceFiles

    }


    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {

    classifier = 'javadoc'

    from androidJavadocs.destinationDir

    }


    artifacts {

    archives androidSourcesJar

    archives androidJavadocsJar

    }

    View Slide

  79. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 3
    repositories {

    maven {
    url "https://raw.github.com/synergian/wagon-git/releases"
    } }


    configurations {

    deployLibrary

    }


    dependencies {

    deployLibrary "ar.com.synergian:wagon-git:0.2.0"

    }

    View Slide

  80. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 3
    repositories {

    maven {
    url "https://raw.github.com/synergian/wagon-git/releases"
    } }


    configurations {

    deployLibrary

    }


    dependencies {

    deployLibrary "ar.com.synergian:wagon-git:0.2.0"

    }

    View Slide

  81. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - SIMPLIFY CONFIGURATION 3
    repositories {

    maven {
    url "https://raw.github.com/synergian/wagon-git/releases"
    } }


    configurations {

    deployLibrary

    }


    dependencies {

    deployLibrary "ar.com.synergian:wagon-git:0.2.0"

    }

    View Slide

  82. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 1
    uploadArchives.dependsOn lookForArtifacts
    task lookForArtifacts {

    doLast {

    def libraryName = ARTIFACT_NAME + '-' + ARTIFACT_VERSION + '.aar'

    def repoPath = ARTIFACT_PACKAGE.replace(".", "/") + "/"
    + ARTIFACT_NAME + "/" + ARTIFACT_VERSION + "/" + libraryName

    def repositoryUrl = 'https://api.bitbucket.org/1.0/repositories/'
    + COMPANY + '/' + REPOSITORY_NAME + '/raw/releases/' + repoPath

    if (urlExists(repositoryUrl)) {

    throw new RuntimeException(“Artifact exists:" + ARTIFACT_VERSION)

    }

    return true

    } }

    View Slide

  83. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 1
    uploadArchives.dependsOn lookForArtifacts
    task lookForArtifacts {

    doLast {

    def libraryName = ARTIFACT_NAME + '-' + ARTIFACT_VERSION + '.aar'

    def repoPath = ARTIFACT_PACKAGE.replace(".", "/") + "/"
    + ARTIFACT_NAME + "/" + ARTIFACT_VERSION + "/" + libraryName

    def repositoryUrl = 'https://api.bitbucket.org/1.0/repositories/'
    + COMPANY + '/' + REPOSITORY_NAME + '/raw/releases/' + repoPath

    if (urlExists(repositoryUrl)) {

    throw new RuntimeException(“Artifact exists:" + ARTIFACT_VERSION)

    }

    return true

    } }

    View Slide

  84. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 1
    uploadArchives.dependsOn lookForArtifacts
    task lookForArtifacts {

    doLast {

    def libraryName = ARTIFACT_NAME + '-' + ARTIFACT_VERSION + '.aar'

    def repoPath = ARTIFACT_PACKAGE.replace(".", "/") + "/"
    + ARTIFACT_NAME + "/" + ARTIFACT_VERSION + "/" + libraryName

    def repositoryUrl = 'https://api.bitbucket.org/1.0/repositories/'
    + COMPANY + '/' + REPOSITORY_NAME + '/raw/releases/' + repoPath

    if (urlExists(repositoryUrl)) {

    throw new RuntimeException(“Artifact exists:" + ARTIFACT_VERSION)

    }

    return true

    } }

    View Slide

  85. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 1
    uploadArchives.dependsOn lookForArtifacts
    task lookForArtifacts {

    doLast {

    def libraryName = ARTIFACT_NAME + '-' + ARTIFACT_VERSION + '.aar'

    def repoPath = ARTIFACT_PACKAGE.replace(".", "/") + "/"
    + ARTIFACT_NAME + "/" + ARTIFACT_VERSION + "/" + libraryName

    def repositoryUrl = 'https://api.bitbucket.org/1.0/repositories/'
    + COMPANY + '/' + REPOSITORY_NAME + '/raw/releases/' + repoPath

    if (urlExists(repositoryUrl)) {

    throw new RuntimeException(“Artifact exists:" + ARTIFACT_VERSION)

    }

    return true

    } }

    View Slide

  86. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 1
    uploadArchives.dependsOn lookForArtifacts
    task lookForArtifacts {

    doLast {

    def libraryName = ARTIFACT_NAME + '-' + ARTIFACT_VERSION + '.aar'

    def repoPath = ARTIFACT_PACKAGE.replace(".", "/") + "/"
    + ARTIFACT_NAME + "/" + ARTIFACT_VERSION + "/" + libraryName

    def repositoryUrl = 'https://api.bitbucket.org/1.0/repositories/'
    + COMPANY + '/' + REPOSITORY_NAME + '/raw/releases/' + repoPath

    if (urlExists(repositoryUrl)) {

    throw new RuntimeException(“Artifact exists:" + ARTIFACT_VERSION)

    }

    return true

    } }

    View Slide

  87. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 2
    def urlExists(String repositoryUrl) {

    try {

    def conn = (HttpURLConnection) new URL(repositoryUrl).openConnection()


    conn.setRequestProperty("Authorization","Basic " +
    getBase64EncodedCredentials())

    conn.setConnectTimeout(10000)

    conn.setReadTimeout(10000)

    conn.setRequestMethod("HEAD")


    def responseCode = connection.getResponseCode()

    println("responseCode: " + responseCode)


    return (200 == responseCode)

    } catch (IOException ignored) {

    return false

    } }

    View Slide

  88. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 2
    def urlExists(String repositoryUrl) {

    try {

    def conn = (HttpURLConnection) new URL(repositoryUrl).openConnection()


    conn.setRequestProperty("Authorization","Basic " +
    getBase64EncodedCredentials())

    conn.setConnectTimeout(10000)

    conn.setReadTimeout(10000)

    conn.setRequestMethod("HEAD")


    def responseCode = connection.getResponseCode()

    println("responseCode: " + responseCode)


    return (200 == responseCode)

    } catch (IOException ignored) {

    return false

    } }

    View Slide

  89. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - EXISTING ARTIFACTS 2
    def urlExists(String repositoryUrl) {

    try {

    def conn = (HttpURLConnection) new URL(repositoryUrl).openConnection()


    conn.setRequestProperty("Authorization","Basic " +
    getBase64EncodedCredentials())

    conn.setConnectTimeout(10000)

    conn.setReadTimeout(10000)

    conn.setRequestMethod("HEAD")


    def responseCode = connection.getResponseCode()

    println("responseCode: " + responseCode)


    return (200 == responseCode)

    } catch (IOException ignored) {

    return false

    } }

    View Slide

  90. @MOLSJEROEN
    PUBLISH-BITBUCKET SCRIPT - BITBUCKET AUTHENTICATION
    def getBase64EncodedCredentials() {

    def s = USERNAME + ":" + PASSWORD;

    return s.bytes.encodeBase64().toString()

    }

    View Slide

  91. @MOLSJEROEN
    CREDITS
    ▸ Distributing Android Libraries via jCenter for Gradle Importing @attwellbrian
    ▸ A private Maven repository in 30 min @molsjeroen
    ▸ Getting the most out of Artifactory @molsjeroen
    ▸ Git as a secure private Maven repository @molsjeroen

    View Slide

  92. @MOLSJEROEN
    GITHUB SAMPLES
    ▸ Bintray example @attwellbrian
    ▸ Artifactory example @molsjeroen
    ▸ Wagon-git example @molsjeroen

    View Slide

  93. @MOLSJEROEN
    OTHER INTERESTING ARTICLES
    ▸ Gradle dependency and local repository @turhanoz
    ▸ Creating and publishing an Android library @Etienne_Lawlor
    ▸ Publish with Gradle on BitBucket @mul0w
    ▸ Gradle Maven Push script @chrisbanes

    View Slide

  94. @MOLSJEROEN
    MANY THANKS
    ▸ Jeroen Mols (Belgium)
    ▸ @MolsJeroen
    ▸ http://jeroenmols.com

    View Slide