Contrasting outcomes when downloading Maven artifact from Azure Artifacts using REST API in Powershell - powershell

I am running the below script in a Powershell ISE console to download a Maven package from our Azure Artifacts repository and and it works perfectly, downloading the war file to my local directory successfully.
Run in Powershell ISE
$url = 'https://pkgs.dev.azure.com/{organisation}/{project}/_apis/packaging/feeds/{feedID}/maven/{groupID/{artifactID}/{version}/{filename}/content?api-version=6.1-preview.1'
$connectionToken="my-personal-access-token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$buildPipeline= Invoke-RestMethod -Uri $url -OutFile .\xxx-portal-18.29.06.war -Headers #{Authorization = "Basic $base64AuthInfo"} -Method Get
However, when I run the same script (albeit with a different output directory) from an Azure Pipelines Powershell Task as depicted below, it fails miserably. The error written to the Pipeline log appears to suggest the failure is down to an authentication issue. What could I be doing wrong and am I using the correct authentication method?
Run as an Azure Pipelines Powershell Task
$url = 'https://pkgs.dev.azure.com/{organisation}/{project}/_apis/packaging/feeds/{feedID}/maven/{groupID/{artifactID}/{version}/{filename}/content?api-version=6.1-preview.1'
$connectionToken="my-personal-access-token"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$buildPipeline= Invoke-RestMethod -Uri $url -Outfile $(Build.BinariesDirectory)\xxx-broker-portal-18.29.06.war -Headers #{Authorization = "Basic $base64AuthInfo"} -Method Get

We create a new Project-scoped maven feed and follow this blog: Maven Package Management with Visual Studio Team Services to publish a maven package. And then using this API: Maven - Download Package to download below war file with your provided PowerShell script.
And we run the same script (albeit with a different output directory) from an Azure Pipelines PowerShell Task, all work as expected.
Please check if you have proper permissions to write xxx-broker-portal-18.29.06.war file to target directory: $(Build.BinariesDirectory). If you own the administrator role for this private agent and can manage directories(Read, write, & manage) where this agent located in, this error should not occur.

Related

Download latest artifact from Azure Devops using Powershell - get buildId

I try to download the latest Artifact from AzureDevops with PowerShell.
Here is my script to get the latest buildid:
$organisation="aaa"
$project="bbb"
$personalAccessToken="ccc"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$url = "https://dev.azure.com/$organisation/$project/_apis/build/latest/1?branchName=main"
$result = Invoke-RestMethod -Uri $url -Method Get -ContentType application/json -Headers $headers
When I execute this, I get the exception
Build pipeline 1 was not found.
Can someone help me, where I can get the correct definitionId?
Download latest artifact from Azure Devops using Powershell - get buildId
To get the latest artifact from the build, we need to provide the parameter definitions and the $top for the REST API Builds - List:
GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?definitions={definitions}&$top={$top}&branchName={branchName}&api-version=6.0
Note: The branch name parameter should include the refs/heads
As test with postman:
And if you want to know the correct definitionId, you could open the pipeline in the web pageļ¼Œ it in the URL:

Download DacPac with Power Shell Script

I've currently got a pipeline that builds and deploys DacPacs to our on-premise databases. However, we have some self-hosted clients who right now get a migration script on each release. We'd like to transition them to also being able to use DacPacs for deployments. I was wondering if it's possible to have a Powershell script that pulls the DacPac file from the artifacts directory on Azure DevOps?
it's possible to have a Powershell script that pulls the DacPac file from the artifacts directory on Azure DevOps?
In Azure Pipeline, you need to publish the file to Build artifacts via Publish Build Artifacts task.
- task: PublishBuildArtifacts#1
displayName: 'Publish Artifact: drop1'
inputs:
PathtoPublish: 'dacpac file path'
ArtifactName: drop
Then you could use the following Powershell script to download the target file:
$token = "PAT"
$url1= "https://dev.azure.com/{OrganizationName}/{ProjectName}/_apis/build/builds/{BuildId}/artifacts?artifactName={ArtifactsName}&api-version=5.1"
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$containerid = $response1.resource.data
echo $containerid
$result= ("$containerid" -split "/")[1]
echo $result
$url="https://dev.azure.com/{OrganizationName}/_apis/resources/Containers/$($result)/{ArtifactsName}?itemPath={path to the item including the root}" #e.g.item file path drop%2FForumContext1.dacpac use %2F replace /
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/octet-stream -OutFile "C:\Response.dacpac"
On the other hand, Azure Devops also supports directly deploying the Dacpac file to on-premise database.
In Release Pipeline, you could use the SQL Server database deploy task in Deployment Group Job.

Azure cli: clone pipeline

Looking at az pipelines documentation it seems it's not possible to clone a pipeline using cli.
I've looked at getting the yaml (az pipelines show -name=x > x_orig.yaml) and then trying to change json and create pipeline from modified yaml, but that feels like a lot of work that could break after next update.
Is there a way to clone a pipline without going the the Web UI?
Currently, there indeed is not available Azure CLI that can clone or export/import a pipeline to create a new pipeline.
I also searched and tried the Azure DevOps REST API for Pipelines, but did not find the available API.
Ideally, the Azure CLI "az pipelines create" can provide an input parameter that allows users specify an existing pipeline as a starting point for the new pipeline.
If your projects really need this feature, I recommend that you can directly report a feature request on the "Azure/azure-cli" repository to ask adding the parameter like as above mentioned. That will allow you directly interact with the appropriate engineering team, and make it more convenient for the engineering team to collect and categorize your suggestions.
As a workaround, we could clone the build definition via power shell script to call REST API.
Note: We need to change the original build definition name.
REST API
Get build definition:
GET https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0
Create build definition
POST https://dev.azure.com/{organization}/{project}/_apis/build/definitions?api-version=6.0
Power shell script
$connectionToken="{pat}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$BuildDefinitionInfoURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions/386"
$BuildDefinitionInfo = Invoke-RestMethod -Uri $BuildDefinitionInfoURL -Headers #{authorization = "Basic $base64AuthInfo"} -Method Get
Write-Host $BuildDefinitionInfo.name
$BuildDefinitionInfo.name = $BuildDefinitionInfo.name +" clone"
Write-Host $BuildDefinitionInfo.name
$body = $BuildDefinitionInfo | ConvertTo-Json -Depth 99
$createBuildDefinitionURL = "https://dev.azure.com/{org name}/{project name}/_apis/build/definitions?api-version=6.0"
$response = Invoke-RestMethod -Uri $createBuildDefinitionURL -ContentType "application/json" -Body $body -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST
Write-Host $response.id
Result:

"Download pipeline artifact" task output

"Download build artifacts" task has the output variable BuildNumber that makes it possible to get the id of the build the artifact was downloaded from. The new "Download pipeline artifact" task (which is preferred over the "Download build artifacts") does not have any the output variables. Is there a way to get the id of the build the artifact was downloaded from?
Also posted an issue on GitHub.
Microsoft is about to release a fix.
There is workaround to get the build id of the downloaded artifact using restful api.
To get the BuildId of the Specific version. You can refer to below below example.
First add a powershell task in your pipeline to run below scripts.
To get the definition id provided definition name(definition id will be used in the following scripts), check here for rest API.
$urldefinition ="https://dev.azure.com/<org>/<proj>/_apis/build/definitions?name=AboutSite-ASP.NET-CI&api-version=5.1"
$result = Invoke-RestMethod -Uri $urldefinition -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -Method Get
$definition= $result.value
$definitionId = $definition[0].id
Then you can get the build id with below scripts:
$url="https://dev.azure.com/<org>/<proj>/_apis/build/builds?definitions=$definitionId&buildNumber=20191109AboutSite-ASP.NET-CI&statusFilter=completed&resultFilter=succeeded&api-version=5.1"
$result = Invoke-RestMethod -Uri $urldefinition -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -Method Get
$build = $result.value
$id = $build[0].id
And then you can output the buildid for the following task to use with below script:
echo "##vso[task.setvariable variable=ArtifactBuildId;isOutput=true]$id"
To get the latest build id you can simply use below api
GET https://dev.azure.com/{organization}/{project}/_apis/build/latest/{definition}?branchName={branchName}&api-version=5.1-preview.1

TFS Build tagging

I am using TFS for source and build of my project. After successful build I want to automate the tagging of build using powershell or any TFS task. And after that I wanted to use the same tag to deploy in specific environment. Can you guide me how can use this?
Assuming you are using VNext build, you can use the REST API to add tags during the build, then set a CD release to deploy the tagged artifacts.
PowerShell sample:
$buildid= $env:BUILD_BUILDID
$TagName= $env:BUILD_DEFINITIONNAME + $env:BUILD_BUILDID
$Uri = "http://mo-12r2:8080/tfs/CollectionLC/0418Scrum/_apis/build/builds/$buildid/tags/$($TagName)?&api-version=2.0"
$buildresponse = Invoke-RestMethod -Method Put -UseDefaultCredentials -ContentType application/json -Uri $Uri
Write-Host "BuildID:" $buildid
Write-Host "TagName:" $TagName
You can follow below steps to do that:
Create a PowerShell script and check in to server, See above sample
Create a build definition and add a PowerShell task as the end task
Select the PowerShell script to run
Create a Release definition with Continuous Deployment enabled
and link the build definition created in step2 as the artifacts. (You can also select any tagged build to deploy if you set manual release.)