不会触发 Azure DevOps REST API 创建的管道

Azure DevOps REST API-created pipeline will not trigger

我使用 REST API.

在 Azure DevOps 中为我的每个存储库创建了 2 个 YAML 管道

管道工作正常,只是它不会在回购更改时触发。不知何故,管道没有被 Azure DevOps 完全识别。 这意味着即使 REST 创建的管道使用默认的 azure-pipelines.yml 文件,回购页面上仍会显示“设置构建”按钮。

此外,当我去 Pipelines 手动设置额外的管道时,我无法做到这一点。它想为 azure-pipelines.yml 文件创建一个新的管道(即使它已经被 REST 创建的管道使用)并且不允许我选择不同的 .yml 文件。

这是我使用 REST 创建管道的代码 API:

string pipelinesURL = $"https://dev.azure.com/{ViewModel.Organization}/{ViewModel.ProjectName}/_apis/pipelines?api-version=6.0-preview.1";

using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Add(
                    new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                    Convert.ToBase64String(
                        System.Text.ASCIIEncoding.ASCII.GetBytes(
                            string.Format("{0}:{1}", "", pat))));

                string folderToUse = "null";
                if (!string.IsNullOrEmpty(folder))
                {
                    folderToUse = "\"" + folder + "\""; //folder + "/"; // @"/" + folder;
                }

                string pipelineDef =
                "{" +
               $"   \"folder\": {folderToUse}," +
               $"   \"name\": \"{name}\"," +
                "   \"configuration\": {" +
                "       \"type\": \"yaml\"," +
               $"       \"path\": \"{yamlPath}\"," +
                "       \"repository\": {" +
               $"           \"id\": \"{repoId}\"," +
               $"           \"name\": \"{repoName}\"," +
                "           \"type\": \"azureReposGit\"" +
                "       }" +
                "   }" +
                "}";

                StringContent stringContent = new StringContent(pipelineDef, Encoding.UTF8, "application/json");

                string url = pipelinesURL;

                   
                using (HttpResponseMessage response = await client.PostAsync(
                        url, stringContent))
                {
                    response.EnsureSuccessStatusCode();
                    string responseBody = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(responseBody);

                    return true;
                }
            }

我该如何解决这个问题?

代码不足以创建工作管道。

此外,使用管道端点也不起作用。它必须是构建定义端点:

https://dev.azure.com/{Organization}/{ProjectName}/_apis/build/definitions?api-version=6.0;

Microsoft 在不同论坛上建议从手动创建的管道中获取定义、修改它并使用它来创建新管道:

您实际上可以使用管道端点来创建管道。在那之后,管道令人困惑地变成了“构建定义”。

只有一个巨大而丑陋的更新端点。因此,在创建管道后,获取响应中返回的 ID (definitionId)。

发出获取请求:

var getDefinitionRequest = new HttpRequestMessage(HttpMethod.Get, $"{request.CollectionUri}build/definitions/{definitionId}");
            getDefinitionRequest.Headers.Authorization =
                new BasicAuthenticationHeaderValue(request.DevopsToken, request.DevopsToken);

            var definitionResponse = await _httpClient.SendAsync(getDefinitionRequest, cancellationToken);
            definitionResponse.EnsureSuccessStatusCode();

然后解析json payload (Json.Net)

var responseObject = JObject.Parse(await definitionResponse.Content.ReadAsStringAsync(cancellationToken));

您现在可以修改它了。要禁用似乎是默认设置的 PR 触发器覆盖,请执行以下操作:

//enable PRs
            var triggers = responseObject.SelectToken("triggers")!.Value<JArray>()!;
            triggers.Add(JObject.Parse(@"{
            ""settingsSourceType"": 2,
            ""branchFilters"": [
                ""+refs/heads/master""
            ],
            ""forks"": {
                ""enabled"": false,
                ""allowSecrets"": false,
                ""allowFullAccessToken"": false
            },
            ""pathFilters"": [],
            ""requireCommentsForNonTeamMembersOnly"": false,
            ""requireCommentsForNonTeamMemberAndNonContributors"": false,
            ""isCommentRequiredForPullRequest"": false,
            ""triggerType"": ""pullRequest""
        }"));

您现在可以将其推回。

var updateDefinitionRequest = new HttpRequestMessage(HttpMethod.Put, $"{request.CollectionUri}build/definitions/{definitionId}?api-version=6.0");
            updateDefinitionRequest.Headers.Authorization =
                new BasicAuthenticationHeaderValue(request.DevopsToken, request.DevopsToken);

            updateDefinitionRequest.Content = new StringContent(responseObject.ToString(Formatting.None));
            updateDefinitionRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            var updateResponse = await _httpClient.SendAsync(updateDefinitionRequest, cancellationToken);

            updateResponse.EnsureSuccessStatusCode();

您也可以使用相同的方法向管道添加变量:

var variables = responseObject.SelectToken("variables");
            JObject items;
            if (variables == null)
            {
                responseObject.Add(new JProperty("variables", items = new JObject()));
            }
            else
            {
                items = variables.Value<JObject>()!;
            }
            
            items["ContainerName"] = new JObject(new JProperty("value", new JValue(request.ContainerName)));
            items["Repository"] = new JObject(new JProperty("value", new JValue(request.RepositoryName)));
            items["OctopusProjectName"] = new JObject(new JProperty("value", new JValue(request.OctopusProjectName)));

用起来很累API。