Plugin from buildSrc not found by Jenkins

I have an issue with gradle and Jenkins, the CI server.

Running my buildscripts on my own machine works fine (windows), but running on Jenkins (linux) fails. The error is

Plugin with id ‘RemoteService’ not found.

The plugin in question is homemade, and lives in buildSrc. Looking at the log on the Jenkins machine does not bring revelations, at least not to me. It appears to identify and compile the plugin fine, but still it’s unable to locate it when it is applied?!

The plugin is called RemoteService.groovy. Here’s a debug dump from running a build on Jenkins:

https://docs.google.com/file/d/0BxgX3GzSY7VFZ1F5ak5TeVBVSDA/edit?usp=sharing

I have tried both with the installed gradle environment on Jenkins, and with the gradle wrapper. Same result. Both run gradle 1.4.

Could you please advice me what to do to make Jenkins locate the plugin?

Regards /Jesper Thuun-Petersen

Can you show the apply statement that throws the exception? Is ‘RemoteService’ really the ID of the plugin, rather than its class name?

the apply looks like this:

apply plugin: ‘RemoteService’

in the remoteservice.properties: implementation-class=RemoteService

Here’s the plugin code:

//import com.stibo.remoteserviceframework.server.impl.InterfaceGenerator
    import java.util.logging.Logger
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.logging.LogLevel
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.TaskAction
  class RemoteService implements Plugin<Project> {
    void apply(Project project) {
        project.convention.plugins.remoteServiceConfiguration = new RemoteServiceConvention()
        project.convention.getPlugin(JavaPluginConvention.class).sourceSets.all(
                new Action<SourceSet>() {
                    public void execute(SourceSet sourceSet) {
                        final String taskName = sourceSet.getTaskName("generate", "RemoteService");
                        if (taskName.equals('generateRemoteService')) {
                            RemoteServiceTask remoteServiceTask = project.getTasks().add(taskName, RemoteServiceTask.class);
                            remoteServiceTask.description = String.format("Generates remote service interfaces %s.", sourceSet.name);
                                final String outputDirectoryName = "$project.buildDir/genclasses"
                            final File outputDirectory = new File(outputDirectoryName);
  /*
                            remoteServiceTask.inputs.files project.sourceSets.main.java.srcDirs
                            remoteServiceTask.outputs.dir outputDirectory
*/
                              project.convention.plugins.remoteServiceConfiguration.destinationDir = outputDirectoryName
                              def classesTask = project.getTasks().getByName('classes')
                            classesTask.dependsOn(remoteServiceTask)
                        }
                    }
                })
    }
}
  class RemoteServiceConvention {
    def String sourcePackage
    def String destinationPackage
    def String destinationDir
      def remoteService(Closure closure) {
        closure.delegate = this
        closure()
    }
  }
    public class RemoteServiceTask extends DefaultTask {
    private static final Logger LOGGER = Logger.getLogger("RemoteServiceTask");
      @TaskAction
    public void generate() {
        def destinationDir = project.convention.plugins.remoteServiceConfiguration.destinationDir;
        def sourcePackage = project.convention.plugins.remoteServiceConfiguration.sourcePackage;
        def destinationPackage = project.convention.plugins.remoteServiceConfiguration.destinationPackage;
        logging.level = LogLevel.DEBUG
        println("Generating remote services to dir ${destinationDir}")
          try {
            ant.java(classname: 'com.stibo.remoteserviceframework.server.impl.InterfaceGenerator', fork: 'true', failOnError: 'true') {
                arg(value: sourcePackage)
                arg(value: destinationPackage)
                arg(value: destinationDir)
                sysproperty(key: "FRAMEWORK_DISABLE_AUTOINJECT", value: "true")
                classpath {
                    pathelement(path: project.sourceSets.main.output.asPath)
                    pathelement(path: project.sourceSets.main.compileClasspath.asPath)
                    pathelement(location: "${project.mainProject}/remoteserviceframework/build/libs/remoteserviceframework-1.0-SNAPSHOT.jar")
                }
            }
        } catch (Exception e) {
            println "ERROR GENERATING INTERFACES: ${e.getMessage()}"
        }
        project.sourceSets.main.getOutput().dir(destinationDir);
    }
}

A good first step is to try with the (fully qualified) class name instead. Something like ‘apply plugin: foo.bar.RemoteService’, or ‘apply plugin: RemoteService’ if it’s located in the default package.

Peter, thanks, that did work!

If I could just wrap my head around why I had it working on my own box but not on jenkins…

/J

Might be a case-(in)sensitive file system thing. If you use the same capitalization for the ‘apply’ statement and the filename of the properties file (which you always should), it will probably work on CI as well.