Download DacPac with Power Shell Script - azure-devops

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.

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:

From where I get all publish artifact of all stages of azure build pipeline instead of searching from all stages

I am publishing build artifact of each run over azure pipeline, whatever artifact I have published than can be accessible to that specific stage(run), But my query is in Azure is there any build artifacts repository where we can get all the build artifacts for all the builds of that pipeline ?
To get all the build artifacts for all pipeline runs, you need to combine the following two Rest APIs: Builds - List and Artifacts - List
Here is a PowerShell example:
$token = "PAT"
$url="https://dev.azure.com/{organization}/{project}/_apis/build/builds?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach( $buildid in $response.value.id )
{
echo $buildid
$url1= "https://dev.azure.com/{organization}/{project}/_apis/build/builds/$($buildid)/artifacts?api-version=4.1"
$response1 = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
echo $response1 | ConvertTo-Json
}
This sample will traverse all pipeline runs and get relevant artifacts information.
Update:
When you use Classic Pipeline, you could add a PowerShell task and input the PowerShell Script. Please change the parameters in the script to make it suitable for your organization

Contrasting outcomes when downloading Maven artifact from Azure Artifacts using REST API in 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.

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:

Azure Devops - How to call one pipeline from another

Could someone help me with how to call one pipeline from another pipeline in Azure DevOps?
I have to run a pipeline and this should trigger another pipeline in different project.
You can try to use Trigger Azure DevOps Pipeline task to trigger another pipeline in different projects.
Depending on your choice in the task it will trigger a build or a release pipeline.
To be able to use the extension an Azure DevOps API endpoint needs to be created.
For the service connection to work as it should you need to configure the following parameters:
Organization Url: The URL of the organization.
(https://dev.azure.com/[organization])
Release API Url: The URL of the Azure DevOps Release API
(https://vsrm.dev.azure.com/[organization])
Personal Access Token: The personal access token.
How you can create a personal access token can be found here: Use personal access tokens to authenticate.
Make sure the personal access token has the following rights:
Triggering a Release: Release – Read, write & execute – Build Read &
Execute
Triggering a Build: Read & Execute
I think resources for Azure Pipelines is what you looking for.
Add a resource in the pipeline that shall be called from another one and name the source pipeline:
# Explicitly set none for repository trigger
trigger:
- none
resources:
pipelines:
- pipeline: myappbuild # Name of the pipeline resource
source: myapp-build-pipeline # Name of the triggering pipeline
trigger:
branches:
- master
You can use API for triggering build. Here is the example that I use to trigger another build pipeline.
- powershell: |
# Write your PowerShell commands here.
Write-Host " ***** Start Script ***** "
$body = '
{
"parameters": "{\"parameter1\": \"value1\"}",
"definition": {"id": "1234"},
"sourceBranch": "git/branch",
"templateParameters": {"templateparameter": "paramvalue"}
}
'
$bodyJson=$body | ConvertFrom-Json
Write-Output $bodyJson
$bodyString=$bodyJson | ConvertTo-Json -Depth 100
Write-Output $bodyString
$user="$(user)"
$token="$(token)"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$Uri = "https://tfs.com:8443/Organization/_apis/build/builds?api-version=6.1-preview.6"
$buildresponse = Invoke-RestMethod -Method Post -UseDefaultCredentials -ContentType application/json -Uri $Uri -Body $bodyString -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
write-host $buildresponse
$buildID = $buildresponse.id
write-host $buildID
Write-Output "Build ID is $buildID... Sleep for 5 seconds.."
Start-Sleep -Seconds 5
$buildInfo = ( Invoke-RestMethod -Method Get -UseDefaultCredentials -Uri "https://tfs.com:8443/Organization/_apis/build/builds/${buildID}?api-version=6.1-preview.6" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} )
while($buildInfo.status -eq "inProgress" -or $buildInfo.status -eq "notStarted") # keep checking till build completed
{
Write-Output "Build is $($buildInfo.status)... Sleep for 5 seconds.."
Start-Sleep -Seconds 5 # Start sleep for 5 seconds
$buildInfo = ( Invoke-RestMethod -Method Get -UseDefaultCredentials -Uri "https://tfs.com:8443/Organization/_apis/build/builds/${buildID}?api-version=6.1-preview.6" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} )
}
Write-Output "Build Status : $($buildInfo.status)" # print build status
Write-Output "Build Result : $($buildInfo.result)" # print build result
displayName: 'Trigger Another Build Pipeline'
You can install az devops extension in your pipeline agent and then you can call az pipeline CLI commands" to manage other build or release pipelines. Next, you can call az pipeline CLI commands from your main pipeline and for this you can use AzureCLI task or Bash task.
Here is an implementation I use with the following:
PowerShell CmdLet "Invoke-RestMethod" https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-5.1
Azure DevOps REST API https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-5.0
The $(System.AccessToken) variable from DevOps. This has the
advantage that a PAT is not necessary. More Infomation at https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken
Unfortunately the target pipeline is not in another project
I created a stage
######### stage_call_other_pipelines ###################
#########################################################
- stage: stage_call_other_pipelines
displayName: "call other pipelines"
jobs:
#XYZ deployment
- job: job_call_XYZ_deployment
displayName: "execute XYZ deployment"
steps:
- checkout: none
- task: PowerShell#2
displayName: "via REST API"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
targetType: 'inline'
script: |
#url
$url = 'https://dev.azure.com/XYZOrganization/XYZProject/_apis/build/builds?api-version=5.0'
#header
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/json")
$headers.Add("Authorization","Bearer $env:SYSTEM_ACCESSTOKEN");
#body
$body = " {
`n `"definition`": {
`n `"id`": 134
`n },
`n `"templateParameters`": {
`n `"ParameterA`": `"ParameterValueA`",
`n `"ParameterB`": `"ParameterValueB`"
`n }
`n }"
#call rest api
$response = Invoke-RestMethod $url -Method 'POST' -Headers $headers -Body $body
#output
$response | ConvertTo-Json
failOnStderr: true
pwsh: true
The token is passed to the agent as an environment variable. The pipeline and its parameters are defined in the body.
Additional
On the pipeline that is to be executed, permissions must be adjusted.
Go to the desired pipeline, click in the right upper corner on the
menu button and select "Manage security"
A form will apear. Choose the Build Service service principal and set "Queue builds" on "Allow"
Since the OP didn't specify how they wanted to accomplish this, I'll share how I'm doing this without YAML pipelines. I use the Edit pipeline option then the meatball menu to select triggers and I can specify which triggering build with branch filters.