Connecting Build pipeline in AzureDevOps to newly created repos with certain prefix Automatically - github

I have a created a build pipeline in Azure DevOps and it is connected to one repo that I have in my Github. However, I want to connect/clone this build pipeline into any newly created repo in my github with a certain prefix in its name, like the word 'Build'.

You can navigate to your Build Pipeline, select the Option menu from the right hand side on the pipeline details page, and choose the Clone item.
You can then point the cloned build pipeline to your new Git repository and change the pipeline's name to have the prefix you wish.

Connecting Build pipeline in AzureDevOps to newly created repos with certain prefix Automatically
To automate the process, you need use the definition REST AP get the json body:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/definitions/get?view=azure-devops-rest-5.0
Then we could change the json file whatever we feel necessary, like Repository URL, change it to the new path for your newly created repo in my github.
At last, we could use create definition REST API with above Json file to create new pipeline:
https://learn.microsoft.com/en-us/rest/api/azure/devops/build/definitions/create?view=azure-devops-rest-5.0
$thisBuildDef.Name = $Clone_Name
$thisBuildDef.path = $BuildDefURL # Relative to the Project name; like "Release/2019"
$thisBuildDef.buildNumberFormat = $BuildNumberFormat
# Update source control path to new branch
$defAsJson = $thisBuildDef | ConvertTo-Json -Depth 100
$defAsJson = $defAsJson.Replace($sourceControlMainline, $sourceControlBranch)
$Uri = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions?api-version=2.0"
$newBuildDef = Invoke-RestMethod -Uri $Uri -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method Post -Body $defAsJson -ContentType "application/json" -ErrorAction Stop
Check the document Using JSON via REST to create build definitions in VSO and the vsts-clone-build-with-powershell.ps1 sample.
Hope this helps.

Related

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:

Managing a CI/CD Pipeline from another Pipeline - Azure Devops

I have a pipeline(Say A). In it, I have written a PowerShell script which helps me to update a particular package in the solution. After merging the changed code with the master branch using this PowerShell script, it automatically triggers another pipeline(say B) whose triggering depends on the changes in master. I have to control the triggering of this pipeline B from Pipeline A - like get the status of the triggered pipeline B, disable the trigger of pipeline B from A, etc. Please help me with this scenario.
You can use a powershell task to call build rest api to get the status of another pipeline(ie. Pipeline B).
First to get the latest build of Pipeline B, you can use below rest api.
GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?definitions={definitions}&$top={$top}&api-version=5.1
Below is the inline script example in the powershell task to get the build status.
$uri = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds?definitions={definitionId}&`$top=1&api-version=5.1"
 
$result =Invoke-WebRequest -Uri $uri -Method Get -ContentType "application/json" -Headers $headers = #{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
$status = $result.value[0].status
$env:SYSTEM_ACCESSTOKEN is the predefined variable with which you can refer to the access token directly in the scripts.
To cancel pipeline B in pipeline A you can call update Build rest api. See below example. First get the build from above api, then update the status to cancelling
$build = $result.value[0]
$uriupdate = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$($build.id)?api-version=5.1"
$build.status = "cancelling"
$body = $build | ConvertTo-Json -Depth 10
$update = Invoke-RestMethod -Uri $uriupdate -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -ContentType "application/json" -Method patch -Body $body
To skip a build when pushing the changes, you can just include [skip ci] in the commit message as Shamrai mentioned.
git commit -m message [skip ci]
I have to control the triggering of this pipeline B from Pipeline A -
like get the status of the triggered pipeline B, disable the trigger
of pipeline B from A, etc.
You can use REST API with PowerShell to control your builds: Builds - List.
To disable the trigger, add scip ci into your commit message: Skipping CI for individual commits
You can use output variable in powershell task. And based on that you can control the next job to execute. This way you don't have to use multiple build pipelines instead multiple jobs in a single pipeline.
You can refer the Microsoft document here

Setting Git Tag from Azure Devops Build Pipeline on Complete

I'm trying to set a tag with the current version number determined by GitVersion on the GIT commit at the end of a successful build. Feels like I can't be the first one to be doing this, but I'm struggling to find something that works.
Azure Devops Pipeline has a feature in Get Sources to "Tag sources" On Success. I've set this and set to a variable that is set by one of the Agent Tasks I have (GitVersion)
I can see in the debug logs that this variable is getting set by the GitVersion component that I've added to the pipeline.
2019-12-06T20:54:20.2390794Z ##[debug]Processed: ##vso[task.setvariable variable=GitVersion.MajorMinorPatch;]2.98.0
However if I leave it just as this, I get a tag created as "v$(GitVersion.MajorMinorPatch)" which means that at the time that the tag is being created that that variable no longer exists.
The Tag Format help tooltip says
"Tag format could be a combination of user-defined or pre-defined variables that have a scope of "All". For example: '$(Build.DefinitionName)$(Build.DefinitionVersion)$(Build.BuildId)$(Build.BuildNumber)$(My.Variable)'"
So I guess the problem is that this variable created during the pipeline does not have a scope of All.
I then tried adding a pipeline variable to the pipeline of "GitVersion.MajorMinorPatch" with the hope that this was at the right scope and hoping that when the "task.setvariable" command is run, that this will set the variable value of this higher scoped variable.
However in this case I just got a tag "v" created.
So I am a bit stuck. Somehow I need to be able to dynamically create or set a variable at scope ALL with the value I want to tag here.
I'd be really grateful for any ideas on this.
If you are doing a yaml pipeline, you can add the following steps
- checkout: self
persistCredentials: true
## Rest of pipeline ##
- script: |
git tag $(GitVersion.NugetVersionV2)
git push origin $(GitVersion.NugetVersionV2)
workingDirectory: $(Build.SourcesDirectory)
The persistCredentials allows the token to be automatically passed to other git commands. Note the assignment of workingDirectory, otherwise I had an error that the location was not a git repository.
For an annotated tag rather than lightweight tag, the syntax would look like this...
- script: |
git tag -a <tagname> -m <message>
git push origin <tagname>
To get a user/date against it you need to set the user name/email as well e.g.
- script: |
git config --global user.name "BuildService"
git config --global user.email "autobuild#fabrikam.com"
git tag -a <tagname> -m <message>
git push origin <tagname>
For this to work, the Project Collection Build Server account (not the Project Build Service Accounts group) needs to be allocated the Contribute permission for the Repositories
Expanding on the excellent answer from Paul Hatcher, I'd like to add that for me the account was called Project Collection Build Service in Azure DevOps Server 2019. This also seems to be in line with the current Microsoft documentation.
Sorry for the answer, my reputation does not yet suffice to comment.
I can see in the debug logs that this variable is getting set by the
GitVersion component that I've added to the pipeline.
The variable GitVersion.MajorMinorPatch you saw from the log is a step-level variable, which means its life cycle is only start from the current GitVersion task.
As the definition you are referring, it scope must to all. This means is must be a global variable. For example, the predefined variables that the system default have, and the customized variables which specified in the Variables tab.
Based on the GitVersion task compile and work logic, in fact, the GitVersion.MajorMinorPatch value is generated and stored as current build's build number:
So, the most convenient method for you to tag the GitVersion.MajorMinorPatch value to repos is using $(Build.BuildNumber):
v$(Build.BuildNumber)
And this is my result:
Update:
To add the GitVersion.MajorMinorPatch which generated by the GitVersion task into Variables, please apply below scripts into PowerShell task:
$connectionToken="{PAT Token}"
$urlget = "https://dev.azure.com/{org}/{project}/_apis/build/definitions/$(System.DefinitionId)?api-version=5.1"
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$getdef = Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET -ContentType application/json -Uri $urlget
Write-Host Pipeline = $($getdef | ConvertTo-Json -Depth 100)
$bvalue=#"
{
"value": "$(GitVersion.MajorMinorPatch)"
}
"#
$getdef.variables | add-member -Name "GitVersion.MajorMinorPatch" -value (Convertfrom-Json $bvalue) -MemberType NoteProperty -Force -PassThru
$getdef = $getdef | ConvertTo-Json -Depth 100
$getdef | clip
$urlput = "https://dev.azure.com/{org}/{project}/_apis/build/definitions/$(System.DefinitionId)?api-version=5.1"
$putdef = Invoke-RestMethod -Uri $urlput -Method PUT -Body $getdef -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
As I mentioned previously, I still don't think it is available to specify $(GitVersion.MajorMinorPatch) in Tag format.
Still strongly suggest you by calling $(Build.BuildNumber) to tag the $(GitVersion.MajorMinorPatch) value
- pwsh: |
# Construct PAT authentication header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "user",$env:SYSTEM_ACCESSTOKEN)))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$url="$(System.CollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/annotatedtags?api-version=5.0-preview.1"
$body = #{name = "$(GitVersion.MajorMinorPatch)"
message = "automatically added"
taggedObject = #{
objectId = "$(Build.SourceVersion)"
}
} | ConvertTo-Json
Invoke-RestMethod -Uri $url -Headers $headers -Method Post -ContentType "application/json" -Body ($body)
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: 'Add tag'

Azure DevOps integration in Sentry: Associate commits

Did someone manage to integrate Azure DevOps in Sentry (sentry.io)? I stuck on "Associate commits with a Release" (see: https://docs.sentry.io/workflow/releases/?platform=browser#associate-commits-with-a-release)
I can not figure out a way how I can tell Sentry (by API) which commit ids are associated with a current release/deploy. How can I add a task to the pipeline which will post the commit ids to Sentry API? Or is there some other way to do it?
In azure devops, the Powershell task also support curl. So, you can execute the api in powershell task of VSTS pipeline directly.
In release pipeline, there has a pre-defined release variable, it stores the commit id which is associated with the current release pipeline: $(Release.Artifacts.{alias}.SourceVersion). Here alias is the artifacts name, and you can get it by getting $(Release.PrimaryArtifactSourceAlias).
First, create variables like this:
Then you can apply the variable $(id) into that API, and execute the api in powershell task:
"refs": [{
"commit":"$(id)"
}]
Now, the commit id could be packed into the body of this api, and send to the Sentry server.
If there has multiple commits associate with this release, since the variable $(Release.Artifacts.{alias}.SourceVersion) I mentioned above only store the latest commit message, here you may need add additional scripts to get what you want by Build id.
In release pipeline, with $(Build.BuildId) you can get the corresponding buildid which associate with this release. And then, you could get the commits(changes) by using this API:
GET https://dev.azure.com/{organization}/{project}/_apis/build/changes?fromBuildId={fromBuildId}&toBuildId={toBuildId}&api-version=5.1-preview.2
You could apply these powershell script into your task without change anything because this script is universal among powershell-ise, powershell command line and powershell task in VSTS.
$token = "{PAT token}"
$url="https://dev.azure.com/{org name}/{project name}/_apis/build/changes?fromBuildId={id1}&toBuildId={id2}"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get
Write-Host "results = $($response.value.id | ConvertTo-Json -Depth 100)"
Now, you could get the list of commits which associate with the build and corresponding release.

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.)