如何通过VSTS REST API创建Build Definition?只读属性难题求解
我明白你现在的困境——那些BuildDefinition里的集合属性看起来都是只读的,但其实这只是C#的语法表象,你完全可以初始化并修改它们来构建完整的构建定义。下面我会一步步告诉你怎么做,还有替代方案供你选择。
核心误解:“只读”属性其实可修改
你看到的List<BuildDefinitionStep> Steps、IDictionary<string, BuildDefinitionVariable> Variables这些属性,虽然只有get访问器,但它们返回的是可修改的集合实例。你只需要在创建BuildDefinition对象时,先初始化这些集合,然后添加元素即可。比如:
var buildDefinition = new BuildDefinition { Name = "My Bitbucket to Azure Build", Description = "Automated build for Bitbucket repo deployed to Azure", BuildNumberFormat = "$(Date:yyyyMMdd).$(Rev:r)", // 初始化集合属性 Steps = new List<BuildDefinitionStep>(), Variables = new Dictionary<string, BuildDefinitionVariable>(), Triggers = new List<BuildTrigger>(), Repository = new BuildRepository() };
完整的Build Definition构建示例
下面是一个完整的代码片段,展示如何配置Bitbucket仓库、CI触发器、构建步骤和变量,最后调用API创建定义:
using Microsoft.TeamFoundation.Build.WebApi; using Microsoft.VisualStudio.Services.Client; using Microsoft.VisualStudio.Services.WebApi; // 1. 初始化VSTS客户端连接 var vstsUri = new Uri("https://your-account.visualstudio.com"); var credentials = new VssBasicCredential("", "your-personal-access-token"); var connection = new VssConnection(vstsUri, credentials); var buildClient = connection.GetClient<BuildHttpClient>(); // 2. 构建BuildDefinition对象 var buildDefinition = new BuildDefinition { Name = "Bitbucket to Azure CI Build", Description = "Automated build and release pipeline", BuildNumberFormat = "$(Date:yyyyMMdd).$(Rev:r)", BadgeEnabled = true, JobTimeoutInMinutes = 30, JobAuthorizationScope = BuildAuthorizationScope.ProjectCollection, // 初始化集合属性 Steps = new List<BuildDefinitionStep>(), Variables = new Dictionary<string, BuildDefinitionVariable>(), Triggers = new List<BuildTrigger>(), Repository = new BuildRepository { // 配置Bitbucket仓库 Type = "Bitbucket", Url = "https://bitbucket.org/your-team/your-repo.git", DefaultBranch = "refs/heads/main", // 设置认证:使用个人访问令牌或OAuth Properties = new Dictionary<string, string> { {"username", "your-bitbucket-username"}, {"password", "your-bitbucket-app-password"} } } }; // 添加CI触发器(Bitbucket提交时触发) buildDefinition.Triggers.Add(new ContinuousIntegrationTrigger { SettingsSourceType = TriggerSettingsSourceType.Definition, BranchFilters = new List<string> { "+refs/heads/main" } }); // 添加构建步骤:NuGet还原 buildDefinition.Steps.Add(new BuildDefinitionStep { DisplayName = "NuGet restore", TaskId = new Guid("6d15af64-176c-496d-b583-fd2ae21d4df4"), // NuGet还原任务的ID Inputs = new Dictionary<string, string> { {"solution", "**/*.sln"}, {"nugetConfigPath", ""}, {"restoreDirectory", ""} } }); // 添加构建步骤:MSBuild编译 buildDefinition.Steps.Add(new BuildDefinitionStep { DisplayName = "Build solution", TaskId = new Guid("71a9a2d3-a98a-4caa-96ab-affca411ecda"), // MSBuild任务的ID Inputs = new Dictionary<string, string> { {"solution", "**/*.sln"}, {"configuration", "Release"}, {"platform", "Any CPU"} } }); // 添加变量(比如Azure相关配置) buildDefinition.Variables.Add("AzureSubscriptionId", new BuildDefinitionVariable { Value = "your-azure-subscription-id", IsSecret = false }); buildDefinition.Variables.Add("AzureWebAppName", new BuildDefinitionVariable { Value = "your-webapp-name", IsSecret = false }); // 3. 调用API创建构建定义 var createdDefinition = await buildClient.CreateDefinitionAsync( buildDefinition, project: "your-vsts-project-name" ); Console.WriteLine($"Build Definition created with ID: {createdDefinition.Id}");
替代方案:直接调用VSTS REST API
如果你觉得客户端库的封装不够直观,也可以直接发送HTTP请求来创建Build Definition:
POST请求URL:
POST https://your-account.visualstudio.com/your-project-name/_apis/build/definitions?api-version=7.1-preview.7请求体示例(JSON):
你可以先手动在VSTS界面创建一个符合需求的Build Definition,然后用GET请求https://your-account.visualstudio.com/your-project-name/_apis/build/definitions/{definition-id}?api-version=7.1-preview.7导出它的JSON结构,再修改成你需要的自动化配置,作为POST请求的体发送。
这种方法的好处是可以完全控制请求内容,避免客户端库的潜在限制。
小技巧:复用现有定义
最快捷的方式是先手动配置一个满足需求的Build Definition,然后通过API克隆它:
var clonedDefinition = await buildClient.CreateDefinitionAsync( new BuildDefinition { Name = "Cloned Automated Build" }, project: "your-project-name", definitionToCloneId: existingDefinitionId // 你手动创建的定义ID );
之后再根据需要修改克隆后的定义属性,这样比从零开始构建要简单得多。
内容的提问来源于stack exchange,提问作者Anh-Duc

