Get value in JSON object from external URI - powershell

In my PowerShell code I have:
$retrieveSourceBranchFromBuildURL = "https://dev.azure.com/$organization/$project/_apis/build/builds/$buildId" + "?api-version=5.0"
When I navigate to the URL in the browser I see:
{
_links: {
self: {
href: "https://dev.azure.com/something/7720f8d2-bf64-47d9-8b10-53f21220d54d/_apis/build/Builds/46070"
},
web: {
href: "https://dev.azure.com/something/7720f8d2-bf64-47d9-8b10-53f21220d54d/_build/results?buildId=46070"
},
sourceVersionDisplayUri: {
href: "https://dev.azure.com/something/7720f8d2-bf64-47d9-8b10-53f21220d54d/_apis/build/builds/46070/sources"
},
timeline: {
href: "https://dev.azure.com/something/7720f8d2-bf64-47d9-8b10-53f21220d54d/_apis/build/builds/46070/Timeline"
},
badge: {
href: "https://dev.azure.com/something/7720f8d2-bf64-47d9-8b10-53f21220d54d/_apis/build/status/67"
}
},
parameters: "{"system.pullRequest.pullRequestId":"5766","system.pullRequest.sourceBranch":"refs/heads/pb/31333-test-branch/name","system.pullRequest.targetBranch":"refs/heads/master","system.pullRequest.sourceCommitId":"1cf19b95a59478a8554c2c03d65dcefe203529a6","system.pullRequest.sourceRepositoryUri":"https://something#dev.azure.com/something/something%20Suite/_git/client-web","system.pullRequest.pullRequestIteration":"1"}",
}
The $buildInformation variable:
$buildInformation = Invoke-RestMethod -Uri $retrieveSourceBranchFromBuildURL -Headers #{Authorization = $pat } -Method Get -ContentType 'application/json'
When I output the value of $buildInformation I get:
#{_links=; properties=; tags=System.Object[]; validationResults=System.Object[]; plans=System.Object[]; triggerInfo=; id=46079; buildNumber=20190624.3; status=completed; result=succeeded; queueTime=2019-06-24T07:57:05.7271255Z; startTime=2019-06-24T07:57:12.8021227Z; finishTime=2019-06-24T08:12:27.003113Z; url=https://dev.azure.com/embrace/7720f8d2-bf64-47d9-8b10-53f21220d54d/_apis/build/Builds/46079; definition=; buildNumberRevision=3; project=; uri=vstfs:///Build/Build/46079; sourceBranch=refs/pull/5740/merge; sourceVersion=735f7a813c343dbbca5e1d1b3e966e0bad1db762; priority=normal; reason=pullRequest; requestedFor=; requestedBy=; lastChangedDate=2019-06-24T08:14:41.11Z; lastChangedBy=; parameters={"system.pullRequest.pullRequestId":"5740","system.pullRequest.sourceBranch":"refs/heads/master-md/social-create-team","system.pullRequest.targetBranch":"refs/heads/master","system.pullRequest.sourceCommitId":"e744e5c35bc3fd1539d5c49daa29147f048f3276","system.pullRequest.sourceRepositoryUri":"https://embrace#dev.azure.com/embrace/Embrace%20Suite/_git/client-web","system.pullRequest.pullRequestIteration":"5"}; orchestrationPlan=; logs=; repository=; keepForever=False; retainedByRelease=True;
When I output the value of $buildInformation.parameters:
Write-Host $buildInformation.parameters
{
"system.pullRequest.pullRequestId":"5740",
"system.pullRequest.sourceBranch":"refs/heads/master-md/social-create-team",
"system.pullRequest.targetBranch":"refs/heads/master",
"system.pullRequest.sourceCommitId":"e744e5c35bc3fd1539d5c49daa29147f048f3276",
"system.pullRequest.sourceRepositoryUri":"https://embrace#dev.azure.com/embrace/Embrace%20Suite/_git/client-web",
"system.pullRequest.pullRequestIteration":"5"
}
But when I try to read a value:
Write-Host $buildInformation.parameters.system.pullRequest.sourceBranch
The output is empty.
So how do I retrieve the parameters.system.pullRequest.sourceBranch value?

To access the property with 'special characters' in its name, enclose the parameter name inside quotes like so:
$buildInformation.parameters.'system.pullRequest.sourceBranch'
NOTE: The trick here is that the value of parameters is inside double quotes. Therefore you might not be able to access the properties under parameters the usual way. To workaround it, you can make a conversion directly on parameters:
$convertedParams = $buildInformation.parameters | ConvertFrom-Json
# Access desired property
$convertedParams.'system.pullRequest.sourceBranch'
When you access the property like you tried
$buildInformation.parameters.system.pullRequest.sourceBranch
the structure of your JSON should be like this:
PS> $buildInformation = '{
"parameters": {
"system": {
"pullRequest":{
"sourceBranch": "refs/heads/master-md/social-create-team"
}
}
}
}' | ConvertFrom-Json
# Checking output
PS> $buildInformation.parameters.system.pullRequest.sourceBranch
refs/heads/master-md/social-create-team

Related

Cannot mention person in Adaptive Card using Teams PowerShell Module

I have registered an Incoming Messages Webhook in one of my Teams channels.
I am using Microsoft Teams PowerShell to create an adaptive card and send it to a channel:
$SimpleCard = #{
type = "message";
attachments = #(#{
contentType = 'application/vnd.microsoft.card.adaptive';
contentUrl = $null;
content = #{
'$schema' = 'http://adaptivecards.io/schemas/adaptive-card.json';
type = 'AdaptiveCard';
version = '1.2';
body = #(#{
type = 'TextBlock';
text = "Hello <at>andrea.tino#mycompany.com</at>";
})
}
});
msteams = #{
entities = #(#{
type = 'mention';
text = "<at>andrea.tino#mycompany.com</at>";
mentioned = #{
id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
name = 'Andrea Tino';
}
})
}
}
Invoke-RestMethod -Method post
-ContentType 'Application/Json'
-Body ($SimpleCard | ConvertTo-Json -Depth 10)
-Uri "https://myorg.webhook.office.com/webhookb2/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx#xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/IncomingWebhook/xxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
The card is correctly sent but the mention is not correctly rendered.
Wrong ID?
It is worth mentioning that the doc makes explicit reference to a type of User ID:
{
"type": "mention",
"text": "<at>John Doe</at>",
"mentioned": {
"id": "29:123124124124",
"name": "John Doe"
}
}
You can see that the ID in the example is: "id": "29:123124124124" while mine is a GUID. I retrieved that User ID by means of Get-TeamUser.
What am I doing wrong?
Mention in adaptive card is supported only in context of bot and the available ways to get id are listed in the document - mention-support-within-adaptive-cards-v12
Concerned team is working to support user mention using AAD Object Id and UPN(use Graph API) in Incoming Webhook.
ID and Name can be fetched from the activity as follows
from: {
id: '29:15fREhoUuf6vVCOuaJYVH-AB6QXXX',
name: 'MOD Administrator',
aadObjectId: 'XXXX'
}
Giving a reference that will help - mention-support-within-adaptive-cards-v12

How to add branch policies using powershell Invoke RestMethod

We have PowerShell script that will automate creating branch.
Now we are trying to automate branch policies using api using PowerShell Invoke-RestMethod.
We have option to manually add policies using cross repository policies, but we have build validation enabled for repositories which is different for each repo.
I'm able to get the policy configurations using GET https://dev.azure.com/$organization/$project/_apis/policy/configurations/repo=$repoName&api-version=6.0
But don't know how to get the get the particular value and add policies.
You can use the Configurations - Create Rest API:
POST https://dev.azure.com/{organization}/{project}/_apis/policy/configurations/{configurationId}?api-version=6.1-preview.1
In the body you specify the branch policy you want to add, for example - build policy:
{
"isEnabled": true,
"isBlocking": false,
"type": {
"id": "0609b952-1397-4640-95ec-e00a01b2c241"
},
"settings": {
"buildDefinitionId": 5,
"scope": [
{
"repositoryId": null,
"refName": "refs/heads/feature",
"matchKind": "prefix"
}
]
}
}
In the above body you add branch (build) policy to branch feature that requires build 5 to pass.
You cans see all the available policy types in the Types - List api.
To add the Build validation in Branch Policy, you could refer to the following PowerShell Sample:
$token = "PAT"
$url="https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/policy/configurations?api-version=6.1-preview.1"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #'
{
"type":{
"id":"0609b952-1397-4640-95ec-e00a01b2c241"
},
"revision":1,
"isDeleted":false,
"isBlocking":true,
"isEnabled":true,
"settings":{
"buildDefinitionId":592,
"displayName":null,
"manualQueueOnly":false,
"queueOnSourceUpdateOnly":true,
"validDuration":720,
"scope":[
{
"repositoryId":"RepoID",
"refName":"refs/heads/BranchName",
"matchKind":"Exact"
}
]
}
}
'#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method POST -Body $JSON -ContentType application/json
You could refer to this doc about Configurations - Create and Repositories - List
Result:

PowerShell GraphQL Mutation Parsing Error

I'm querying the Monday API v2 (https://monday.com/developers/v2) I'm getting stuck in getting the PowerShell query to work, the script is below:
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
$url = "https://api.monday.com/v2/"
$hdr = #{ }
$hdr.Add("Authorization", "redacted")
$hdr.Add("Content-Type", "application/json")
$bodytxt = '{"query":"mutation{change_column_value (board_id: 528033866, item_id: 574335355, column_id: \"status_1\", value: "{\"index\": 1}") {id}}"}'
$response = Invoke-WebRequest -Uri $url -Headers $hdr -Method Post -body $bodytxt
Write-Host $response
And it keeps returning
{"errors":[{"message":"Parse error on \": 1}\" (STRING) at [1, 110]","locations":[{"line":1,"column":110}]}],"account_id":5305133}
The mutation query in Postman works fine
change_column_value (board_id: 528033866, item_id: 574335355, column_id: "status_1", value: "{\"index\": 1}"){id}
}
I have tried working with what quotes are escaped, but I still haven't been able to get it to run succesfully. I was referencing the tips here https://www.reddit.com/r/PowerShell/comments/b9jasa/query_graphql_with_powershell/
Any thoughts on how to fix this error?
EDIT: Sorry forgot to add the current query (not mutation) that works fine through Powershell
$bodytxt = '{"query":"{ boards (ids: 528033866) { groups (ids: \"group_title\"){ items () { id name updates () { body } column_values () { id title value text } } title } } }"}'
The easiest way to create a GraphQL query is
create a hashtable with HERE-STRINGS
convert it to a JSON string with ConvertTo-Json.
$bodytxt = #{"query" = #'
mutation {
change_column_value(
board_id: 123123
item_id: 456456
column_id: "status1"
value: "{\"index\":1}"
) {
id
}
}
'#
} | ConvertTo-Json
White spaces inside #'...'# are optional.
reply to this comment
it should always work in the API call with the GraphQL?
I think it depends on services, but in most cases, yes. application/json is the GraphQL default content type for the request body.
and for monday.com
Be sure to use the application/json content type

Querying GraphQL with PowerShell

So I've been trying to query GraphQL from PowerShell. Everything looks perfect in a cmd, but I cannot make it work in PS, see, I have this code so far:
$oAuth2TokenUrl = "https://api.cloudflare.com/client/v4/zones/0000/analytics/dashboard"
$accessKey = '1111'
$Cloudflare_Oauth_Header = #{
"Authorization" = "Bearer $accessKey";
}
$query = #'
{ "query": "query { viewer {
zones(filter: {zoneTag: 0000}) {
httpRequests1mGroups(orderBy: [datetimeMinute_ASC], limit: 1000, filter: {datetime_geq: "2019-09-08T20:00:00Z", datetime_lt: "2019-09-08T20:02:00Z"}) {
dimensions {datetimeMinute}
sum {
browserMap {
pageViews
uaBrowserFamily
}
bytes
cachedBytes
cachedRequests
contentTypeMap {
bytes
requests
edgeResponseContentTypeName
}
clientSSLMap {
requests
clientSSLProtocol
}
countryMap {
bytes
requests
threats
clientCountryName
}
encryptedBytes
encryptedRequests
ipClassMap {
requests
ipType
}
pageViews
requests
responseStatusMap {
requests
edgeResponseStatus
}
threats
threatPathingMap {
requests
threatPathingName
}
}
uniq {
uniques
}
}
}
} }" }
'#
$Cloudflare_zone = Invoke-RestMethod -Method Post -Headers $Cloudflare_Oauth_Header -ContentType "application/json; charset=utf-8" -Uri $oAuth2TokenUrl -Body $query
And I keep getting the error Invoke-RestMethod : The remote server returned an error: (501) Not Implemented.
But if I curl in cmd it returns what is expected and no error is shown.
Please let me know if you need more details.
I would suggest getting a simple query to work first, and then expanding it to be more complex. Also, be sure to use -ContentType "application/json" which some GraphQL servers require. The switch -UseBasicParsing can also help avert error but probably isn't the issue here. Lastly, you might also need a trailing slash in the URL: E.g., http://127.0.0.1:8080/graphql/.
This thread might also help:
https://www.reddit.com/r/PowerShell/comments/b9jasa/query_graphql_with_powershell/
I have a GraphQL module for PowerShell with a single function (Invoke-GraphQLQuery that may help you here). Link: https://github.com/anthonyg-1/PSGraphQL
But I definitely agree that you should start with a much smaller query. Check out some of the examples in my readme or run Get-Help Invoke-GraphQLQuery for more.

Adding a key/value pair to an object in VTL (for API Gateway)

I am writing a mapping template for an AWS API Gateway integration response. I would like to add a key/value pair to the JSON object returned my Lambda function.
My function returns some JSON like this:
{
"id": "1234",
"name": "Foo Barstein"
}
I would like the template to output something like this:
{
"id": "1234",
"name": "Foo Barstein",
"href": "https://example.tld/thingy/1234"
}
And my mapping template looks like this:
#set($thingy = $input.json('$'))
#set($thingy.href = "https://example.tld/thingy/$thingy.id")
$thingy
However, my template outputs the unmodified $thingy, without the href I have tried to add.
I've read the VTL user guide, but to no avail.
Something like this has worked for me:
#set($body = $input.path('$'))
#set($body.href = "https://example.tld/thingy/$body.id")
$input.json('$')
There is no easy way to achieve this but you can workaround it:
## Mapping template
#set($body = $input.body)
#set($id = $input.json('$.id'))
{
"custom": {
"href" : "https://example.tld/thingy/$id"
},
"body": $body
}
And then merge all the keys in AWS.Lambda (if you use Lambda):
## Lambda handler
exports.handler = function(event, context) {
const requestParams = Object.assign({}, event.body, event.custom);
// ... function code
}
And requestParams will be what you want.
Following could do the trick. Beware, untested!
{
#set($payload = $util.parseJson($input.json('$')))
#set($body = "{
#foreach ($mapEntry in $payload.entrySet())
""$mapEntry.key"": ""$mapEntry.value"",
#end
""href"": ""$payload.id""
}")
$body
}