Home > Software design >  Create Pull Request by Azure DevOps Service REST API with Linux Shell script
Create Pull Request by Azure DevOps Service REST API with Linux Shell script

Time:06-02

I try to create a Pull Request by the Azure DevOps Services REST API. I am using PAT which is working with getting WorkItems like:

#!/bin/bash
source ~/bin/variables.sh
id=${1}
url="$(organization)/$(project)/_apis/wit/workitems/${id}?api-version=7.1-preview.3"
workItem=$(curl -s -u $(presenter):$(PAT) -X GET "${url}")
  • organization is our organization-url.
  • project is the project name.
  • presenter is the user.name (from az account show)
  • PAT is the personal access token.

I created a Json like:

{
     "sourceRefName": "refs/heads/U1367_My_Source_Branch",
     "targetRefName": "refs/heads/F231_My_Target_Branch",
     "title": "F231 Source bla foo. U1367 Target bla foo",
     "description": "Bla foo WorkItem: #2117",
     "isDraft": true
}

The Json is generated without newlines:

json='{"sourceRefName":"'${source}'","targetRefName":"'${target}'","title":"'${title}'","description":"'${description}'","isDraft":true}'

and send it with the following:

 url="https://dev.azure.com/$(organizationName)/$(project)/_apis/git/repositories/${repo}/pullrequests?supportsIterations=true&api-version=7.1-preview.1"
 response=$(curl -s -u $(presenter):$(PAT) -X POST -H "Content-Type: application/json" -d '${json}' "${url}")
  • organizationName is our organization name :-)
  • repo is the id (Guid) of the repo

I get this response:

{
    "$id": "1",
    "innerException": null,
    "message": "TF400898: An Internal Error Occurred. Activity Id: 169c9863-5441-40a6-8e8d-4c826faf8308.",
    "typeName": "Newtonsoft.Json.JsonReaderException, Newtonsoft.Json",
    "typeKey": "JsonReaderException",
    "errorCode": 0,
    "eventId": 0
}

I checked the permissions of the PAT. I have the permission to create pull requests.

Any suggestions to create a working pull request via the API by a shell script?

CodePudding user response:

Expanding my comment to a full answer:

In shell scripts, we use quotes (single or double) and/or backslashes to get shell metacharacters to go into the variable's setting. Single quotes work to quote double quotes, and double quotes work to quote single quotes; the quote ends when we come across the matching close quote. For instance:

DQ='"'

sets variable $DQ to the double quote symbol, while:

SQ="'"

sets variable $SQ to the single quote (or apostrophe or whatever you like to call it) symbol. Meanwhile:

DONT='John yelled "don'"'"'t"'
#     ----------------  =  --

sets $DONT; the contents are partly single-quoted (as underlined with -) and partly double quoted (as underlined with =) and contain literal double quotes and an apostrophe / single-quote, so that when expanded, we see:

$ echo "$DONT"
John yelled "don't"

Here, you have:

json='{"sourceRefName":"'${source}'","targetRefName":"'${target}\
'","title":"'${title}'","description":"'${description}'","isDraft":true}'

(but all in one line—I split it here just for StackOverflow posting) which, if we first set source and target and so on, and run it and then run echo "$json", shows that it sets the variable json correctly). Unfortunately, you then have:

response=$(curl -s -u $(presenter):$(PAT) -X POST \
-H "Content-Type: application/json" -d '${json}' "${url}")

(which I have once again split for StackOverflow posting).

When we want the shell to expand some variable we must not use single quotes. So -d '${json}' is wrong: you want -d "${json}" or just -d "$json".

(In a POSIX style shell, ${var} requires the braces only if $var is followed by something that might be interpreted as more letters of the variable, or if we want to use certain fancy constructs like ${var?error} and the like. So if we want to print the contents of variable $v followed by the literal string ariable, we need ${v}ariable so that it's not taken as ${variable} instead—but if we want $v followed by $ariable we can write $v$ariable, and when using double quotes as in "$var" the closing double quote suffices so that we could write "$v"ariable, for instance.)

The precise rules for when to use which kind of quote can get hairy in some special circumstances, but the short way to remember this is that single quotes are more powerful than double quotes:

echo "$hello $world"

expands both $hello and $world but:

echo '$hello $world'

expands neither one. Getting a literal single quote into single quotes is ugly though: we get constructs like the one for DONT= above. Sometimes it's nice to set variables DQ and SQ and use double quotes:

DQ='"'
SQ="'"
DONT="John yelled ${DQ}Don${SQ}t${DQ}"

after which:

echo "$DONT"

prints what we want, yet the variable setting is ... almost readable.

  • Related