Azure DevOps YAML管道参数在由REST API触发时不起作用

12

我正在尝试创建一个基于YAML的管道,它需要一个参数,然后通过Azure DevOps REST API触发管道运行。我能够看到构建已排队,但参数没有从我的POST正文中被覆盖。

我的模板my-template.yaml

parameters:
    - name: testParam
      type: string
      default: 'N/A'


steps:
    - script: echo ${{ parameters.testParam }}

扩展模板的我的管道 YAML。

trigger:
    - master

extends:
    template: my-template.yaml

然后我使用queue build REST API触发了这个流水线:https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=5.1,POST 请求的请求体如下。

{
    "parameters": "{\"testParam\": \"hello world\"}",
    "definition": {
        "id": 50642
    },
    "sourceBranch": "refs/heads/master"
}

所以我期望管道执行会打印出hello world而不是N/A。不幸的是,我仍然在管道结果中看到N/A

有人知道发生了什么吗?我错过了什么吗?


似乎是Azure DevOps的问题:https://developercommunity.visualstudio.com/content/problem/1000544/parameters-to-api-rest-build-queue-method.html - MaMazav
6个回答

16

我遇到了完全相同的问题——一个带有运行时参数的流水线,通过UI运行可以工作,但是通过Queue Build REST API无法正常工作。

我能够通过使用一个未记录的API来解决这个问题,这个API与 Az DevOps Pipelines UI 在运行管道时调用的API完全相同:

https://dev.azure.com/{organization}/{project}/_apis/pipelines/{pipelineId}/runs?api-version=5.1-preview

POST请求体如下:

{
  "stagesToSkip": [],
  "resources": {
    "repositories": {
      "self": {
        "refName": "refs/heads/master"
      }
    }
  },
  "templateParameters": {
    "testParam": "hello world"
   },
  "variables": {}
}

请注意,在此API中,您的运行时参数将被提交为实际的JSON,而不是字符串化的JSON,并位于键templateParameters下。

另外,请勿忘记包含此调用所需的标准标头:

  • Content-Type: application/json
  • Accept: application/json
  • AUTHORIZATION: bearer $SYSTEM_ACCESSTOKEN

使用这种方法,在调用的流水线中,您始终可以访问${{ parameters.testParam }}的值,无论是通过REST API还是在UI中手动调用流水线。

尽管您正确地指出了通过REST API执行时该值可作为$(testParam)访问,但在UI中运行流水线时,该变量没有填充。

因此,我建议使用此未记录的API,因为调用的流水线可以使用${{ parameters.testParam }}而不必考虑它是如何被调用的。当然,这是(截至撰写本文时)未记录的,所以... ¯_(ツ)_/¯

另外,应注意您的流水线必须按照Josh Gust的建议进行格式化:

my-template.yaml:

parameters:
  - name: testParam
    type: string
    default: 'N/A'
steps:
  - script: echo ${{ parameters.testParam }}

azure-pipelines.yaml:

parameters:
  - name: testParam
    type: string
    default: 'N/A'
trigger:
  - master
extends:
  template: my-template.yaml
  parameters:
    testParam: ${{ parameters.testParam }}

有趣!你是怎么发现这个神奇而可能超凡的API端点的? - Josh Gust
3
我在使用UI运行pipeline时,在Chrome开发工具中观察网络流量,找到了UI在运行pipeline时所做的POST请求。通过一些小调整,我成功地像UI代码一样使用了它。 - akokskis
2
到目前为止,该API已经有文档可供参考。请访问https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/run%20pipeline?view=azure-devops-rest-6.1。 - PaulVrugt
我已经在PowerShell模块AzurePipelinesPS中添加了Invoke-APPipeline的支持,该支持支持参数、资源和变量。https://www.powershellgallery.com/packages/AzurePipelinesPS/3.1.34 - Dejulia489
谢谢您。微软的文档非常详尽,但不够简洁明了,无法找出我所缺失的内容。 - DeadlyChambers
显示剩余2条评论

2

经过2到3小时的努力,终于找到了解决方案:

https://dev.azure.com/{organization}/{project}/_apis/pipelines/2/runs?api-version=6.0-preview.1

   Where 2= {pipelineId}

enter image description here

Header :

Authorization: Personal access token. Use any value for the user name and the token as the password.
Type: basic

Content-Type : application/json
Accept : application/json

目前我正在使用:Postman来测试这个API,下面分享主要截图:
在这里输入图片描述
在这里输入图片描述

在 Body 部分:

{"previewRun":false,"stagesToSkip": [],"resources": {"repositories": {"self": {"refName": "refs/heads/master"}}},"templateParameters": {"testParam": "rawat Rob" },"variables": {}}

previewRun :{If true, don't actually create a new run. Instead, return the final YAML document after parsing templates.}

对我来说它正在运作,并且已经测试了5到7次


谢谢,这是我找到的唯一真正解决这个问题的方法。供将来参考,至少对我来说,这是唯一既适用于curl,又适用于在GUI中手动启动管道并选择参数值的方法。在我的情况下,我从Azure外部的作业触发了一个curl,但也很方便能够手动启动作业。 - Kristoffer
按照相同的方法进行操作,但是出现以下错误: { "$id": "1", "innerException": null, "message": "未指定池。", "typeName": "Microsoft.Azure.Pipelines.WebApi.PipelineValidationException, Microsoft.Azure.Pipelines.WebApi", "typeKey": "PipelineValidationException", "errorCode": 0, "eventId": 3000 } - Devops-Learner

1

看起来在这种情况下参数是不必要的,我将yaml合并成以下形式。

# File: azure-pipelines.yml
trigger:
    - master

steps:
    - script: echo $(testParam)


请注意$(testParam)${{ parameters.testParam }}之间的区别。
然后我通过REST API触发它,它完全正常工作。

enter image description here


1

0

你需要改变的唯一事情就是 REST API 请求的主体

应该如下所示

   $body='{
   "definition": {            "id": "50642"        },
   "sourceBranch": "refs/heads/master",
   "templateParameters": {
   "testParam": "hello world"
    },
   "variables": {}


0

你没有将管道中的参数发送到模板。

看一下文档,它说明了应该如何操作。我没有测试过,但我认为如果你正确地将参数连接到模板,你将会得到使用模板所期望的结果。

基本上,你的模板应该长这样:

# File: simple-param.yml
parameters:
- name: yesNo # name of the parameter; required
  type: boolean # data type of the parameter; required
  default: false

steps:
    - script: echo ${{ parameters.yesNo }}

你的管道应该像这样:

# File: azure-pipelines.yml
trigger:
- master

extends:
    template: simple-param.yml
    parameters:
        yesNo: false # set to a non-boolean value to have the build fail

请注意参数:yesNo: false

另外运行时参数文档可能会建议您将管道参数定义为显式参数。


感谢Josh的回复。将参数发送到模板实际上是我在阅读您提到的文档后的第一次尝试。然而,在echo步骤中的参数值是我设置的azure-pipelines.yml参数值,而不是我通过REST API发送的参数值。因此,我将其删除并尝试了一下,但仍然无法正常工作。 - little-eyes
你在管道上也定义了一个 parameters: 对象吗? - Josh Gust
虽然你说得没错,@JoshGust,但更深层次的问题是队列构建 REST API 无法处理运行时参数。我在我的回答中解释了细节。 - akokskis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接