[JIRA] (JENKINS-59108) Artifactory plugin can't publish Gradle builds from within Docker

9 views
Skip to first unread message

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 3:58:02 PM8/27/19
to jenkinsc...@googlegroups.com
Kevin Phillips created an issue
 
Jenkins / Bug JENKINS-59108
Artifactory plugin can't publish Gradle builds from within Docker
Issue Type: Bug Bug
Assignee: Eyal Ben Moshe
Components: artifactory-plugin, gradle-plugin
Created: 2019-08-27 19:57
Environment: Linux
Jenkins v2.189
Artifactory Plugin v3.3.2
Gradle Plugin v1.33
Pipeline Plugin v2.6
Priority: Critical Critical
Reporter: Kevin Phillips

We have been using the Gradle and Artifactory plugins on our production Jenkins instance for years using the traditional freestyle job types. We are now working on migrating all of our production builds to use Jenkins Pipeline scripts. As part of that transition we have a need to build Java projects using Gradle and publish artifacts generated by these projects to Artifactory. Further, nearly all of our production builds are performed within dockerized build environments so all build time dependencies can be managed and reproduced. However, I can not for the life of me find a way to get a simple Gradle operation to publish artifacts along with the requisite build info and back-links to the Artifactory build information. Here is an brief example of the sort of build configuration we are looking to use (in scripted pipeline format):

 

node {
  stage ("build") {
    // checkout project sources
    checkout scm

    // get artifactory connection parameters
    def artifactory_server = Artifactory.server 'server-id'

    // construct a gradle build object
    def gradle_proxy = Artifactory.newGradleBuild()

    // configure the gradle build environment to use the gradle wrapper
    gradle_proxy.deployer repo: "snapshot-repo", server: artifactory_server
    gradle_proxy.useWrapper = true  // <---- this option appears to be undocumented but I found it when I went looking through the source for the plugin

    // build docker build environment from the source repo
    container = docker.build("./docker")

    // launch the build environment
    container.inside() {
      // try to build the gradle project...
      // this operation fails
      build_info = gradle_proxy.run rootDir: "master", buildFile: "build.gradle", tasks: ":subproj:artifactoryPublish"

      // publish build info if/when the build succeeds
      artifactory_server.publishBuildInfo buildInfo
    }
  }
} 

 

 

When running this build, the call to the gradle_proxy.run task produces the following error:

expected to call org.jfrog.hudson.pipeline.common.types.packageManagerBuilds.GradleBuild.run but wound up catching ArtifactoryGradleBuild; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/ 

I will say that I am sort of flying blind here. Most of the docs and examples I've found online that integrate Gradle, Jenkins and Artifactory assume that you are using a freestyle job configuration or that you are using a Gradle binary (ie: not the Gradle wrapper) which is deployed explicitly by Jenkins, which is not something we can/want to do in our case. Also, I am not sure if Docker is somehow playing a part in this problem because none of the examples I've found online to orchestrate this type of build use Docker. So maybe this behavior / result is unique to this specific combination of build tools.

If anyone can tell me whether or not I've missed something obvious here in my build script, or perhaps point me to some documentation or examples that shows how to orchestrate this type of build, I would really appreciate it.

Add Comment Add Comment
 
This message was sent by Atlassian Jira (v7.11.2#711002-sha1:fdc329d)

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 4:02:02 PM8/27/19
to jenkinsc...@googlegroups.com
Kevin Phillips commented on Bug JENKINS-59108
 
Re: Artifactory plugin can't publish Gradle builds from within Docker

I probably should mention that I have successfully managed to get parts of the jenkins-gradle-artifactory integration to work in isolation from one another. For example, if I create a spec file that lists all the artifacts produced by the Gradle build and pass that to the Artifactory server instance in the Jenkins build script, I can publish the artifacts and build information is correctly attached to the files, and hyperlinks to the buildinfo records are added to the Jenkins build pages. However this solution forces me to duplicate the list of artifacts - once in the build.gradle file and again in the file spec in the Jenkinsfile. So sooner or later one of these is bound to get out of sync and break.

Similarly, if I don't use any of the Jenkins Artifactory plugin logic directly, but merely call `./master/gradlew artifactoryPublish`, Gradle will successfully publish files to Artifactory. However, the Jenkins build info is not attached to the published artifacts and the hyperlinks in the Jenkins build pages are not added, so this is not a workable solution either.

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 6:19:02 PM8/27/19
to jenkinsc...@googlegroups.com

I just create a new test build with a smaller Gradle project that didn't have any dependencies that required a Dockerized build environment (ie: so I could do the same build sequence without the Docker dependency) and I still received the error/warning message mentioned above. However, I hit another Gradle error that is different and not obviously related to the previous warning:
An exception occurred applying plugin request [id: 'com.jfrog.artifactory', version: '4.9.8']
> Failed to apply plugin [id 'com.jfrog.artifactory']
> Cannot cast object 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention@4c55d658' with class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention' to class 'org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention'
I'm not yet sure what is breaking here but my original problem statement still holds: I am unable to publish build info for a Gradle build that uses the Artifactory plugin.

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 6:23:02 PM8/27/19
to jenkinsc...@googlegroups.com

So, just to be clear, my simplified build configuration that produced the previous error message looks like this:

node  {
    stage ("build") {
        checkout scm
       
        def artifactory_server = Artifactory.server 'server-id' 
        
        def gradle_proxy = Artifactory.newGradleBuild()          
        gradle_proxy.deployer repo: 'snapshot-repo', server: artifactory_server
        gradle_proxy.useWrapper = true
        
        def build_info = gradle_proxy.run tasks: "artifactoryPublish"
        
        artifactory_server.publishBuildInfo build_info
    } // stage
} // node 

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 6:27:02 PM8/27/19
to jenkinsc...@googlegroups.com

Also worth noting, using the exact same build configuration I can replace the call to gradle_proxy.run with a shell build step that calls into gradlew and the build succeeds ... however there is no build info attched to the artifacts that are published by Gradle to Artifactory. Here's a sample of the build script that I am describing:

 

node  {
    stage ("build") {
        checkout scm
       
        def artifactory_server = Artifactory.server 'server-id' 
        
        def gradle_proxy = Artifactory.newGradleBuild()          
        gradle_proxy.deployer repo: 'snapshot-repo', server: artifactory_server
        gradle_proxy.useWrapper = true
        
        def build_info = Artifactory.newBuildInfo()
        sh "./gradlew artifactoryPublish"
        artifactory_server.publishBuildInfo build_info
    } // stage
} // node  

thefriendlycoder@gmail.com (JIRA)

unread,
Aug 27, 2019, 6:37:03 PM8/27/19
to jenkinsc...@googlegroups.com

After examining the build output a little closer, I noticed that when using the GradleBuild object to proxy the call to Gradle, the gradle wrapper is given an "init script" that appears to be generated by the Artifactory Jenkins plugin. I dug into one our build servers so I could crack open one of these init scripts to see what it looks like and here's what I found:

import org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTaskinitscript {
    dependencies {
        classpath fileTree('<path_to_jenkins_temp_folder>/artifactory/cache/artifactory-plugin/3.3.2')
    }
}addListener(new BuildInfoPluginListener())
class BuildInfoPluginListener extends BuildAdapter {    def void projectsLoaded(Gradle gradle) {
        Map<String, String> projectProperties = new HashMap<String, String>(gradle.startParameter.getProjectProperties())
        projectProperties.put("build.start", Long.toString(System.currentTimeMillis()))
        gradle.startParameter.setProjectProperties(projectProperties)
        Project root = gradle.getRootProject()
        root.logger.debug("Artifactory plugin: projectsEvaluated: ${root.name}")
        if (!"buildSrc".equals(root.name)) {
            root.allprojects {
                apply {
                    apply plugin: ArtifactoryPlugin
                }
            }
        }        // Set the "archives" configuration to all Artifactory tasks.
        for (Project p : root.getAllprojects()) {
            Task t = p.getTasks().findByName(ArtifactoryTask.ARTIFACTORY_PUBLISH_TASK_NAME)
            if (t != null) {
                ArtifactoryTask task = (ArtifactoryTask)t
                task.setAddArchivesConfigToTask(true)
            }
        }
    }
} 

The most notable part I think in the init script is the absolute class path to a temporary folder where there is apparently a  gradle / java dependency named "artifactory-plugin" which appears to be pegged at version 3.3.2 (ie: the same version as the Jenkins Artifactory plugin). So I can't help but think there must be a class defined in the Jenkins Artifactory plugin that is also defined in the Gradle Artifactory plugin and the two class definitions are incompatible with one another, and that is the cause of the Java casting error I mentioned in my earlier comment.

Honestly, I have no idea how any of this works ... or is supposed to work. If there is an interdependency between the Artifactory plugin for Gradle and the Artifactory plugin for Jenkins that would preclude mixing incompatible versions between the CI build environment and the application build environment.

I sincerely hope someone out there can offer some advice on how to proceed here.

Reply all
Reply to author
Forward
0 new messages