Jenkins Active Choices响应式参数无内容显示问题求助
我们GitLab仓库中有格式为PROJECT_NAME-ENV_NAME-images.yaml的YAML文件,结构如下:
producta: service1: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v1.1.80" serviceb: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v1.1.42" productb: servicec: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v1.1.42" smoke_test: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "2dc13f68" serviced: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v1.1.42" servicee: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v1.1.42" servicee: image: repository: repo pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. tag: "v0.0.9"
在Jenkins中我们定义了PROJECT_NAME和ENV_NAME输入参数,products是多选类型的Active Choice参数。需求是:用户输入项目、环境及需更新标签的产品列表后,在Active Choices Reactive Reference Parameter类型的servicesToBeUpdated参数中渲染包含对应服务及标签的HTML输入表格。
我们配置的Groovy脚本如下:
def gitlabUrl = "https://gitlab.com/group/helm-charts.git" def gitlabCredentialsId = "XXXXXX-XXX-XXX-XXXX-XXX" def gitlabBranch = "v1" def imagesYamlFile = "images/project/${params.Project}-${params.Env}-images.yaml" withCredentials([usernamePassword(credentialsId: gitlabCredentialsId, usernameVariable: 'GITLAB_USERNAME', passwordVariable: 'GITLAB_PASSWORD')]) { sh """ rm -rf repo git clone --branch ${gitlabBranch} ${gitlabUrl} repo cp repo/${imagesYamlFile} . """ } def imagesYaml = readYaml file: imagesYamlFile def productslist = imagesYaml.keySet() for (product in productslist) { def microservices = imagesYaml[product].keySet() def service_list = [] for (microservice in microservices) { def yamlLength = imagesYaml[product][microservice].size() if (yamlLength > 1 && microservice.equals("image")) { def tag = imagesYaml[product][microservice].tag def service = [:] service['service'] = microservice service['release_tag'] = tag service_list.add(service) } else if (yamlLength > 1) { def msImage = imagesYaml[product][microservice].keySet() for (mss in msImage) { def mssYamlLength = imagesYaml[product][microservice][mss].size() if (mssYamlLength > 1 && mss != "SNOWFLAKE_CONTAINER_IMAGE") { def tag = imagesYaml[product][microservice][mss].tag def service = [:] service['service'] = "${microservice}.${mss}" service['release_tag'] = tag service_list.add(service) } } } else { def image = imagesYaml[product][microservice].image def tag = image.tag def service = [:] service['service'] = microservice service['release_tag'] = tag service_list.add(service) } } service_tier_map[product] = service_list } // Get the list of products to update from the user input def productsToUpdate = params.products.split(",") // Loop through each product and its associated services service_tier_map.each { selectedProduct, services -> // Check if the current product is in the list of products to update if (productsToUpdate.contains(product)) { def updated_services = [] // Loop through each service and update its release tag services.each { service -> updated_services.add(service) } service_to_be_updated_map[product] = updated_services } } html_to_be_rendered = "<table><tr>" service_to_be_updated_map.each { product, services -> services.each { service -> html_to_be_rendered = """ ${html_to_be_rendered} <tr> <td> <input name=\"value\" alt=\"${service.service}\" json=\"${service.service}\" type=\"checkbox\" class=\" \"> <label title=\"${service.service}\" class=\" \">${service.service}</label> </td> <td> <input type=\"text\" class=\" \" name=\"value\" value=\"${service.release_tag}\"> </br> </td> </tr> """ } } html_to_be_rendered = "${html_to_be_rendered}</tr></table>" return html_to_be_rendered
问题:修改products输入参数的值后,Jenkins界面上的servicesToBeUpdated参数下无任何内容显示。
1. 初始化核心映射变量
脚本中service_tier_map和service_to_be_updated_map两个关键映射未提前初始化,Groovy会因未定义变量触发运行时错误,直接跳过后续逻辑。
修复:在读取YAML后添加初始化代码:
def service_tier_map = [:] def service_to_be_updated_map = [:]
2. 修正循环变量引用错误
遍历service_tier_map时,判断条件误用了外部循环的product变量,而非当前迭代的selectedProduct,导致无法匹配用户选择的产品,service_to_be_updated_map始终为空。
修复:调整判断与赋值逻辑:
service_tier_map.each { selectedProduct, services -> if (productsToUpdate.contains(selectedProduct)) { service_to_be_updated_map[selectedProduct] = services } }
3. 适配实际YAML结构解析逻辑
原脚本的分支判断不符合实际YAML结构:你的YAML中每个服务(如service1)下直接是image节点,不存在microservice.equals("image")的场景,导致标签提取失败。
修复:简化服务遍历逻辑:
for (product in productslist) { def microservices = imagesYaml[product].keySet() def service_list = [] for (microservice in microservices) { def imageConfig = imagesYaml[product][microservice].image if (imageConfig && imageConfig.tag) { def service = [:] service['service'] = microservice service['release_tag'] = imageConfig.tag service_list.add(service) } } service_tier_map[product] = service_list }
注:原YAML中productb下有重复的servicee节点,解析时会覆盖前一个,建议先修复YAML文件的重复键问题。
4. 修复HTML结构错误
原HTML开头和结尾的<tr>标签冗余且结构无效,导致浏览器无法渲染。同时多个输入控件的name属性重复,会导致提交值被覆盖。
修复:重构HTML构造代码:
html_to_be_rendered = "<table>" service_to_be_updated_map.each { product, services -> services.each { service -> html_to_be_rendered += """ <tr> <td> <input name=\"${service.service}_checkbox\" type=\"checkbox\" class=\"\"> <label title=\"${service.service}\" class=\"\">${service.service}</label> </td> <td> <input type=\"text\" class=\"\" name=\"${service.service}_tag\" value=\"${service.release_tag}\"> </td> </tr> """ } } html_to_be_rendered += "</table>"
5. 检查Jenkins参数配置
- 确认
servicesToBeUpdated的Referenced parameters已包含Project、Env、products,确保参数变化时触发脚本重新执行。 - 确认
products参数的返回值是逗号分隔的字符串,与params.products.split(",")的解析逻辑匹配。 - 在Jenkins脚本控制台测试核心逻辑,排除Git拉取、YAML读取的权限或路径问题。
内容的提问来源于stack exchange,提问作者chitender kumar

