You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins动态创建参数报错:groovy.lang.MissingPropertyException

Jenkins动态生成Choice参数后访问params.STEP_1报MissingPropertyException问题解决

问题描述

我尝试基于AWS Parameter Store中的子项目数量动态创建Choice参数,参数已成功生成,但访问params.STEP_1时Jenkins抛出groovy.lang.MissingPropertyException错误。

原代码示例

def jobProperties() {
    params = jobParams()

    properties([
        parameters(
            params
        )
    ])
}


def jobParams() {
    def allChoices = []

    // 从AWS Parameter Store获取子项目列表
    def paramChoices = sh(script:'echo $(aws ssm get-parameter --name "PATH" --query Parameter.Value --region $(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region) --with-decryption | xargs)',returnStdout: true).trim()
    // def paramChoices = "proj1,proj2,proj3,proj4"
    def commonChoices = paramChoices.split(",") as List

    // 动态生成Choice参数
    for (int i = 1; i < commonChoices.size(); i++) {
        def name = "STEP_${i}"
        allChoices += choice(name: name, choices: commonChoices)
    }

    return allChoices
}

pipeline {
    agent any
    stages {
        stage('Prepare') {
            steps {
                script {
                    jobProperties()
                    echo $(params.STEP_1)
                }
            }
        }
    }
}

错误信息

Also:   org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: 1c76a536-17b4-4ba2-bf64-9ae0224b51f7
groovy.lang.MissingPropertyException: No such field found: field org.jenkinsci.plugins.workflow.cps.UninstantiatedDescribableWithInterpolation STEP_1
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:402)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:386)
    at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:375)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:379)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:342)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
    at org.jenkinsci.plugins.workflow.cps.LoggingInvoker.getProperty(LoggingInvoker.java:121)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
    at WorkflowScript.run(WorkflowScript:40)
    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.GeneratedMethodAccessor263.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    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.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:187)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:423)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:331)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:295)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:97)
    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:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:840)

问题原因及解决方案

1. 动态参数生效时机问题

Jenkins声明式流水线中,properties()方法设置的参数仅会在下一次构建时生效,当前构建无法访问刚设置的参数。如果需要在当前构建中使用动态生成的参数,需调整参数生成逻辑到流水线初始化阶段。

2. 语法错误

原代码中echo $(params.STEP_1)是Shell语法,Groovy中应改为echo "${params.STEP_1}"或echo params.STEP_1。

3. 循环边界问题

原代码for (int i = 1; i < commonChoices.size(); i++)会跳过最后一个参数生成(因为是小于号),应改为i <= commonChoices.size()确保生成对应数量的参数。


修正后的代码示例(当前构建可访问参数)

将参数生成逻辑直接放到声明式流水线的parameters块中,参数会在构建启动前初始化,当前构建可正常访问:

def jobParams() {
    def allChoices = []

    // 从AWS Parameter Store获取子项目列表
    def paramChoices = sh(script:'echo $(aws ssm get-parameter --name "PATH" --query Parameter.Value --region $(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region) --with-decryption | xargs)',returnStdout: true).trim()
    // def paramChoices = "proj1,proj2,proj3,proj4"
    def commonChoices = paramChoices.split(",") as List

    // 动态生成Choice参数
    for (int i = 1; i <= commonChoices.size(); i++) {
        def name = "STEP_${i}"
        allChoices += choice(name: name, choices: commonChoices)
    }

    return allChoices
}

pipeline {
    agent any
    // 构建前初始化动态参数
    parameters(jobParams())
    stages {
        stage('Prepare') {
            steps {
                script {
                    echo "${params.STEP_1}"
                }
            }
        }
    }
}

替代方案(构建过程中动态获取参数)

如果需要在构建过程中动态生成参数并立即使用,可改用input步骤:

pipeline {
    agent any
    stages {
        stage('Prepare') {
            steps {
                script {
                    def paramChoices = sh(script:'echo $(aws ssm get-parameter --name "PATH" --query Parameter.Value --region $(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region) --with-decryption | xargs)',returnStdout: true).trim()
                    def commonChoices = paramChoices.split(",") as List
                    
                    // 动态生成选项并获取用户输入
                    def step1Choice = input(
                        message: '选择STEP_1的项目',
                        parameters: [choice(name: 'STEP_1', choices: commonChoices)]
                    )
                    
                    echo "STEP_1选择的项目是: ${step1Choice}"
                }
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Deepakvg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:32:33