如何在声明式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'}" } }
代码说明
- 遍历Stage子节点:通过
PipelineNodeGraphVisitor.visitGraph递归遍历Stage下的所有执行节点,精准定位到绑定Agent的node步骤节点。 - 多方式兼容:同时尝试
NodeStepAction和WorkspaceAction获取Agent名称,适配不同Jenkins版本和流水线写法。 - 回退逻辑:当Stage未单独指定Agent时,自动读取全局Agent信息,兼容全局Agent的场景。
内容的提问来源于stack exchange,提问作者Lara Croft
相关产品推荐
相关产品推荐

