I'm trying to create a comment in a Azure Devops Pull Request thread:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Variables
$organization = "movieseat"
$project = "pokedex"
$repositoryId = "Pokedex"
$pullRequestId = "97"
$threadId = "283"
$pat = "Bearer $env:System_AccessToken"
$body = #"
{
"content"="Finished building feature branch"
"commentType"="text";
}
"#
$postURL = "https://dev.azure.com/$organization/$project/_apis/git/repositories/$repositoryId/pullRequests/$pullRequestId/threads/$threadId/comments?api-version=5.0"
$prComment = Invoke-RestMethod -Uri $postURL -Headers #{Authorization = $pat} -Body $body -Method Post -ContentType 'application/json'
Write-Output $prComment
But during the release step I get:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Value cannot be null.\r\nParameter name:
comment","typeName":"System.ArgumentNullException,
mscorlib","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}
At D:\a\r1\a\_Pokedex master\PokeDexArtifact\release\commentURL.ps1:49 char:14
+ ... prComment = Invoke-RestMethod -Uri $postURL -Headers #{Authorization ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
##[error]PowerShell exited with code '1'.
##[section]Finishing: PowerShell Script
I can't find any info relating to this error.
I'm not 100% sure, but I think this was the actual error:
message":"Value cannot be null.\r\nParameter name: comment",
$body = #"
{
"content": "http://google.com",
"commentType": "text";
}
"#
Running the code like this works. Notice the , after the content value. Although I removed the commentType value since it works without it as well.
// edit. I've updated the code block, replaced a = with a : in the content line.
{
"content"="Finished building feature branch"
"commentType"="text";
}
That is not valid JSON. The best way to handle creating JSON strings in PowerShell is to use ConvertTo-Json on an associative array:
$body = #{
content = 'Finished building feature branch'
commentType = 'text'
} | ConvertTo-Json -Depth 10
Related
I'm trying to call an Azure REST API endpoint to get information my daily usage cost.
I'm using Powershell 7.2 and here's my code:
$uri = 'https://management.azure.com/subscriptions/{subscription id}/providers/Microsoft.CostManagement/query?api-version=2021-10-01'
$token = '{generated bearer token string}'
$securetoken = ConvertTo-SecureString $token -AsPlainText -Force
$body = #{
type = 'Usage'
timeframe = 'MonthToDate'
dataset = #{
granularity = 'Daily'
aggregation = #{
totalCost = #{
name = 'PreTaxCost'
function = 'Sum'
}
}
grouping = #(
#{
type = 'Dimension'
name = 'ServiceName'
}
)
}
}
$costresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication Bearer -Token $securetoken -Body $body
Write-Host $costresponse
Here's the request body example from the Microsoft documentation I'm trying to emulate:
{
"type": "Usage",
"timeframe": "TheLastMonth",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"type": "Dimension",
"name": "ResourceGroup"
}
]
}
}
When I run the code I get this error message:
Line |
27 | … tresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"error":{"code":"BadRequest","message":"Invalid query definition: Missing dataset granularity; valid
| values: 'Daily'.\r\n\r\n (Request ID: c6ead005-85b3-4ebe-9b46-........)"}}
I think the error has to do with the body syntax but I can't figure out what is the issue. I'm following this Microsoft documentation: https://learn.microsoft.com/en-us/rest/api/cost-management/query/usage
EDIT:
I tried converting the body to JSON and adding a depth parameter like this:
$costresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication Bearer -Token $securetoken -Body ($body|ConvertTo-Json -Depth 5)
And now I get a slightly different error message:
Line |
26 | … tresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"error":{"code":"BadRequest","message":"Invalid query definition, Dataset is invalid or not supplied.
| (Request ID: cf6a4b8f-88e8-4037-aa33-904......)"}}
I needed to add -ContentType 'application/json' to my Invoke-WebRequest function to get it to work. Thanks to #bluuf for the suggestion.
I am using this invoke-restmethod so I can get a token so I can do some sql work. the variables come from Azure Key Vault. I have tried to write the variables as
$($SPNAppid)
$SPNAppid
${$SPNAppid} etc
Here is the code :
$request = Invoke-RestMethod -Method POST -Uri
"https://login.microsoftonline.com/${$TenantId}"/oauth2/token" -Body
#{ resource="https://database.windows.net/";
grant_type="client_credentials"; client_id=${$SPNAppid};
client_secret=${$SPNValue} } -ContentType
"application/x-www-form-urlencoded"
Getting this error below. What is the best way to do this - whatever i do i am getting the errors below.
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name.
At C:\agent01_2\_work\_temp\b3f54d23-b7b6-4cc3-96ec-8b4b534be571.ps1:20 char:319
+ ... ervicePrincipalKey } -ContentType "application/x-www-form-urlencoded"
+ ~
The string is missing the terminator: ".
The code you posted, has an extra " and given the ambiguity of the long line I would suggest to use splatting like this :
$header = #{
"Content-type" = "application/x-www-form-urlencoded"
"Authorization" = "Bearer $token"
}
$body = #{
resource = "https://database.windows.net/"
grant_type = "client_credentials"
client_id = $SPNAppid
client_secret = $SPNValue
}
$params = #{
Method = 'Post'
Uri = "https://login.microsoftonline.com/$($TenantId)/oauth2/token"
Body = $body
ContentType = $header
}
$request = Invoke-RestMethod #params
I do not think the API call would work this way, usually clientId etc. are part of the URL, you can read more about it here - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
Hello I have 145 releases
And I have to do an equal action for everyone for example add a certain variable and edit a certain line.
Is there a way to control everyone with a script?
I checked for a template, but it creates the release from 0 and does not edit it.
Can a script in PS or Python be a solution? I did not find any information on Google about it, other than an export release template.
Azure devops release edit bulk 110
You could use the REST API Definitions - Update to update the release pipeline:
PUT https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/{DefinitionsId}?api-version=6.0
And if we want to batch modify the release pipeline, we need to get each ID of the release pipeline with REST API Definitions - List:
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0
Then we could iterate through each Rlease ID obtained.
I provide a rough code for your better reading:
$connectionToken="PAT"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ReleasePipelineUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions?api-version=6.0"
Write-Host "URL: $ReleasePipelineUrl"
$ReleasePipelines = (Invoke-RestMethod -Uri $PipelineUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ReleasePipelinesId = $ReleasePipelines.value.id
Write-Host "ReleasePipelinesId = $ReleasePipelinesId"
ForEach ($Pt in $ReleasePipelinesId)
{
$baseUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/definitions/$($Pt)?api-version=6.0"
$pipeline = (Invoke-RestMethod -Uri $baseUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
Write-Host "URL: $baseUrl"
$pipeline.variables.TestValue.value = "$buildNumber"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
Write-Host "URL: $json "
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'TestValue' is updated to" $updatedef.variables.TestValue.value
}
I'm using below code to update the Release definition in Powershell,
PowerShell_1:
Write-Host ">>>>>>>>>Start in Task 1: "$(pos)
Write-Host "##vso[task.setvariable variable=pos;]Yes"
PowerShell_2
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.pos.value = "$(pos)"
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
Write-Host "After in Task 2: "$(pos)
But issue is, i'm using the above code in two Tasks in a Release Pipeline,
The above code is passes in Task 1, but the same code throws below error on Task 2,
Release Variable:
Please Help me to get out of this.
Thanks in advance.
Something must have changed here 2021, reference to this developer community article.
I am trying to update my Azure DevOps Pipeline Variable via PowerShell task in YAML.
All authorizations are present. Here is my PowerShell task:
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.test.value = "0"
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'test' is updated to" $updatedef.variables.test.value
write-host "=========================================================="
Unfortunately I get the following error: The property 'value' cannot be found on this object. Verify that the property exists and can be set.
Any ideas?
I have found a solution for myself.
#Azure DevOps Personal Access Token
$MyPat = '*****';
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$MyPat"));
#DevOps API
$url = 'https://dev.azure.com/<Organisation>/<Project>/_apis/distributedtask/variablegroups?api-version=6.0-preview.2';
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Basic $B64Pat"
}
#complete output as JSON
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)";
#my value in JSON
$variable = $pipeline.value.variables.MyVariable.value;
Because your answer in the $pipeline variable contains the source code of the error page.
I think, you use the wrong URL:
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
You may try to use of the following for inline script:
$url = "$(System.TeamFoundationServerUri)/$(System.TeamProjectId)/_apis/Release/definitions/$(Release.DefinitionId)?api-version=5.0-preview.3"
or for PS file:
$serverUrl = $env:SYSTEM_TEAMFOUNDATIONSERVERURI
$teamProjectID = $env:SYSTEM_TEAMPROJECTID
$releaseID = $env:RELEASE_DEFINITIONID
$url = "$serverUrl/$teamProjectID/_apis/Release/definitions/$releaseID?api-version=5.0-preview.3"
I have tested it with the code you shared and the details steps as below.
Create a new release definition->add variable pos and set the value to No
Add task power shell to set variable as env variable.
Write-Host ">>>>>>>>>Start in Task 1: "$(pos)
Write-Host "##vso[task.setvariable variable=pos;]Yes"
Result:
Add task bash and enter the script printenv to print all env variable to check it.
Add task power shell and enter below script to update the release variable.
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$pipeline.variables.pos.value = $($env:POS)
Write-Host "The variable pos value is" $pipeline.variables.pos.value
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
Write-Host "After in Task 2: "$(pos)
Result:
I am calling the storage REST API to get container names using
Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers
This command often returns 'remote name could not be resolved error', even when the storage account exists and is reachable. Just running the command again gives correct result.
Invoke-WebRequest : The remote name could not be resolved: '<storageAccountName>.blob.core.windows.net'
At line:1 char:1
+ Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers #In ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
From the information you provided, you use the client credential flow to get the access token, then use the token to call the Storage Rest API - List Containers.
You could use the script below, it works for me.
Make sure the service principal you used has a RBAC role e.g. Contributor/Owner in your storage account -> Access Control, if not, click the Add to add it.
$ClientID = "xxxxxxx"
$ClientSecret = "xxxxxxx"
$tennantid = "xxxxxxx"
$storageaccountname = "joystoragev2"
$TokenEndpoint = {https://login.microsoftonline.com/{0}/oauth2/token} -f $tennantid
$Resource = "https://storage.azure.com/"
$Body = #{
'resource'= $Resource
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept'='application/json'}
Body = $Body
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
$accesstoken = $token.access_token
$url = {https://{0}.blob.core.windows.net/?comp=list} -f $storageaccountname
$header = #{
'Authorization' = 'Bearer ' + $accesstoken
'x-ms-version' = '2019-02-02'
}
$response = Invoke-WebRequest –Uri $url –Headers $header –Method GET
$response.RawContent