-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JENKINS-48885: JenkinsRule always returns null in getPluginManager().getPlugin() on new core versions #65
Comments
What I figured out is that the jobDSL plugin gets a pluginmanager that has zero plugins (TestPluginManager), I am guessing this is some config issue? |
@maconic I'll hopefully be able to look into this at some point this weekend. It is possible that is in how dependency management for Jenkins plugins is managed now. Is the Spock test you added complete? Maybe I messed it up with my edit, but it looks like it is missing |
I am afraid my knowledge of the jenkins internals is too limited to resolve this :( Sry, I will post the Spock Spec again! def "should create pipelineJob"() {
given:
FreeStyleProject freeStyleProject = rule.createFreeStyleProject('project')
def scripts = new ExecuteDslScripts()
scripts.scriptText = '''
pipelineJob("testPipeline") {
// because stash notifier will not work
triggers {
scm('')
}
logRotator {
numToKeep(15)
artifactNumToKeep(1)
}
}
'''.stripIndent()
freeStyleProject.getBuildersList().add(scripts)
when:
QueueTaskFuture<FreeStyleBuild> futureRun = freeStyleProject.scheduleBuild2(0)
then:
// JenkinsRule has different assertion capabilities
def run = rule.assertBuildStatusSuccess(futureRun)
rule.assertLogContains('''test'''.stripIndent(), run)
}
|
It would be great if you can give me a hint over the weekend! I will check here, in case there are some questions. |
An even simpler version with Spock would be: def "should create pipelineJob"() {
given:
WorkflowJob workflowJob = rule.createProject(WorkflowJob, 'project1')
FreeStyleProject freeStyleProject = rule.createFreeStyleProject('project')
new DslScriptLoader(new JenkinsJobManagement(System.out, [:], new File('.'))).runScript('''
pipelineJob('myJob') {
}
'''.stripIndent())
when:
QueueTaskFuture<FreeStyleBuild> futureRun = freeStyleProject.scheduleBuild2(0)
then:
def run = rule.assertBuildStatusSuccess(futureRun)
rule.assertLogContains('''test'''.stripIndent(), run)
} |
Can you post full stacktrace from Gradle or from tests that is causing it? |
There isn't too much of a stracktrace, but I will try. Maybe I can provide you with an example project if that would be helpful? |
A reproducible project and steps will be very helpful and appreciated! |
Sorry for taking me a while, I hope it is going to be helpful. Just run gradle integrationTest (Java needs to be installed, nothing more - I tested it with JDK8) |
This is somewhat strange, and I don't know why this is happening:
both show |
Well for the job dsl plugin to work, you have to create a freestyle job and most examples I have seen work with a workflow job, maybe this is the root issue? |
Test can be reduced down to def "should create pipelineJob"() {
when:
new DslScriptLoader(new JenkinsJobManagement(System.out, [:], new File('.'))).runScript(
'''
//pipelineJob('pipelineJobFails')
freeStyleJob('freeStyleJobSucceeds')
'''.stripIndent()
)
then:
rule.jenkins.jobNames.size() == 1
} If So, it doesn't seem like the plugin detection is working. The Job DSL Plugin does some preventative actions to check if plugins are installed and what not before creating job (as seen at https://github.com/jenkinsci/job-dsl-plugin/blob/bfd0dee59f365d6d5223632f6dc210b30f2bb958/job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/DslFactory.groovy#L120-L121). Side note, the Job DSL Plugin doesn't require a freestyle project to run, I think that is just how most people make use of it. For example, you can execute the Job DSL using pipeline ( node {
jobDsl(
scriptText: '''
freeStyleJob('jobName')
'''
)
} Right now, I have the dependency management setup so that the
I'm leaning towards the Side note, there is an example at https://github.com/sheehan/job-dsl-gradle-example for just testing out Job DSL scripts, but you should be able to something similar with this Gradle plugin. That example copies the |
Hi! You are absolutely right, I could get this running by using a workflow script! I would prefer the approach without copying the plugins! :) |
I believe this is an upstream bug in Jenkins - https://issues.jenkins-ci.org/browse/JENKINS-48885 |
Looks like it! |
Seems like there is not too much of a progress on the Jenkins issue :( Mabye we can get the plugin provider to use a different API? |
I guess there is no example on how to use the "copy plugins" approach from Kotlin? TBH I struggle a bit to convert the zero typed Groovy code to fully typed Kotlin :( |
I think the "copy plugins" approach will still have the same issue. You could try using an older Jenkins core / Jenkins Test Harness version and see if that helps, but I think this needs to be fixed in Jenkins proper. |
Yeah I did a downgrade and the older version of the JobDsl plugin treats this as a warning. |
Any thoughts on this one two years later? :) I've been avoiding updating for a while because I was hitting this issue and was having trouble figuring out what was going on. In my case I've hit this because the durable task plugin's When I debug I can see that the plugin manager thinks there's nothing loaded: I can't figure out any workaround apart from downgrading |
I think this is basically still relying on upstream fixes in the Jenkins Test Harness (at least from my understanding):
I haven't released a new version in a while with default version updates, but it still doesn't look fixed. |
I, too, am experiencing this issue with recent versions of the JUnit plugin. I can reproduce this issue with Jenkins Pipeline Shared Library Gradle Plugin 0.10.1 and Jenkins Test Harness 2.64. I cannot reproduce this problem with a Maven-based test, also using Jenkins Test Harness 2.64. So Jenkins Test Harness 2.64 does support calling I stepped through the working Maven-based version and compared it to the broken Gradle-based version. The difference seems to be in lines 125-156 of The code that creates this index in To summarize, I am not sure the problem is upstream in the Jenkins test harness. I think the problem is that we are not invoking the logic in |
Thanks for looking into it @basil . I haven't spent really any time on this repository in a while since I haven't used Jenkins Pipelines in some time. Maybe something similar could be done as |
@mkobit @basil I was able to get around this, I think it has to do with the creation of the We have something like this in our build.gradle: task resolveTestPlugins(type: Copy) {
from configurations.testPlugins
into new File(sourceSets.test.output.resourcesDir, 'test-dependencies')
include '*.hpi'
include '*.jpi'
doLast {
def baseNames = source.collect { it.name[0..it.name.lastIndexOf('.')-1] }
new File(destinationDir, 'index').setText(baseNames.join('\n'), 'UTF-8')
}
}
test {
dependsOn tasks.resolveTestPlugins
inputs.files sourceSets.jobs.groovy.srcDirs
// set build directory for Jenkins test harness, JENKINS-26331
systemProperty 'buildDirectory', project.buildDir.absolutePath
} I think we copied this from here a while ago. That drops index contents with the VERSIONS attached:
I noticed that the plugin manager was trying to read things through the short name, so
In my case when it loads In the interim, I created my own rule/plugin manager just to debug through this more easily (that's how i noticed what archive the Plugin reference was for) class OverridenRule extends JenkinsRule {
public static final PluginManager INSTANCE;
public MyRule() {
// visible
}
static {
try {
INSTANCE = new OverridenManager();
} catch (IOException e) {
throw new Error(e);
}
}
@Override
public PluginManager getPluginManager() {
return INSTANCE;
}
static class OverridenManager extends TestPluginManager {
public OverridenManager() throws IOException {
}
@Override
protected Collection<String> loadBundledPlugins() throws Exception {
// Overridden method that is going to rename trilead-api-1.0.8.hpi to trilead-api.jpi
def names = []
def directory = getClass().getClassLoader().getResource("test-dependencies/")
def dir = new File(directory.getFile())
dir.eachFileRecurse(FileType.FILES) { file ->
if (file.getName().contains(".hpi")) {
String fileWithoutExt = file.name.take(file.name.lastIndexOf('.'))
def shortName = fileWithoutExt.take(fileWithoutExt.lastIndexOf('-'))
copyBundledPlugin(file.toURI().toURL(), shortName + ".jpi")
names.add(shortName)
}
}
return names
}
@Override
public PluginWrapper getPlugin(String shortName) {
// load from our special dir?
def superPlugin = super.getPlugin(shortName)
if (superPlugin != null) {
return superPlugin
}
// added breakpoint here but once it works it never gets here!
return super.getPlugin(shortName)
}
} I have a hunch that I can probably fix this with some gradle plugin copy task magic by just copying things under the Updated taskI was able to remove my hacked manager and just update my task to this, best of luck everyone task resolveTestPlugins(type: Copy) {
from configurations.testPlugins
into new File(sourceSets.test.output.resourcesDir, 'test-dependencies')
include '*.hpi'
include '*.jpi'
rename { filename ->
// the plugin manager will load plugins by short name (trilead-api) instead of (trilead-api-1.0.8)
String fileWithoutExt = filename.take(filename.lastIndexOf('.'))
def shortName = fileWithoutExt.take(fileWithoutExt.lastIndexOf('-'))
filename.replace fileWithoutExt, shortName
}
doLast {
//
def baseNames = source.collect { it.name[0..it.name.lastIndexOf('-') - 1] }
new File(destinationDir, 'index').setText(baseNames.join('\n'), 'UTF-8')
}
} Double EditI think I might have commented on the wrong repo/issue :( since this isn't the plugin responsible for the I could have sworn we copied that part from you at some point in history...... oh well, my 2 year memory points to this being where I copied it from: https://groups.google.com/forum/#!topic/job-dsl-plugin/Us5Ce1QHLVw |
I was able to work around this issue using a variant of task resolveIntegrationTestDependencies(type: ResolveIntegrationTestDependenciesTask) {
configuration = configurations.integrationTestRuntimeClasspath
}
tasks.processIntegrationTestResources.dependsOn resolveIntegrationTestDependencies With this workaround in place, a I am hopeful that this issue will eventually be resolved upstream so that I can remove the workaround from my local build. |
@basil thanks for that, I was just looking at how to do something similar to my resolution (for an unrelated gradle project). Your hunch about the |
Just thought I'd mention the changes I managed to make to my build.gradle.kts which took care of this without extending plugins {
...
id("org.jenkins-ci.jpi") version "0.38.0" apply false
}
tasks {
...
register<org.jenkinsci.gradle.plugins.jpi.TestDependenciesTask>("resolveIntegrationTestDependencies") {
into {
val javaConvention = project.convention.getPlugin<JavaPluginConvention>()
File("${javaConvention.sourceSets.integrationTest.get().output.resourcesDir}/test-dependencies")
}
configuration = configurations.integrationTestRuntimeClasspath.get()
}
processIntegrationTestResources {
dependsOn("resolveIntegrationTestDependencies")
}
} not that I condone using Kotlin. |
@robons thanks, this helped a lot ! Here is the groovy version for anyone interested: plugins {
...
id("org.jenkins-ci.jpi") version "0.38.0" apply false
}
task resolveIntegrationTestDependencies(type: org.jenkinsci.gradle.plugins.jpi.TestDependenciesTask) {
configuration = configurations.integrationTestRuntimeClasspath
def javaConvention = project.convention.getPlugin(JavaPluginConvention)
into file("${javaConvention.sourceSets.integrationTest.output.resourcesDir}/test-dependencies")
}
tasks.processIntegrationTestResources.dependsOn resolveIntegrationTestDependencies |
Sadly somehow workflow-aggregator plugin can not be found, even if it is on the plugin dependencies list.
Spock Test:
Error:
ERROR: (script, line 2) plugin 'workflow-aggregator' needs to be installed
The text was updated successfully, but these errors were encountered: