jenkinsci / seed-plugin

Seed Jenkins plug-in
https://plugins.jenkins.io/seed/
38 stars 13 forks source link

hudson.model.Failure: ‘$’ is an unsafe character #36

Closed DavidCADanneels closed 5 years ago

DavidCADanneels commented 6 years ago

When using seed-plugin version 2.1.4 on Jenkins 2.89.4 with job-dsl 1.53, we are able to create the Project Generator with a general Seed job, but when we run this Generator to create a new branch we get the below error.

Should we use another version of the seed-plugin or is an update needed in the plugin itself?

Grtz, David.

ERROR:

... ` Config: BRANCH_FOLDERPATH: SPEEDBOAT${BRANCH} Config: BRANCH_SEEDNAME: SPEEDBOAT${BRANCH}_GENERATOR Config: BRANCH_STARTNAME: SPEEDBOAT${BRANCH}_BUILD

...

Extension branchSeedScm has produced: scm { svn { location('**') { directory 'seed' credentials '**' } } }

Extension branchSeedScm has been applied. Extension branchSeedParameters has produced: environmentVariables { env('BRANCH_SCM', BRANCH_SCM) }

Extension branchSeedParameters has been applied. Extension branchSeedDsl has produced:

Extension branchSeedDsl has been applied. Processing provided DSL script ERROR: Build step failed with exception hudson.model.Failure: ‘$’ is an unsafe character at jenkins.model.Jenkins.checkGoodName(Jenkins.java:3894) at javaposse.jobdsl.plugin.JenkinsJobManagement.createOrUpdateConfig(JenkinsJobManagement.java:154) at javaposse.jobdsl.dsl.JobManagement$createOrUpdateConfig$1.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at javaposse.jobdsl.dsl.JobManagement$createOrUpdateConfig$1.call(Unknown Source) at javaposse.jobdsl.dsl.DslScriptLoader$_extractGeneratedJobs_closure4.doCall(DslScriptLoader.groovy:192) 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:1022) at groovy.lang.Closure.call(Closure.java:414) at groovy.lang.Closure.call(Closure.java:430) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2040) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2025) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2066) at org.codehaus.groovy.runtime.dgm$162.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 javaposse.jobdsl.dsl.DslScriptLoader.extractGeneratedJobs(DslScriptLoader.groovy:185) at javaposse.jobdsl.dsl.DslScriptLoader.this$2$extractGeneratedJobs(DslScriptLoader.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:384) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:174) at javaposse.jobdsl.dsl.DslScriptLoader$_runScriptsWithClassLoader_closure1.doCall(DslScriptLoader.groovy:84) 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:1022) at groovy.lang.Closure.call(Closure.java:414) at groovy.lang.Closure.call(Closure.java:430) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2040) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2025) at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2066) at org.codehaus.groovy.runtime.dgm$162.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 javaposse.jobdsl.dsl.DslScriptLoader.runScriptsWithClassLoader(DslScriptLoader.groovy:68) at javaposse.jobdsl.dsl.DslScriptLoader.this$2$runScriptsWithClassLoader(DslScriptLoader.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.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:182) at javaposse.jobdsl.dsl.DslScriptLoader.runScripts(DslScriptLoader.groovy:44) at javaposse.jobdsl.dsl.DslScriptLoader$runScripts.callCurrent(Unknown Source) at javaposse.jobdsl.dsl.DslScriptLoader.runScript(DslScriptLoader.groovy:58) at net.nemerosa.jenkins.seed.support.DSLHelper.launchGenerationScript(DSLHelper.java:25) at net.nemerosa.jenkins.seed.generator.AbstractGenerationStep.perform(AbstractGenerationStep.java:57) at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20) at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:744) at hudson.model.Build$BuildExecution.build(Build.java:206) at hudson.model.Build$BuildExecution.doRun(Build.java:163) at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:504) at hudson.model.Run.execute(Run.java:1724) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43) at hudson.model.ResourceController.execute(ResourceController.java:97) at hudson.model.Executor.run(Executor.java:429) Build step 'Seed - Branch folder generation' marked build as failure [InfluxDB Plugin] Collecting data for publication in InfluxDB... [InfluxDB Plugin] Publishing data to: [[description='**', url='**', database='jenkins_metrics_rep', retentionPolicy='rp_default', exposeExceptions=true, globalListener=true, globalListenerFilter='']] Finished: FAILURE `

DavidCADanneels commented 6 years ago

For info: this is the code which generates the general Seed job:

configure { node -> node / 'builders' / 'net.nemerosa.jenkins.seed.generator.ProjectGenerationStep' { projectConfig { pipelineConfig { destructor true authorisations '''\ hudson.model.Item.Workspace:jenkins* hudson.model.Item.Read:jenkins hudson.model.Item.Discover:jenkins_ hudson.model.Item.Read:jenkins_EXT hudson.model.Item.Discover:jenkinsEXT hudson.model.Item.Workspace:jenkinsBUILD hudson.model.Item.Read:jenkinsBUILD hudson.model.Item.Discover:jenkinsBUILD hudson.model.Item.Build:jenkinsBUILD hudson.model.Item.Cancel:jenkinsBUILD hudson.model.Item.Read:jenkinsQA hudson.model.Item.Discover:jenkinsQA hudson.model.View.Read:jenkins hudson.model.View.Read:jenkins_QA hudson.model.View.Read:jenkinsBUILD hudson.model.View.Read:jenkins*EXT ''' branchSCMParameter true branchParameters '' generationExtension '' pipelineGenerationExtension '' disableDslScript true scriptDirectory '' namingStrategy { projectFolderPath '${PROJECT}' branchFolderPath '${PROJECT}${BRANCH}' projectSeedName '${PROJECT}_GENERATOR' projectDestructorName '${PROJECT}DESTRUCTOR' branchSeedName '${PROJECT}${BRANCH}GENERATOR' branchStartName '${PROJECT}${BRANCH}_BUILD' branchName '${BRANCH}' ignoredBranchPrefixes '' } eventStrategy { delete true auto true trigger true commit 'REVISION' } } project '${PROJECT}' scmType 'svn' scmUrl '${PROJECT_SCM_URL}' scmCredentials '${PROJECT_SCM_CREDENTIALS}' triggerIdentifier '' triggerType '' triggerSecret '' } } }

Perhaps I need to surround my ${PROJECT} (and other) parameter(s) with double quotes instead of single quotes?

futchas commented 5 years ago

@DavidCADanneels Got the same issue..how did you solve it?

DavidCADanneels commented 5 years ago

The error indicates that one of the variable is not set, in my case ${BRANCH}. I already noticed this in my code, but still need to fix it. In your case it might be another variable which is not resolved, but most likely it will be the same one.

DavidCADanneels commented 5 years ago

I performed a deeper analysis of this issue. The SEED job (which generates the Generator job of a project) used parameters like ${PROJECT} and ${PROJECT}_${BRANCH} where ${BRANCH} is an input parameter of the Generator job, to be replaced at runtime. When I check the Generator job (generated by our SEED job) I can see that:

DavidCADanneels commented 5 years ago

NOTE:

DavidCADanneels commented 5 years ago

After digging into the code, I finally found the solution. The values of branchFolderPath, branchSeedName and branchStartName (which should contain the value of the BRANCH parameter) are only resolved when running the Generator job (to create a new branch).

Placeholders for BRANCH should be indicated with a *.

Hence, if I provide the following values:

my Generator job still contains the unresolved PROJECT variables (for those 3 fields):

but when I run this Generator job to create a new branch, I can see that the values are resolved correctly:

Config: BRANCH_FOLDER_PATH: SPEEDBOAT_12.1-PIPELINE
Config: BRANCH_SEED_NAME: SPEEDBOAT_12.1-PIPELINE_GENERATOR
Config: BRANCH_START_NAME: SPEEDBOAT_12.1-PIPELINE_PUBLISH

For me this issue is resolved, although I'm still struggling with the running the Branch Generator job, which expects a seed.groovy file i.s.o. generating this file (is related to config, which used to be stored in a Yaml file and now needs to be passed differently). Looking into migration steps: https://github.com/jenkinsci/seed-plugin/wiki/Migration-from-0.x