12

I'm trying to create a YAML based pipeline that takes a parameter, then trigger the pipeline to run from a Azure DevOps REST API. I'm able to see the build gets queued, but the parameter was not overridden from my POST body.

My template my-template.yaml.

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


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

My pipeline yaml that extends the template.

trigger:
    - master

extends:
    template: my-template.yaml

Then I trigger this pipeline using the queue build REST API: https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=5.1 with a POST body as below.

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

So I'm expecting the pipeline execution will echo hello world instead of N/A. Unfortunately, I'm still seeing N/A in the pipeline results.

Anyone has idea of what happened? Am I miss anything?

little-eyes
  • 945
  • 2
  • 9
  • 14
  • Seems like an issue in Azure DevOps: https://developercommunity.visualstudio.com/content/problem/1000544/parameters-to-api-rest-build-queue-method.html – MaMazav Jun 18 '20 at 11:15

6 Answers6

16

I ran into the exact same problem - a pipeline taking runtime parameters that worked when run via the UI, but not via the Queue Build REST API.

I was able to solve this by using an undocumented API, the exact same one that the Az DevOps Pipelines UI calls when running a pipeline:

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

With the following POST body:

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

Note that with this API, your runtime parameters are being submitted as actual JSON, not stringified JSON, and under the key templateParameters.

As well, don't forget to include the standard headers one might expect for this call:

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

Using this approach, in the called pipeline, you will always be able to access the value of ${{ parameters.testParam }} whether the pipeline is called via REST API or manually in the UI.

While you're correct that the value is accessible as $(testParam) when executed via REST API, that variable is not populated when running the pipeline in the UI.

As such, I'd recommend using this undocumented API, since the called pipeline can use ${{ parameters.testParam }} without regard to how it's being called. Of course, it's (as of writing) undocumented, so.... ¯_(ツ)_/¯

As well, it should be noted that your pipeline must be formatted as @Josh Gust suggested:

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 }}
akokskis
  • 1,486
  • 15
  • 32
  • Interesting! How did you discover this magical and possibly transcendental api endpoint? – Josh Gust Apr 03 '20 at 23:36
  • 3
    @JoshGust - I watched the network traffic in the chrome dev tools while running the pipeline in the UI to find the POST call the UI was making when running the pipeline. With a few small tweaks, I was able to use it just as the UI code does. – akokskis Apr 05 '20 at 00:42
  • 2
    by now, the api is actually documented. See https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/run%20pipeline?view=azure-devops-rest-6.1 – PaulVrugt Aug 27 '20 at 07:50
  • @akokskis even following the answers in this thread, only looking at the chrome network traffic was able to fix my issue. Your comment should basically be it's own answer – trker Oct 23 '20 at 01:51
  • I have added support for Invoke-APPipeline that supports parameters, resources and variables to the PowerShell module AzurePipelinesPS. https://www.powershellgallery.com/packages/AzurePipelinesPS/3.1.34 – Dejulia489 Feb 02 '21 at 16:08
  • Thank you for this. Microsoft documentation is extensive, but is not concise enough to figure out what I was missing. – DeadlyChambers Dec 23 '21 at 03:32
  • In the mean time the `templateParameters` property is also available for the old `queue build` REST API: https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-6.1 – Lodewijk Jun 02 '23 at 13:44
2

Got the solution after spending 2 to 3 Hour:

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

Right Now I'm using: Postman for testing this API So sharing posting main screenshot: enter image description here enter image description here

In the Body part :

{"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.}

It is working for me And having test around 5 to 7 time

Rawan-25
  • 1,753
  • 1
  • 17
  • 25
  • Thanks, this is the only solution I've found that really solves this issue for me. For future reference, at least for me this is the only approach that works both when curling and when starting a pipeline manually in the gui and selecting a parameter value there. In my case I trigger a curl from a job outside of azure but it is convenient to be able to start the job manually as well. – Kristoffer Aug 14 '20 at 04:02
  • Following the same method but getting below error `{ "$id": "1", "innerException": null, "message": "No pool was specified.", "typeName": "Microsoft.Azure.Pipelines.WebApi.PipelineValidationException, Microsoft.Azure.Pipelines.WebApi", "typeKey": "PipelineValidationException", "errorCode": 0, "eventId": 3000 }` – Devops-Learner May 17 '21 at 13:18
1

Looks like the parameters are not necessary in this case, I merged the yaml into one like below.

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

steps:
    - script: echo $(testParam)

Note the difference between $(testParam) and ${{ parameters.testParam }}.

Then I trigger it from REST API and it works totally fine.

enter image description here

little-eyes
  • 945
  • 2
  • 9
  • 14
1

Seems that it's an issue in Azure DevOps Rest API: https://developercommunity.visualstudio.com/content/problem/1000544/parameters-to-api-rest-build-queue-method.html

​I encountered the same problem and noticed that the runtime parameter is introduced to the pipeline run as variable. Thus using $(MyParam) instead of ${{parameters.MyParam}} in the yaml fixes the problem.

MaMazav
  • 1,773
  • 3
  • 19
  • 33
0

You're not sending your parameter from your pipeline to the template.

Take a look at how the documentation says this should happen. I haven't tested but I think if you wire the parameter to the template properly, you'll get what you expect using the template.

Basically your template should look like this:

# 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 }}

And your pipeline should be thus:

# 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

Notice the parameters: yesNo: false

Also, the Runtime Parameters Documentation might suggest that you should define your pipeline parameters as explicit parameters.

Josh Gust
  • 4,102
  • 25
  • 41
  • Thanks Josh for your reply. Sending the parameter to the template is actually my first trial after reading the documentation you mentioned. However, the parameter value in the echo step is the azure-pipelines.yml parameter value I set, not the one I sent in via REST API. So I removed it and give a try, still not working. – little-eyes Mar 27 '20 at 23:38
  • Did you define a `parameters:` object on the pipeline as well? – Josh Gust Mar 28 '20 at 00:07
  • While you're correct, @JoshGust, there is a deeper issue in that the Queue Build REST API doesn't handle runtime parameters. I explained the details in my answer. – akokskis Apr 03 '20 at 20:25
0

The only thing you need to change is the body of the rest api request

It should be as given below

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

}'

mystack
  • 4,910
  • 10
  • 44
  • 75