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

  2. BEFORE SOFTWARE CAN BE REUSABLE IT FIRST HAS TO BE

    USABLE. Ralph Johnson
  3. MAVEN FUNDAMENTALS

  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
  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
  6. @MOLSJEROEN HOW MAVEN STORES DEPENDENCIES

  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
  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
  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'
 }
  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'
 }
  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'
 }
  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
  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'
 } } } }
  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'
 } } } }
  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'
 } } } }
  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'
 } } } }
  17. THERE IS AN EASY WAY AND A HARD WAY. THE

    HARD PART IS FINDING THE EASY WAY. Dr. Lloyd
  18. PUBLIC DISTRIBUTION

  19. @MOLSJEROEN PUBLIC MAVEN REPOSITORIES repositories {
 jcenter()
 } ‣ Bintray

    ‣ Browse repository repositories {
 mavenCentral()
 } ‣ Sonatype ‣ Browse repository
  20. @MOLSJEROEN PUBLIC MAVEN REPOSITORIES repositories {
 jcenter()
 } ‣ Bintray

    ‣ Browse repository repositories {
 mavenCentral()
 } ‣ Sonatype ‣ Browse repository
  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
  22. @MOLSJEROEN

  23. @MOLSJEROEN

  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'
 }
 }
  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'
 }
 }
  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'
 }
 }
  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'
  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'
  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'
  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'
  31. @MOLSJEROEN BINTRAY - UPLOAD ARTIFACTS 3 ‣ $ ./gradlew assembleRelease

    bintrayUpload
  32. @MOLSJEROEN

  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
  34. @MOLSJEROEN JITPACK.IO - UPLOAD ARTIFACTS DO NOTHING

  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'
 }
  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'
 }
  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'
 }
  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'
 }
  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‘
 }
  40. I THINK, FUNDAMENTALLY, OPEN SOURCE DOES TEND TO BE MORE

    STABLE SOFTWARE. Linus Torvalds
  41. PRIVATE DISTRIBUTION

  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
  43. @MOLSJEROEN

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


    dependencies { classpath “org.jfrog.buildinfo: build-info-extractor-gradle:3.1.1"
 }
 }
  45. @MOLSJEROEN ARTIFACTORY - UPLOAD ARTIFACTS 1 ‣ PROJECT_HOME/build.gradle buildscript {


    dependencies { classpath “org.jfrog.buildinfo: build-info-extractor-gradle:3.1.1"
 }
 }
  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")
 } } }
  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")
 } } }
  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")
 } } }
  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")
 } } }
  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")
 } } }
  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
 }
 } }
  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
 }
 } }
  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
 }
 } }
  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
 }
 } }
  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
 }
 } }
  56. @MOLSJEROEN ARTIFACTORY - UPLOAD ARTIFACTS 4 ▸ $ gradle assembleRelease

    artifactoryPublish
  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'
 }
  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'
 }
  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'
 }
  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
  61. @MOLSJEROEN

  62. @MOLSJEROEN

  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=<username_here>
 PASSWORD=<password_here>
  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=<username_here>
 PASSWORD=<password_here>
  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=<username_here>
 PASSWORD=<password_here>
  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=<username_here>
 PASSWORD=<password_here>
  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
  68. @MOLSJEROEN CONSUME ARTIFACTS ‣ PROJECT_HOME/build.gradle allprojects {
 repositories {
 maven

    {
 credentials {
 username '<bitbucket_username>'
 password ‘<bitbucket_password>'
 }
 url "https://api.bitbucket.org/1.0/repositories/" + “<bitbucket_team>/<repository>/raw/releases"
 } } } ‣ MODULE_HOME/build.gradle dependencies {
 compile "com.jeroenmols:landscapevideocamera:<version>"
 }
  69. @MOLSJEROEN CONSUME ARTIFACTS ‣ PROJECT_HOME/build.gradle allprojects {
 repositories {
 maven

    {
 credentials {
 username '<bitbucket_username>'
 password ‘<bitbucket_password>'
 }
 url "https://api.bitbucket.org/1.0/repositories/" + “<bitbucket_team>/<repository>/raw/releases"
 } } } ‣ MODULE_HOME/build.gradle dependencies {
 compile “com.jeroenmols:landscapevideocamera:<version>"
 }
  70. @MOLSJEROEN CONSUME ARTIFACTS ‣ PROJECT_HOME/build.gradle allprojects {
 repositories {
 maven

    {
 credentials {
 username '<bitbucket_username>'
 password ‘<bitbucket_password>'
 }
 url "https://api.bitbucket.org/1.0/repositories/" + “<bitbucket_team>/<repository>/raw/releases"
 } } } ‣ MODULE_HOME/build.gradle dependencies {
 compile “com.jeroenmols:landscapevideocamera:<version>"
 }
  71. @MOLSJEROEN CONSUME ARTIFACTS ‣ PROJECT_HOME/build.gradle allprojects {
 repositories {
 maven

    {
 credentials {
 username '<bitbucket_username>'
 password ‘<bitbucket_password>'
 }
 url "https://api.bitbucket.org/1.0/repositories/" + “<bitbucket_team>/<repository>/raw/releases"
 } } } ‣ MODULE_HOME/build.gradle dependencies {
 compile "com.jeroenmols:landscapevideocamera:<version>"
 }
  72. @MOLSJEROEN PUBLISH-BITBUCKET SCRIPT ▸ Dramatically simplifies configuration ▸ Check for

    existing artifacts ▸ Bitbucket authentication
  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
 } } }
  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
 } } }
  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
 } } }
  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
 } } }
  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
 }
  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
 }
  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"
 }
  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"
 }
  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"
 }
  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
 } }
  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
 } }
  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
 } }
  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
 } }
  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
 } }
  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
 } }
  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
 } }
  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
 } }
  90. @MOLSJEROEN PUBLISH-BITBUCKET SCRIPT - BITBUCKET AUTHENTICATION def getBase64EncodedCredentials() {
 def

    s = USERNAME + ":" + PASSWORD;
 return s.bytes.encodeBase64().toString()
 }
  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
  92. @MOLSJEROEN GITHUB SAMPLES ▸ Bintray example @attwellbrian ▸ Artifactory example

    @molsjeroen ▸ Wagon-git example @molsjeroen
  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
  94. @MOLSJEROEN MANY THANKS ▸ Jeroen Mols (Belgium) ▸ @MolsJeroen ▸

    http://jeroenmols.com