TFS2015 Variables Issue (Build.SourceBranch and Build.SourceBranchName) - powershell

From: https://connect.microsoft.com/VisualStudio/Feedback/Details/2264644
According to: https://msdn.microsoft.com/en-us/library/vs/alm/build/scripts/variables
Build.SourceBranch should map to $/teamproject/branch and Build.SourceBranchName should map to "branch" where the full path is $/teamproject/branch
I have a branch structure like $/MyProject/Development/MyBranch and when I try to use these variables in PowerShell (i.e. using BUILD_SOURCEBRANCH and BUILD_SOURCEBRANCHNAME), I am getting:
BUILD_SOURCEBRANCH: $/MyProject
BUILD_SOURCEBRANCHNAME: MyProject
From my understanding of the article, the variables should return $/MyProject/Development/MyBranch and MyBranch respectively.
Anyone else able to repro this behaviour with a TFVC repository? If you set up a vNext build definition with just a PowerShell task and add the following snippet, you'll be able to see the available variables in the output:
[CmdletBinding()]
param()
$environmentVars = get-childitem -path env:*
foreach($var in $environmentVars)
{
$keyname = $var.Key
$keyvalue = $var.Value
Write-Output "${keyname}: $keyvalue"
}

I have to modify the answer as I have new find. After double checking the MSDN article, I found for TFVC BUILD_SOURCEBRANCH will be the root server path for the workspace. So I tried mapping the branch path to Server Path, please refer to the screenshot below. After specifying the Server Path to the branch path, you will get correct value of BUILD_SOURCEBRANCH.

Related

Does Azure YAML pipelne support wildcards in path filter in trigger?

I have this structure of projects (folders) in git repository:
/src
/src/Sample.Backend.Common
/src/Sample.Backend.Common.Tests
/src/Sample.Backend.Common.Domain
/src/Sample.Backend.Common.Domain.Tests
/src/Sample.Backend.Pricing.Abstractions
/src/Sample.Backend.Pricing.Domain
/src/Sample.Backend.Pricing.Domain.Tests
/src/Sample.Backend.Pricing.Persistence
/src/Sample.Backend.Pricing.Persistence.Tests
/src/Sample.Backend.Accounting.Abstractions
/src/Sample.Backend.Accounting.Domain
/src/Sample.Backend.Accounting.Domain.Tests
/src/Sample.Backend.Accounting.Persistence
/src/Sample.Backend.Accounting.Persistence.Tests
/src/Sample.Backend.Api
/src/Sample.Common
/src/Sample.Frontend.Common
/src/Sample.Frontend.Web
/src/Sample.Tests.Common
(The sample is simplified, in real there are much more projects/folders.)
I want different pipelines for different parts. For example a pipeline to be triggered whenever any file is commited in master branch in any Backend project. Something like this:
trigger:
branches:
include:
- master
paths:
include:
- src/Sample.Backend.*
- src/Sample.Common
- src/Sample.Tests.Common
The problem is, that filter src/Sample.Backend.* is not working. I have to add exact name of each Backend folder to get it working. I could use exclude but I have the same problem - there are many other projects and I would have to name them all.
I found that wildcards are not supported: https://github.com/MicrosoftDocs/azure-devops-docs/issues/397#issuecomment-422958966
Is there any other way to achieve the same result?
Does Azure YAML pipelne support wildcards in path filter in trigger?
This is a known request on our main forum for product:
Support wildcards (*) in Trigger > Path Filters
This feature has not yet been implemented; you could add your comment and vote this on user voice.
As a workaround for us, we add an inline PowerShell task as the first task to execute the git command line git diff HEAD HEAD~ --name-only then get the modified file names and filter the files name in the latest submit, and use Logging Command to sets variables which are then referenced in custom conditions in the next steps in the build pipeline:
and(succeeded(), eq(variables['CustomVar'], 'True'))
Our inline PowerShell script:
cd $(System.DefaultWorkingDirectory)
$editedFiles = git diff HEAD HEAD~ --name-only
echo "$($editedFiles.Length) files modified:"
$editedFiles | ForEach-Object {
echo $_
Switch -Wildcard ($_ ) {
'XXXX/Src/Sample.Backend.*' {
Write-Host ("##vso[task.setvariable variable=CustomVar]True")
}
'XXXX/Src/Sample.Common*' {
Write-Host ("##vso[task.setvariable variable=CustomVar]True")}
'XXXX/Src/Sample.Tests.Common' {
Write-Host ("##vso[task.setvariable variable=CustomVar]True")}
}
}
Then add the condition for all remaining tasks:
In this case, if the changed files do not meet our filters, then all remaining tasks will be skipped.
UPDATE: 09/09/2021
This is possible now as it is written here
Wild cards can be used when specifying inclusion and exclusion branches for CI or PR triggers in a pipeline YAML file. However, they cannot be used when specifying path filters. For instance, you cannot include all paths that match src/app//myapp*. This has been pointed out as an inconvenience by several customers. This update fills this gap. Now, you can use wild card characters (, *, or ?) when specifying path filters.
Note: documentation seems to be not updated yet.
Old answer:
No this is not possible at the moment. You have even feature request here and I would recommend to upvote it. (I already did this) Rick in above mentioned topic shared his idea how to overcome the issue:
I currently achieve this by having 3 files:
azure-pipelines.yml ( This calls some python on each commit )
azure-pipelines.py (This checks for changed folders and has some parameters to ignore certain folders, then calls the API directly)
azure-pipelines-trigger.yml ( This is called by the python based on the changed folders )
It works well enough, but it is unfortunate for the need to go through these loops.
But it needs an extra work.
This feature will roll out over the next two to three weeks according to the latest release notes
Update on this.
It took a few weeks but the change mentioned by pavlo in the comments above finally got rolled out and path triggers are now supported in YAML.

Is it possible to change the name of a build based on the branch name in Azure Pipelines?

Most of my builds are from either feature branches or develop, and so I tend to use a known build variable to track the build number such as:
variables:
- group: BuildVars
name: $(BuildPrefix)$(Rev:r)
This works and provides me with a nicely formatted build version that I can then follow through into releases, etc:
However, when we're planning a release, we name our branches after the release, for example: release/1.1, and I'd like to have the build name reference that instead of the hardcoded (previous) version.
I know that I can reference the branch name via the Build.SourceBranch variable, but I don't see an obvious way to read and modify that outside of a build step, by which time I believe it's too late? I don't really want to have to manually change the BuildPrefix variable until the release has been deployed out to production.
Building on from this would then be the ability to append appropriate pre-release tags, etc. based on the branch name...
you can always update the build name during the execution of a build using this:
- pwsh: |
Write-Host "##vso[build.updatebuildnumber]value_goes_here"
so you could calculate the value in the same (or previous step) and update the build name with that value
Is it possible to change the name of a build based on the branch name in Azure Pipelines?
The answer is yes.
The solution we currently use is add a Run Inline Powershell task to update build number based on the Build_SourceBranchName:
$branch = $Env:Build_SourceBranchName
Write-Host "Current branch is $branch"
if ($branch -eq "Dev")
{
Write-Host "##vso[build.updatebuildnumber]$DevBuildNumber"
}
elseif ($branch -eq "Beta")
{
Write-Host "##vso[build.updatebuildnumber]$BetaBuildNumber"
}
elseif ($branch -eq "Test")
{
Write-Host "##vso[build.updatebuildnumber]$TestBuildNumber"
}
Check the Logging Command during the build for some more details.
Hope this helps.

Access SourceBranchName in Release pipeline

I'm trying to release my buildartifacts to a specific folder based on the name of the sourcebranch which upon creating a pull request triggered the build and therefor the release.
I've managed to so far to get:
write-host $env:RELEASE_TRIGGERINGARTIFACT_ALIAS
$triggerAlias = $env:RELEASE_TRIGGERINGARTIFACT_ALIAS
This alias (from my point of view) is the primary artifcat alias which I need to access
Release.Artifacts.{Primary artifact alias}.SourceBranchName
based on this documentation. So how do I combine the alias to get the sourcebranchname
$env:RELEASE_ARTIFACTS_{$triggerAlias}_SOURCEBRANCHNAME
This doesn't seem to be working and neither does
$env:RELEASE_ARTIFACTS_$($triggerAlias)_SOURCEBRANCHNAME
Any advice is much appreciated.
You can read the variable in this way:
$triggerAlias = $env:RELEASE_TRIGGERINGARTIFACT_ALIAS
$branchNameVariable = "RELEASE_ARTIFACTS_$($triggerAlias)_SOURCEBRANCHNAME"
#Get the value of the environment variable Release.Artifacts.{alias}.SourceBranchName
$branchName = (Get-item env:$branchNameVariable).Value

Powershell script in VSTS Build Definition not updating AssemblyVersion.cs

I have a Project hosted in VSTS and I'm experimenting with the Build Definitions. I'm trying to execute a powershell script that updates the AssemblyVersion.cs before the Project is built. When I run the script locally it works fine, but when it's ran during the Build process, the script runs without error, but the AssemblyVersion.cs is not updated.
$regex = '\[assembly: AssemblyVersion\("(.*)"\)\]'
$assemblyInfoPath = "..\Properties\AssemblyInfo.cs"
(Get-Content $assemblyInfoPath) | ForEach-Object {
if($_ -match $regex)
{
# Get current version, and update revision number
$version = [version]$matches[1]
$newVersion = "{0}.{1}.{2}.{3}" -f $version.Major, $version.Minor, $version.Build, ($version.Revision + 1)
'[assembly: AssemblyVersion("{0}")]' -f $newVersion
Write-Host "Version updated to: $newVersion"
}
else
{
$_
}
} | Set-Content $assemblyInfoPath
The Build output states that the version has been updated, but when I view AssemblyInfo.cs in the File Viewer it shows the old version.
The build process doesn't check in/commit changes made to source code automatically at the end of the process. You have to write a script to do that.
You need to checkin or push changes to remote repository.
If you are using TFVC, there is TFVC Build Tasks extension that includes TFVC-Check-in Changes step/task that can check in changes.
If you are using Git, you can add these steps/tasks to push changes:
Command Line (Tool: git; Arguments: add **\*.*; Working folder: $(build.sourcesdirectory))
Command Line (Tool: git; Arguments: commit -m "update"; Working folder: $(build.sourcesdirectory))
Command Line (Tool: git; Arguments: push origin HEAD:$(Build.SourceBranchName); Working folder: $(build.sourcesdirectory))
On the other hand, you also could build a custom build/release task and use it in your build/release. More information about custom build/release task, you can refer to: Add a build task
Note: It is not recommended to checkin/push changes to the remote repository in build or release.

Get Build status by Commit SHA1

Our team is using TeamCity for continuous integration and Git-TFS (TFS2015 RC) for versioning.
I want to check if a specific Commit has been built (successfully) by TeamCity and thus can be reintegrated.
It is possible to query TeamCity builds by using their REST API, e.g.:
GET http://teamcity:8000/guestAuth/app/rest/builds/18
with the result containing some xml that shows the git commit SHA:
<revisions count="1">
<revision version="96b1db05b64ecc895da070137e93cde3d2cadfa1">
<vcs-root-instance [...]/>
</revision>
</revisions>
The fact, that this information is in theory available, makes me hope that it is possible to query TeamCity builds by this particular information, like:
GET http://teamcity:8000/guestAuth/app/rest/builds/revision:96b1db05b64ecc895da[...]
but this yields a #400 BAD REQUEST response. I was not able to find out in the TeamCity 9 Documentation, whether this is possible or not. I would rather not iterate all builds to check if they contain this specific commit.
NOTE: This feature has now been implemented by JetBrains and is available in TeamCity 9.1 EAP4 now.
I don't believe this can be done without iteration, which is a little annoying
You can view changes by hash
/httpAuth/app/rest/changes?version:SHA_HASH
and you can find changes by build locator
/httpAuth/app/rest/changes?locator=build:(id:BUILD_ID)
but you can't go the other way, otherwise this could be done simply.
The buildLocator doesn't allow you to query using a revision dimension so I can't see any way around this
The following script may be of use to you if you haven't already written it yourself - save this to a file called get-build-status-by-git-commit.ps1 so it works with the sample at the end
# -----------------------------------------------
# Get Build Status By Git Commit
# -----------------------------------------------
#
# Ver Who When What
# 1.0 DevOpsGuys 01-07-15 Initial Version
# Script Input Parameters
param (
[ValidateNotNullOrEmpty()]
[string] $TeamCityServer = $(throw "-TeamCityServer is mandatory, please provide a value."),
[ValidateNotNullOrEmpty()]
[string] $ApiUsername = $(throw "-ApiUsername is mandatory, please provide a value."),
[ValidateNotNullOrEmpty()]
[string] $ApiPassword = $(throw "-ApiPassword is mandatory, please provide a value."),
[ValidateNotNullOrEmpty()]
[string] $GitSha = $(throw "-GitSha is mandatory, please provide a value.")
)
function Main()
{
$CurrentScriptVersion = "1.0"
$ApiCredentials = New-Object System.Management.Automation.PSCredential($ApiUsername, (ConvertTo-SecureString $ApiPassword -AsPlainText -Force))
Write-Host "================== Get Build Status By Git Commit - Version"$CurrentScriptVersion": START =================="
# Log input variables passed in
Log-Variables
Write-Host
# Set initial query url
$queryBuilds = "/httpAuth/app/rest/builds?fields=nextHref,build(id,status,revisions)"
while($queryBuilds)
{
$buildsToCheck = Api-Get "$TeamCityServer$queryBuilds"
$queryBuilds = $buildsToCheck.builds.nextHref;
foreach($build in $buildsToCheck.builds.build)
{
if ($build.revisions.revision.version -eq $GitSha) {
Write-Host "STATUS: "$build.status
Exit 0
}
}
}
Write-Host "================== Get Build Status By Git Commit - Version"$CurrentScriptVersion": END =================="
}
function Log-Variables
{
Write-Host "TeamCityServer: " $TeamCityServer
Write-Host "GitSha: " $GitSha
Write-Host "Computername:" (gc env:computername)
}
function Api-Get($Url)
{
Write-Host $Url
return Invoke-RestMethod -Credential $ApiCredentials -Uri $Url -Method Get -TimeoutSec 20;
}
Main
You can use this in the following way
.\get-build-status-by-git-commit.ps1 "http://teamcity:8000/" username password 96b1db05b64ecc895da070137e93cde3d2cadfa1
This is using httpAuth, but you could easily tailor the script to be using guest. I've used httpAuth in case it's of use to anyone else.
Hope this helps
I was looking for the same thing and stumbled upon this question. I don't know if you still need this but however I found the API in TeamCity v10. But you have to know your BuildTypeID for this
https://${teamcity.domain}/app/rest/buildTypes/id:${BuildTypeID}/builds/revision:${COMMIT_SHA}
You can find your build type id from TeamCity UI by going to your specific build and then
Edit configuration settings >> General Settings
And then the value in the Build configuration ID field.
Hope this helps.
The related feature request in TeamCity issue tracker: https://youtrack.jetbrains.com/issue/TW-40540. Vote for it.
The current workaround is to request builds with their revisions included into the response and then find the necessary builds on the client side.
The request can look like:
.../app/rest/builds?locator=buildType(id:XXX)&fields=build(id,href,revisions(revision))
Recent versions of teamcity allow the 'version' locator such that the following will return builds where the version SHA matches the query.
http://teamcity:8111/app/rest/changes?locator=version:SHA_HASH
I'm on TeamCity 2019.2, and I was able to directly search the builds endpoint for a specific commit:
TEAMCITY_URL/app/rest/builds/revision:SHA_HASH.
Not sure what version it was implemented in.