如何用C#通过Azure DevOps API批量更新生成与发布定义的代理池?
完全可以通过Azure DevOps REST API或者官方.NET客户端库实现你描述的逻辑,以下是具体实现方案:
前置准备
- 申请Azure DevOps个人访问令牌(PAT),授权范围勾选 生成(Build)的读取、写入和管理、发布(Release)的读取、写入和管理
- 安装对应NuGet依赖包:
Install-Package Microsoft.TeamFoundationServer.Client Install-Package Microsoft.VisualStudio.Services.Release.Client
核心代码实现
1. 初始化服务连接
using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Services.WebApi; using Microsoft.TeamFoundation.Build.WebApi; using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi.Clients; using Microsoft.VisualStudio.Services.ReleaseManagement.WebApi; // 配置参数 string orgUrl = "https://dev.azure.com/你的组织名称"; string pat = "你的PAT令牌"; int oldPoolId = 旧代理池ID; int newPoolId = 新代理池ID; string updateComment = "迁移到Azure环境,统一更新代理池"; // 初始化连接 var credentials = new VssBasicCredential(string.Empty, pat); var connection = new VssConnection(new Uri(orgUrl), credentials); // 初始化生成、发布服务客户端 var buildClient = connection.GetClient<BuildHttpClient>(); var releaseClient = connection.GetClient<ReleaseHttpClient>();
2. 筛选并更新生成定义
// 可根据需求添加筛选条件,比如名称前缀、创建时间、路径等,避免全量拉取 List<BuildDefinition> buildDefinitions = await buildClient.GetDefinitionsAsync( project: "你的项目名称", // 可选筛选参数示例:name: "前缀*", minCreatedTime: DateTime.Now.AddDays(-30) ); foreach (var def in buildDefinitions) { // 获取完整定义详情 var fullDef = await buildClient.GetDefinitionAsync(def.Project.Id, def.Id); // 遍历生成定义下的所有代理作业 if (fullDef.Process is DesignerProcess designerProcess) { bool hasUpdate = false; foreach (var phase in designerProcess.Phases.OfType<AgentJobPhase>()) { if (phase.Target?.Id == oldPoolId) { phase.Target.Id = newPoolId; hasUpdate = true; } } // 有变更才提交更新 if (hasUpdate) { fullDef.Comment = updateComment; await buildClient.UpdateDefinitionAsync(fullDef, fullDef.Project.Id, fullDef.Id); } } }
3. 筛选并更新经典发布定义
// 同样可添加筛选条件减少拉取量 List<ReleaseDefinition> releaseDefinitions = await releaseClient.GetReleaseDefinitionsAsync( project: "你的项目名称", // 可选筛选参数示例:searchText: "前缀*", isDeleted: false expand: ReleaseDefinitionExpands.Phases ); foreach (var def in releaseDefinitions) { // 获取完整定义详情 var fullDef = await releaseClient.GetReleaseDefinitionAsync(def.Project.Id, def.Id); bool hasUpdate = false; // 遍历发布定义的所有阶段 foreach (var environment in fullDef.Environments) { // 遍历阶段下的所有代理作业 foreach (var phase in environment.DeployPhases.OfType<AgentDeploymentPhase>()) { if (phase.DeploymentInput?.QueueId == oldPoolId) { phase.DeploymentInput.QueueId = newPoolId; hasUpdate = true; } } } // 有变更才提交更新 if (hasUpdate) { fullDef.Comment = updateComment; await releaseClient.UpdateReleaseDefinitionAsync(fullDef, fullDef.Project.Id, fullDef.Id); } }
注意事项
- 执行前建议先注释更新接口调用,打印待修改的定义列表验证匹配规则,确认无误后再执行写入操作
- 旧代理池ID可以在代理池的页面URL中获取,格式一般为
_settings/agentpools?poolId=xxx中的xxx数值 - 该方案仅适用于经典生成/发布定义,YAML格式的定义需要修改yaml文件本身,不适用该接口逻辑
内容的提问来源于stack exchange,提问作者jvanderwoude
相关产品推荐
相关产品推荐

