【问题标题】:Queue Azure devops YAML pipeline from code does not accept runtime parameters来自代码的队列 Azure devops YAML 管道不接受运行时参数
【发布时间】:2021-01-04 02:35:31
【问题描述】:

YAML 管道如下所示

parameters:
  - name: parameter1
    type: string
steps:
task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      # Write your PowerShell commands here.
      Write-Host ${{ parameters.parameter1 }}


队列构建的 C# 代码就像

var build = new Build()
            {
                Definition = definition,
                Project = project

            };
var dict = new Dictionary<string, string> { { "parameter1", "parametervalue" } };
build.Parameters = JsonSerializer.Serialize(dict);
buildClient.QueueBuildAsync(build).Wait();

我收到异常无法将构建排队,因为存在验证错误或警告。必须提供“parameter1”参数的值。 解决此问题的任何想法都会有所帮助。

【问题讨论】:

  • 这里的参数不是运行时参数而是变量。我不确定这是否暴露给 SDK 以传递运行时参数。如果这是您的选择,您可以尝试定义默认值。
  • @ShaykiAbramczyk 我不确定这是否是重复的。 Pankaj 想要传递运行时参数 programaticallu,当您提出问题时,该参数尚不可用。
  • @KrzysztofMadej 同意,但我认为它应该有效。 Pankaj 你能测试一下吗?
  • 我对其进行了测试,但我得到了需要 parameter1 的异常。很明显,这里是错误的。但我认为这不是通过 SDK 公开的,或者有一种神奇的方式可以通过它。我也尝试将其传递为parameters.paramter1,但结果相同。
  • 我重新打开了问题:)

标签: c# azure-devops yaml azure-pipelines tfs-sdk


【解决方案1】:

目前看来,通过 C# SDK 传递运行时参数来运行管道是不可能的。您找到了使用 REST API 的解决方法。

这不是 SDK 的问题。他们按照自己的节奏发展。因此,在 REST API 中可用的功能并不总是在 SDK 中同时可用。它可能在未来可用,但目前如果你想以编程方式运行它,你需要使用 REST API。

【讨论】:

  • 一年过去了,还是这样吗?另外,C# 客户端代码是开源的吗?我好像没找到?
【解决方案2】:

我设法对一些可能对其他人有所帮助的客户端代码进行了逆向工程。它可能尚未完全投入生产,但请随时对其进行改进:

public class PipelineHttpClient : VssHttpClientBase
{
    public PipelineHttpClient(Uri baseUrl, VssCredentials credentials) 
        : base(baseUrl, credentials)
    {
    }

    public PipelineHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings) 
        : base(baseUrl, credentials, settings)
    {
    }

    public PipelineHttpClient(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers) 
        : base(baseUrl, credentials, handlers)
    {
    }

    public PipelineHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers) 
        : base(baseUrl, credentials, settings, handlers)
    {
    }

    public PipelineHttpClient(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler) 
        : base(baseUrl, pipeline, disposeHandler)
    {
        
    }

    public async Task<PipelineRun> RunPipelineAsync(Guid project, int pipelineId, object parameters, string refName = "refs/heads/master")
    {
        var method = HttpMethod.Post;
        var locationId = Guid.Parse("7859261e-d2e9-4a68-b820-a5d84cc5bb3d");
        object routeValues = new
        {
            project,
            pipelineId,
            //pipelineVersion = ""
        };
        var version = new ApiResourceVersion("6.0");
        
        // ensure that the refName is prefixed correctly.
        refName = refName.StartsWith("refs/heads/", StringComparison.InvariantCultureIgnoreCase) 
            ? refName 
            : $"refs/heads/{refName}";

        var content = (HttpContent) new ObjectContent<object>(new
            {
                StagesToSkip = new object[0],
                TemplateParameters = parameters,
                Variables = new object(),
                Resources = new
                {
                    Repositories = new
                    {
                        Self = new
                        {
                            RefName = refName
                        }
                    }
                }
            },
            new VssJsonMediaTypeFormatter(true));
        var queryParameters = new Dictionary<string, string>();
        return await SendAsync<PipelineRun>(method, locationId, routeValues, version, content, queryParameters, cancellationToken: CancellationToken.None);
    }
}

public class Pipeline
{
    [JsonProperty("url")]
    public string Url { get; set; }

    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("revision")]
    public int Revision { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("folder")]
    public string Folder { get; set; }
}

public class Repository
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }
}

public class Self
{
    [JsonProperty("repository")]
    public Repository Repository { get; set; }

    [JsonProperty("refName")]
    public string RefName { get; set; }

    [JsonProperty("version")]
    public string Version { get; set; }
}

public class Repositories
{
    [JsonProperty("self")]
    public Self Self { get; set; }
}

public class Resources
{
    [JsonProperty("repositories")]
    public Repositories Repositories { get; set; }
}

public class PipelineRun
{
    [JsonProperty("pipeline")]
    public Pipeline Pipeline { get; set; }

    [JsonProperty("state")]
    public string State { get; set; }

    [JsonProperty("createdDate")]
    public DateTime CreatedDate { get; set; }

    [JsonProperty("url")]
    public string Url { get; set; }

    [JsonProperty("resources")]
    public Resources Resources { get; set; }

    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

用法:

PipelineHttpClient client = new PipelineHttpClient(...);
var project = Guid.Parse("TODO");
var pipelineId = 1234;
// pipeline parameters:
var parameters = new {meaningOfLife = 42};
var result = await client.RunPipelineAsync(project, pipelineId, parameters, "refs/heads/feature/my-branch");
if (result.State == "inProgress")
{
    // TODO the pipeline is running!
}

【讨论】:

    猜你喜欢
    • 2022-11-03
    • 2020-08-26
    • 2022-08-02
    • 1970-01-01
    • 2019-11-17
    • 2020-06-08
    • 2020-12-20
    • 2020-05-23
    • 1970-01-01
    相关资源
    最近更新 更多