Jenkins CasC加载含参数流水线报错及启动失败问题求助
Jenkins Config as Code(CasC)流水线参数加载异常解决方案
问题描述
使用Jenkins Config as Code(CasC)自动生成带参数的流水线任务时,Jenkins启动直接失败,抛出groovy.lang.MissingPropertyException(提示WorkflowScript类不存在app属性)。而通过GUI手动创建相同脚本的任务时,首次执行会报同样错误,但参数完成注册后后续执行正常;CasC场景下无法通过GUI重试来绕过这个问题。
错误信息
hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: app for class: WorkflowScript at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:66) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:471) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getProperty(DefaultInvoker.java:39) at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20) at WorkflowScript.run(WorkflowScript:19) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.delegateAndExecute(ModelInterpreter.groovy:137) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.executeSingleStage(ModelInterpreter.groovy:666) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(ModelInterpreter.groovy:395) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(ModelInterpreter.groovy:393) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.executeSingleStage(ModelInterpreter.groovy:665) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:288) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.toolsBlock(ModelInterpreter.groovy:544) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.toolsBlock(ModelInterpreter.groovy:543) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:276) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:443) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:442) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:275) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withCredentialsBlock(ModelInterpreter.groovy:481) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withCredentialsBlock(ModelInterpreter.groovy:480) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:274) at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.inDeclarativeAgent(ModelInterpreter.groovy:595) at org.jenkinsci.plugins.pipeline.modeldefinition.agent.CheckoutScript.checkoutAndRun(CheckoutScript.groovy:64) at org.jenkinsci.plugins.pipeline.modeldefinition.agent.CheckoutScript.doCheckout(CheckoutScript.groovy:40) at org.jenkinsci.plugins.pipeline.modeldefinition.agent.impl.LabelScript.run(LabelScript.groovy:43) at ___cps.transform___(Native Method) at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:73) at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30) at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:65) at jdk.internal.reflect.GeneratedMethodAccessor288.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72) at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21) at com.cloudbees.groovy.cps.Next.step(Next.java:83) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:152) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:146) at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:136) at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:275) at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:146) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:187) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:420) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:330) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:294) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68) at jenkins.util.ErrorLoggingExecutorService.lambda$wrap$0(ErrorLoggingExecutorService.java:51) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Finished: FAILURE
环境信息
- Jenkins版本:2.387.1
- 相关插件版本:
- Config as Code: 1569.vb_72405b_80249
- config as code groovy extension: 1.1
- pipeline: 596.v8c21c963d92d
- pipeline groovy: 3653.v07ea_433c90b_4
- pipeline groovy libraries: 629.vb_5627b_ee2104
原流水线脚本
pipeline { agent none parameters { choice(name: 'app', choices: ['app1', 'app2'], description: 'Select the app.') choice(name: 'app_year', choices: ['', '2023', '2022', '2021'], description: 'Select the app year.') choice(name: 'deploy_env', choices: ['builds'], description: 'Default is builds.') choice(name: 'feature', choices: ['', 'feat1', 'feat2', 'feat3'], description: 'Select the feature, leave blank for all.') } triggers { cron('H/15 * * * *') } stages { stage ('App Healthcheck') { agent { label 'test-deploy01' } options { timeout(time: 3600, unit: 'SECONDS') } steps { sh "cd /opt/tools/ansible/${app}/scripts/; \ PYTHONPATH=shared python app_service_check.py -y $app_year -e $deploy_env -p $feature" } } } }
解决方案
1. 显式通过params引用参数
Declarative Pipeline中,CasC加载任务时参数上下文初始化顺序不同,直接使用参数名会导致找不到属性。必须通过params对象显式引用所有参数:
修改后的脚本步骤部分:
sh "cd /opt/tools/ansible/${params.app}/scripts/; \ PYTHONPATH=shared python app_service_check.py -y ${params.app_year} -e ${params.deploy_env} -p ${params.feature}"
2. 为参数设置默认值
在parameters块中给每个参数添加defaultValue,确保CasC加载时参数有初始值,避免未定义状态:
parameters { choice(name: 'app', choices: ['app1', 'app2'], defaultValue: 'app1', description: 'Select the app.') choice(name: 'app_year', choices: ['', '2023', '2022', '2021'], defaultValue: '', description: 'Select the app year.') choice(name: 'deploy_env', choices: ['builds'], defaultValue: 'builds', description: 'Default is builds.') choice(name: 'feature', choices: ['', 'feat1', 'feat2', 'feat3'], defaultValue: '', description: 'Select the feature, leave blank for all.') }
3. CasC配置中同步定义参数
如果你的CasC配置是通过YAML定义任务,建议在CasC的任务配置中同步定义参数,而不是仅在流水线脚本中声明。这样CasC加载时会先初始化参数,再解析流水线脚本:
示例CasC YAML片段:
jobs: - script: > pipelineJob('app-healthcheck') { parameters { choiceParam('app', ['app1', 'app2'], 'Select the app.', 'app1') choiceParam('app_year', ['', '2023', '2022', '2021'], 'Select the app year.', '') choiceParam('deploy_env', ['builds'], 'Default is builds.', 'builds') choiceParam('feature', ['', 'feat1', 'feat2', 'feat3'], 'Select the feature, leave blank for all.', '') } definition { cps { script(readFileFromWorkspace('pipelines/app-healthcheck.groovy')) sandbox() } } }
修改后的完整流水线脚本
pipeline { agent none parameters { choice(name: 'app', choices: ['app1', 'app2'], defaultValue: 'app1', description: 'Select the app.') choice(name: 'app_year', choices: ['', '2023', '2022', '2021'], defaultValue: '', description: 'Select the app year.') choice(name: 'deploy_env', choices: ['builds'], defaultValue: 'builds', description: 'Default is builds.') choice(name: 'feature', choices: ['', 'feat1', 'feat2', 'feat3'], defaultValue: '', description: 'Select the feature, leave blank for all.') } triggers { cron('H/15 * * * *') } stages { stage ('App Healthcheck') { agent { label 'test-deploy01' } options { timeout(time: 3600, unit: 'SECONDS') } steps { sh "cd /opt/tools/ansible/${params.app}/scripts/; \ PYTHONPATH=shared python app_service_check.py -y ${params.app_year} -e ${params.deploy_env} -p ${params.feature}" } } } }
内容的提问来源于stack exchange,提问作者New2Python
相关产品推荐
相关产品推荐

