Does Azure YAML pipelne support wildcards in path filter in trigger? - azure-devops

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.

Related

How to get source branch from google cloud build trigger on push when merging

I am merging 'feature-branch' onto 'dev-branch' from a github pull request. I am using a google cloud build trigger that is triggered on push to 'dev-branch'. From what I can tell in the documentation of substitution variables, there are no substitution variables to get the name of the branch that I am merging from - 'feature-branch' and only the branch that I merging to - 'dev-branch'. Is there a way or a workaround to get information (name, sha, id, etc.) of the branch that is being merged from on a google cloud build trigger from a push to branch event?
Presumably you can have some naming conventions on the first line of the commit message (happens at merge pull request "event"), so that this line includes the source (or head) branch name (the source of the merge - in your words - 'feature-branch').
Then, you can create a substitution variable:
substitutions:
_COMMIT_MESSAGE: $(commit.commit.message)
here is a documentation link: Creating substitutions using payload bindings
And use that variable in some build step to get the the head branch name:
mapfile -t commit_lines <<< "${_COMMIT_MESSAGE}"
source_branch="$(echo ${commit_lines[0]} | <<add your command here following naming convention for the commit message>> )"
echo "=> My source branch name: ${source_branch}"
After that you can use the source branch name.

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.

Why is my nuget package push filtered out in VSTS (Azure Devops)

I have an azure DevOps pipeline who compile correctly and the log files indicate a successful "pack" into "D:\a\1\a\Packages\Rvi.LA.ObjetsMetiers.1.1.0.nupkg".
Concerning the nuget push step, I can see the following in the debug log :
2019-02-14T14:19:43.5995520Z ##[debug]pattern: 'D:\a\1\a\Packages\RVI.LA.ObjetsMetiers*.nupkg'
2019-02-14T14:19:44.9183973Z ##[debug]expanding braces
2019-02-14T14:19:44.9184020Z ##[debug]pattern: 'D:/a/1/a/Packages/RVI.LA.ObjetsMetiers*.nupkg'
2019-02-14T14:19:44.9209179Z ##[debug]findPath: 'D:\a\1\a\Packages'
2019-02-14T14:19:44.9209259Z ##[debug]statOnly: 'false'
2019-02-14T14:19:44.9212246Z ##[debug]findPath: 'D:\a\1\a\Packages'
2019-02-14T14:19:44.9212452Z ##[debug]findOptions.allowBrokenSymbolicLinks: 'undefined'
2019-02-14T14:19:44.9212597Z ##[debug]findOptions.followSpecifiedSymbolicLink: 'undefined'
2019-02-14T14:19:44.9212885Z ##[debug]findOptions.followSymbolicLinks: 'undefined'
2019-02-14T14:19:44.9223644Z ##[debug] D:\a\1\a\Packages (directory)
2019-02-14T14:19:44.9225732Z ##[debug] D:\a\1\a\Packages\Rvi.LA.ObjetsMetiers.1.1.0.nupkg (file)
2019-02-14T14:19:44.9225814Z ##[debug]2 results
2019-02-14T14:19:44.9225888Z ##[debug]found 2 paths
So, it finds two results but strangely indicates "found 2 paths" when one of them is a file. Anyway, it successfully finds the one who needs to be pushed and detect it is a file.
The problem is in the following part of the log :
2019-02-14T14:19:44.9225984Z ##[debug]applying include pattern
2019-02-14T14:19:44.9235322Z ##[debug]0 matches
2019-02-14T14:19:44.9235403Z ##[debug]0 final results
2019-02-14T14:19:44.9247396Z ##[warning]No packages matched the search pattern.
2019-02-14T14:19:44.9247569Z ##[debug]Processed: ##vso[task.issue type=warning;]No packages matched the search pattern.
It seems to exclude it with the include pattern who is "$(Build.ArtifactStagingDirectory)\Packages\$(NomNuspec)*.nupkg" and is translated to "D:\a\1\a\Packages\RVI.LA.ObjetsMetiers*.nupkg" in the log above.
I don't understand why it is not found. Is there something who should hit me in the eye even though two persons looked at it many times?
Got it.
The package was packed as "Rvi.LA.ObjetsMetiers.1.1.0.nupkg", but the filter was "RVI" in uppercase. I did see it, but thought "case sensitivity does not matter with a file name!", but it does. The last update told me this is a real possibility.
I modified my nuget file to pack with "RVI.LA.ObjetsMetiers", not "Rvi.LA.ObjetsMetiers" and the original path "$(Build.ArtifactStagingDirectory)\Packages\$(NomNuspec)*.nupkg" works as $(NomNuspec) is resolved with "RVI.LA.ObjetsMetiers" as stated above.
I will suggest to nuget to remove the "case-sensitiveness" as there is no way to have two files named "fileA.txt" and "FileA.txt" anyway.

Fail a merge or build if a particular file has changed?

On VSTS, we have some files we want to protect on certain branches. How can one fail a merge/build if a particular file has changed?
First prize is to configure this on the build server, which in this case is VisualStudio.com (VSTS / GIT).
Scenario: we have various release branches v1, v2, v3. We want to protect the packages.json file to prevent anyone updating Nuget packages on these branches. So if the package.json file has changed on a pull request into "v3", don't allow the merge.
For Git, you can protect a certain branch (not a certain file), then all the files exist in the branch will be protected.
You can use Branch security which users/groups can contribute for the branch.
Or you can use Branch Policies to protect not commit changes on the branch directly but use pull request to make changes etc.
Or you can lock a branch to prevent updating.
To expanded Starain's answer:
First create a build definition for the branch you want to protected (such as select V3 branch in get sources step). And add a powershell task with the content below:
$head=$(git rev-parse HEAD)
$parents=$(git rev-list --parents -n 1 $head)
$p1,$p2,$p3=$parents.split(' ')
If ($p1 = $head)
{
$parent1=$p2
$parent2=$p3
}
ElseIf ($p2 = $head)
{
$parent1=$p1
$parent2=$p3
}
Else
{
$parent1=$p1
$parent2=$p2
}
$outp1=$(git diff $head $parent1 --name-only)
$outp2=$(git diff $head $parent2 --name-only)
If ($outp1 -contains 'package.json')
{
echo "changed the specified file on the branch which contains commit $parent1"
exit 1
}
If ($outp2 -contains 'package.json')
{
echo "changed the specified file on the branch which contains commit $parent2"
exit 1
}
So that when the file package.json has been change, powershell script will fail the build result.
Then add the branch policy for the branch which you want to protect.
Add build policy -> select the build definition you just created -> Policy requirement as Required -> Build expiration 0.1 hours (6 min) or other values since it’s every fast to queue a build with a powershell task -> save.
You can try to do it in the build, simple workflow:
Configure branch policy for a succeed build required
Check whether the specific file changed in that build
Fail build if specific file has been changed
You can put a required reviewer for a particular folder/file in VSTS for a particular branch.
In this way the person won't be able to check-in without getting an approval from the required reviewer.
Git doesn't really work that way; individual files don't have any sort of security on them.
You could use a pre-commit hook, but it's important to note that those hooks are client-side, not server-side -- each user would have to set up a pre-commit hook.
VSTS/TFS doesn't support Git server hooks (at least, not to the extent that it can block a push), otherwise a pre-receive or update hook would be exactly what you want.

Configuring VCS of Teamcity for code checkout

I am trying to specify rather complicated labeling rule in VCS of Teamcity. Not sure if what I am trying to do is possible or not.
This is my directory structure I have inherited.
mysvn/abc/repos
|
-TestDomain
-TestSystem
|
-MyFrameWork
-MySoftware
|
-MySoftwareDevices
-MySoftwareFiles
|
-branches
-tags
-trunk1
-MySoftwareDriver
|
- branches
- tags
- trunk2
I want to specify such a rule that in the working directory of the checkout directory of Teamcity has structure like this:
Teamcity checkout directory
|
-FolderA
-FolderB
Where FolderA has contents of trunk1 and FolderB has contents of trunk2.
Is it possible to be done?
SVN URL like:
mysvn/abc/repos/TestSystem/MySoftware/MySoftwareFiles/trunk1
does give me trunk1. But I need contents of trunk1 and trunk2 under two different folders in the same build checkout directory.
Labeling I have been using: trunk=>tags
Ok got the thing working. Its kind of hit and trial. Hoping someone comes up with proper explanations.
Labeling rules still has:
trunk=>tags
The SVN URL : mysvn/abc/repos/TestSystem
It is the checkout rules which I added:
-:.
+:MySoftware/MySoftwareFiles/trunk1=>MyDir/FolderA
+:MySoftware/MySoftwareDriver/trunk2=>MyDir/FolderB