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

如何在声明式Jenkins Pipeline中用Groovy获取各Stage运行的Agent

问题描述

我想获取Jenkins流水线每个Stage运行的Agent名称。虽然用env.NODE_NAME能实现,但需要在每个Stage块里写代码捕获。所以我尝试通过PipelineNodeGraphVisitor获取所有Stage类型的FlowNodes,统一捕获所有Stage的Agent,并用WorkspaceAction获取这些FlowNodes运行的Agent。

但遇到问题:当流水线全局定义一个Agent时,能正常获取到所有Stage用同一个Agent;但当某个Stage指定了不同的Agent(比如'test')时,通过WorkspaceAction拿到的还是全局定义的Agent,不是指定的'test'。

我使用的Groovy代码如下:

WorkflowRun run = Jenkins.instance.getItemByFullName(env.JOB_NAME)._getRuns()[0]
FlowExecution exec = run.getExecution()
PipelineNodeGraphVisitor visitor = new PipelineNodeGraphVisitor(run)
def flowNodes = visitor.getPipelineNodes()

for (Iterator iterator = flowNodes.iterator(); iterator.hasNext();)
{
  def node = iterator.next()
  if (node.getType() == FlowNodeWrapper.NodeType.STAGE) //Get Stage Type flownodes
  {
    String stageName = node.getDisplayName()
    print "${stageName}"
   
    for (FlowNode enclosing : node.getNode().iterateEnclosingBlocks()) {
      WorkspaceAction ws = enclosing.getAction(WorkspaceAction.class)
      if (ws != null) {
         print "${ws.getNode()}"
      }
    }
  }
}
解决方案

问题出在你遍历的是Stage节点的外层包裹块,这些块可能指向全局Agent的上下文,而非Stage自身绑定的Agent。正确的做法是遍历Stage节点的子节点,找到对应NodeStep的Agent关联信息。

下面是修正后的代码:

WorkflowRun run = Jenkins.instance.getItemByFullName(env.JOB_NAME)._getRuns()[0]
PipelineNodeGraphVisitor visitor = new PipelineNodeGraphVisitor(run)
def flowNodes = visitor.getPipelineNodes()

flowNodes.each { nodeWrapper ->
    if (nodeWrapper.getType() == FlowNodeWrapper.NodeType.STAGE) {
        String stageName = nodeWrapper.getDisplayName()
        def stageNode = nodeWrapper.getNode()
        
        String agentName = null
        
        // 递归遍历Stage下的所有子节点,找到绑定Agent的节点
        PipelineNodeGraphVisitor.visitGraph(stageNode) { flowNode ->
            if (!agentName) {
                // 尝试从NodeStepAction直接获取Agent名称
                NodeStepAction nodeStepAction = flowNode.getAction(NodeStepAction.class)
                if (nodeStepAction != null) {
                    agentName = nodeStepAction.getNode()
                }
                // 备用方案:从WorkspaceAction获取Agent
                WorkspaceAction ws = flowNode.getAction(WorkspaceAction.class)
                if (ws != null) {
                    agentName = ws.getNode()
                }
            }
        }
        
        // 如果Stage未指定单独Agent,回退到全局Agent
        if (!agentName) {
            for (FlowNode enclosing : stageNode.iterateEnclosingBlocks()) {
                WorkspaceAction ws = enclosing.getAction(WorkspaceAction.class)
                if (ws != null) {
                    agentName = ws.getNode()
                    break
                }
            }
        }
        
        println "Stage: ${stageName} -> Agent: ${agentName ?: '未指定Agent'}"
    }
}

代码说明

  1. 遍历Stage子节点:通过PipelineNodeGraphVisitor.visitGraph递归遍历Stage下的所有执行节点,精准定位到绑定Agent的node步骤节点。
  2. 多方式兼容:同时尝试NodeStepAction和WorkspaceAction获取Agent名称,适配不同Jenkins版本和流水线写法。
  3. 回退逻辑:当Stage未单独指定Agent时,自动读取全局Agent信息,兼容全局Agent的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:35:24