mibexsoftware / bamboo-plan-dsl-plugin

Configuration as code with a Groovy-based DSL or YAML for Atlassian Bamboo.
https://marketplace.atlassian.com/plugins/ch.mibex.bamboo.plandsl/
Other
40 stars 16 forks source link

Enum not found on the classpath #66

Open sohrab- opened 6 years ago

sohrab- commented 6 years ago

I have a rather strange issue and I am not certain what the root cause is. Basically when I reference certain classes or enums in my code, this works fine with local unit testing but on the SEED task I get compilation errors where the class cannot be resolved. I am wondering if there is a different class-loading approach in the SEED task that causes this issue.

Here is a simplified example:

src/main/groovy/dsls/XConfig.groovy

package dsls
class XConfig {
   static enum Envs { DEV, TEST, SIT }
}

src/main/groovy/dsls/plans/XPlan.groovy

package dsls.plans
import dsls.XConfig
...
class XPlan {
   static void configure(Project project) {
      ...
   }
   private static void addEnvs(XConfig.Envs env) {
      ...
   }
}

dsls/XPlans.groovy

import static dsls.plans.XPlan.configure
project(key: 'KEY', name: 'Name') {
   configure delegate
}

This runs fine locally but on the SEED task it would cause the following issue:

Plan DSL: will now process script file from XPlans.groovy
Plan DSL: task failed: startup failed:file:/var/atlassian/application-data/bamboo/xml-data/build-dir/ENG-SEED-JOB1/src/main/groovy/dsls/plan/XPlan.groovy: 96: unable to resolve class XConfigEnvs  @ line 96, column 32.   addEnv(XConfig.                                 
                                                                             ^1 error
ch.mibex.bamboo.plandsl.dsl.DslException: startup failed:
file:/var/atlassian/application-data/bamboo/xml-data/build-dir/ENG-SEED-JOB1/src/main/groovy/dsls/plan/XPlan.groovy: 96: unable to resolve class XConfig.Envs 
 @ line 96, column 32.
   addEnv(XConfig. 
   ^ 1 error
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
    at ch.mibex.bamboo.plandsl.dsl.DslScriptParserImpl.parse(DslScriptParserImpl.groovy:37)
    at ch.mibex.bamboo.plandsl.dsl.DslScriptParser$parse.call(Unknown Source)
    at ch.mibex.bamboo.plandsl.plugin.PlanDslExecutorImpl$1.doInTransaction(PlanDslExecutorImpl.groovy:53)
    at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:21)
    at com.atlassian.sal.spring.component.SpringHostContextAccessor$1.doInTransaction(SpringHostContextAccessor.java:71)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at com.atlassian.sal.spring.component.SpringHostContextAccessor.doInTransaction(SpringHostContextAccessor.java:68)
    at sun.reflect.GeneratedMethodAccessor160.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
    at com.sun.proxy.$Proxy338.doInTransaction(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor160.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
    at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
    at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
    at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy561.doInTransaction(Unknown Source)
    at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:18)
    at sun.reflect.GeneratedMethodAccessor455.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
    at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
    at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
    at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy1150.execute(Unknown Source)
    at com.atlassian.sal.api.transaction.TransactionTemplate$execute.call(Unknown Source)
    at ch.mibex.bamboo.plandsl.plugin.PlanDslExecutorImpl.execute(PlanDslExecutorImpl.groovy:46)
    at ch.mibex.bamboo.plandsl.plugin.PlanDslExecutor$execute.call(Unknown Source)
    at ch.mibex.bamboo.plandsl.plugin.task.SeedTask$_execute_closure1$_closure3.doCall(SeedTask.groovy:54)
    at ch.mibex.bamboo.plandsl.plugin.task.SeedTask$_execute_closure1$_closure3.doCall(SeedTask.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
    at groovy.lang.Closure.call(Closure.java:426)
    at groovy.lang.Closure.call(Closure.java:420)
    at com.atlassian.bamboo.utils.BambooRunnables$BambooRunnableFromCallable.run(BambooRunnables.java:64)
    at com.atlassian.bamboo.security.ImpersonationHelper.runWith(ImpersonationHelper.java:26)
    at com.atlassian.bamboo.applinks.ImpersonationServiceImpl$1.call(ImpersonationServiceImpl.java:74)
    at java_util_concurrent_Callable$call.call(Unknown Source)
    at ch.mibex.bamboo.plandsl.plugin.task.SeedTask$_execute_closure1.doCall(SeedTask.groovy:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1021)
    at groovy.lang.Closure.call(Closure.java:426)
    at groovy.lang.Closure.call(Closure.java:442)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2030)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2015)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2068)
    at org.codehaus.groovy.runtime.dgm$164.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at ch.mibex.bamboo.plandsl.plugin.task.SeedTask.execute(SeedTask.groovy:50)
    at com.atlassian.bamboo.task.TaskExecutorImpl.lambda$executeTasks$2(TaskExecutorImpl.java:282)
    at com.atlassian.bamboo.task.TaskExecutorImpl.executeTaskWithPrePostActions(TaskExecutorImpl.java:223)
    at com.atlassian.bamboo.task.TaskExecutorImpl.executeTasks(TaskExecutorImpl.java:282)
    at com.atlassian.bamboo.task.TaskExecutorImpl.execute(TaskExecutorImpl.java:111)
    at com.atlassian.bamboo.build.pipeline.tasks.ExecuteBuildTask.call(ExecuteBuildTask.java:71)
    at com.atlassian.bamboo.v2.build.agent.DefaultBuildAgent.build(DefaultBuildAgent.java:185)
    at com.atlassian.bamboo.v2.build.agent.BuildAgentControllerImpl$1.call(BuildAgentControllerImpl.java:120)
    at com.atlassian.bamboo.v2.build.agent.BuildAgentControllerImpl$1.call(BuildAgentControllerImpl.java:113)
    at com.atlassian.bamboo.variable.CustomVariableContextImpl.withVariableSubstitutor(CustomVariableContextImpl.java:185)
    at com.atlassian.bamboo.v2.build.agent.BuildAgentControllerImpl.waitAndPerformBuild(BuildAgentControllerImpl.java:113)
    at com.atlassian.bamboo.v2.build.agent.DefaultBuildAgent$1.run(DefaultBuildAgent.java:126)
    at com.atlassian.bamboo.utils.BambooRunnables$1.run(BambooRunnables.java:47)
    at com.atlassian.bamboo.security.ImpersonationHelper.runWith(ImpersonationHelper.java:26)
    at com.atlassian.bamboo.security.ImpersonationHelper.runWithSystemAuthority(ImpersonationHelper.java:17)
    at com.atlassian.bamboo.security.ImpersonationHelper$1.run(ImpersonationHelper.java:41)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
file:/var/atlassian/application-data/bamboo/xml-data/build-dir/ENG-SEED-JOB1/src/main/groovy/dsls/plan/XPlan.groovy: 96: unable to resolve class XConfig.Envs 
 @ line 96, column 32.
   addEnv(XConfig.
                 ^ 1 error
    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:946)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:593)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:542)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
    at groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:256)
    at groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:243)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:254)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:212)
    at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:566)
    at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:616)
    at groovy.util.GroovyScriptEngine$createScript.call(Unknown Source)
    at ch.mibex.bamboo.plandsl.dsl.DslScriptParserImpl.parseScript(DslScriptParserImpl.groovy:61)
    at sun.reflect.GeneratedMethodAccessor5690.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:174)
    at ch.mibex.bamboo.plandsl.dsl.DslScriptParserImpl.parse(DslScriptParserImpl.groovy:34)
    ... 106 more
Finished task 'Configure plans' with result: Error

Something that makes this even more confusing is that there are YPlans, YPlan and YConfig with the same setup that do compile fine.

Here is the SEED task configuration:

image

I have tried all the different variations of import it the enum or its parent object or even doing fully qualified names but the error persists.

sohrab- commented 6 years ago

To make this easier, I have created this sample project that replicates the issue.

This repo is checked out and run by a Seed Task with configuration identical to the screenshot in the last comment. This fails with the aforementioned exception.

I have placed the job's entire log in logs.txt in that zip as well.

enum-bamboo-seed.zip

sohrab- commented 6 years ago

I've confirmed this also occurs on the latest version of the plugin.

Plugin version: 1.9.6 Bamboo version: 6.1.1 build 60104 - 10 Aug 17

mrueegg commented 6 years ago

Hi,

Please excuse my late reply!

I was able to reproduce this case. As far as I can see, it only happens with nested/inner classes. I think this could be related to https://stackoverflow.com/questions/27044522/groovy-importing-static-nested-classes

What do you think? Inner classes seam to be problematic in Groovy when accessed from scripts. Looks like they need to be precompiled...

sohrab- commented 6 years ago

Hi Michael

What was confusing me is that I had other nested enums that do work. I have now found out why.

In the sample code if you explicitly import dsls.BpmConfig in BpmPlans.groovy (even though not used there), the plan does pass.

It looks like there is a classloading issue (race condition?) and this way we can force the classloader to load the class prior to its use.