0
votes

I'm trying to publish a snapshot of grails 3 plugin to remote maven repository (Artifactory). Here is my build script:

import org.springframework.util.StringUtils

buildscript {
    ext {
        grailsVersion = project.grailsVersion
    }
    repositories {
        jcenter()
        mavenLocal()
        mavenCentral()
        maven { url "https://repo.grails.org/grails/core" }
        maven { url "${artifactory_contextUrl}"
            credentials {
                username "${artifactory_user}"
                password "${artifactory_password}"
            }
            name = "remote-maven-repo"
        }
    }
    dependencies {
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.1.2"
    }
}

plugins {
    id "io.spring.dependency-management" version "0.5.2.RELEASE"
    id "com.jfrog.bintray" version "1.2"
}

String baseVersion = "0.1.0-%customer%-SNAPSHOT"
String currentVersion = "$baseVersion".replaceAll('%customer%',property('plugin.default.customer').toUpperCase())
version currentVersion
group "org.grails.plugins"

apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: "spring-boot"
apply plugin: "org.grails.grails-plugin"
apply plugin: "org.grails.grails-gsp"

println "Current customer mode: [${property("plugin.default.customer")}]"

ext {
    grailsVersion = project.grailsVersion
    gradleWrapperVersion = project.gradleWrapperVersion
}

String defaultVersion = "default"


// Custom versioning scheme, take version of dependency with 'default' version from gradle.preperties
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.version == defaultVersion) {
            customer = property("plugin.default.customer")
            String version = resolveDefaultVersion(details.requested.group, details.requested.name, customer)
            details.useVersion(version)
        }
    }
}

configurations.all {
    // check for updates every build
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}



String resolveDefaultVersion(String group, String name, String customer) {
    if(group == 'com.mycompany.domain' && name == 'custom-lib'){
        String version = property("custom-lib.${customer}.version")
        println "resolved artifact [$group.$name] version [$version]"
        return version
    }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "https://repo.grails.org/grails/core" }
    add buildscript.repositories.getByName("remote-maven-repo")
}

dependencyManagement {
    imports {
        mavenBom "org.grails:grails-bom:$grailsVersion"
    }
    applyMavenExclusions false
}


dependencies {
    provided 'org.springframework.boot:spring-boot-starter-logging'
    provided "org.springframework.boot:spring-boot-starter-actuator"
    provided "org.springframework.boot:spring-boot-autoconfigure"
    provided "org.springframework.boot:spring-boot-starter-tomcat"

    provided "org.grails:grails-web-boot"
    provided "org.grails:grails-dependencies"
    provided 'javax.servlet:javax.servlet-api:3.1.0'

    testCompile "org.grails:grails-plugin-testing"

    console "org.grails:grails-console"

    //Security
    compile "org.grails.plugins:spring-security-core:3.0.0.M1"
    compile "org.grails.plugins:spring-security-acl:3.0.0.M1"
    //Not grails3 compatible
    //compile "org.grails.plugins:spring-security-oauth2-provider:2.0-RC5"

    compile "org.grails.plugins:hibernate:4.3.10.6"
   //configurable customer-dependent dependency, take version from gradle.properties 
    compile group: "com.mycompany.domain", name:"custom-lib", version:"$defaultVersion", changing: true
}

task wrapper(type: Wrapper) {
    gradleVersion = gradleWrapperVersion
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            // gradle can't handle custom versioning scheme and will left com.mycompany.domain.custom-lib version value as 'default' in generated pom, we will fix it here.
            pom.withXml {
                asNode().get('dependencies').get(0).get('dependency').each { dep ->
                    String pomVer = dep.get("version").text()
                    String pomArtifactId = dep.get("artifactId").text()
                    String pomGroupId = dep.get("groupId").text()
                    if(pomVer == defaultVersion){
                        String customer = property("plugin.default.customer")
                        dep.get("version").get(0).setValue(resolveDefaultVersion(pomGroupId, pomArtifactId, customer))
                    }else if (StringUtils.isEmpty(pomVer)){
                        //gradle also left dependencies with provided scope in pom without version --> remove these dependencies
                        dep.replaceNode {}
                    }
                }
            }
        }
    }
    repositories {
        maven {
            name 'myArtifactory'
            url "${artifactoryContextUrl}/${(project.version.endsWith('-SNAPSHOT') ? snapshotRepoKey : releaseRepoKey)}"
            credentials {
                username = artifactory_user
                password = artifactory_password
            }
        }
    }
}


install.repositories.mavenInstaller.pom.whenConfigured { pom ->
    pom.dependencies.findAll { it.version == defaultVersion }.each { dep ->
        dep.version = resolveDefaultVersion(dep.groupId, dep.artifactId, property("plugin.default.customer"))
    }
}

When I'm running gradle install - to install plugin in local m2 repo everything works fine, and pom looks good, it has dependencies with exactly the same scopes and versions, also provided dependencies are excluded from pom during publishing to local repository. When I'm running gradle publishMavenJavaPublicationToMyArtifactoryRepository pom is looking quite strange, gradle is ignoring defined in build script dependencies scopes and always using runtime. As an example:

pom after gradle install:

<dependency>
      <groupId>org.grails.plugins</groupId>
      <artifactId>spring-security-acl</artifactId>
      <version>3.0.0.M1</version>
      <scope>compile</scope>
</dependency>

pom after gradle publishMavenJavaPublicationToMyArtifactoryRepository:

<dependency>
      <groupId>org.grails.plugins</groupId>
      <artifactId>spring-security-acl</artifactId>
      <version>3.0.0.M1</version>
      <scope>runtime</scope>
</dependency>

Also pom after gradle install doesn't contain dependencies with scope provided. Pom.xml after gradle publishMavenJavaPublicationToMyArtifactoryRepository contains

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <scope>provided</scope>
</dependency>

without version, gradle doesn't like that.

Why am I receiving such different results? How can I generate the same pom for gradle publishMavenJavaPublicationToMyArtifactoryRepository as for gradle install. I don't like an opportunity to edit pom in publications section. Any help is highly appreciated.

1

1 Answers

2
votes

This is a known limitation of the incubating new maven-publish plugin. The install task uses the "old"/stable Install task. If you really rely on these scopes, one workaround might be to use the gradle based "uploadArchives" task instead of relying on the bintray plugin for publishing your archives. Alternatively you can implement a fix by using the xml hooks of the new publish plugin.