Git 基于对子文件夹的更改触发Azure DevOps构建
我有一个包含多个项目的VisualStudio解决方案,每个项目都是一个单独的微服务。对于开发团队来说,将所有服务放在同一个解决方案和git repo中非常方便,因为服务可以相互调用Git 基于对子文件夹的更改触发Azure DevOps构建,git,azure-devops,azure-pipelines,Git,Azure Devops,Azure Pipelines,我有一个包含多个项目的VisualStudio解决方案,每个项目都是一个单独的微服务。对于开发团队来说,将所有服务放在同一个解决方案和git repo中非常方便,因为服务可以相互调用 Master.sln - SubFolderA - MicroserviceA.sln - SubFolderB - MicroserviceB.sln - SubFolderC - MicroserviceC.sln 然而,我想在Azure DevOps中独立构建/发
Master.sln - SubFolderA - MicroserviceA.sln
- SubFolderB - MicroserviceB.sln
- SubFolderC - MicroserviceC.sln
然而,我想在Azure DevOps中独立构建/发布单个微服务,当它们发生更改时,因此如果ServiceA是唯一要更改的服务,那么ServiceA是唯一构建和部署的服务
为此,我创建了一个新的构建管道定义,其中设置了“路径过滤器”,以在微服务文件夹的内容发生更改时触发构建(因此每个微服务添加一个要监视的路径过滤器)
我这里的问题是,当触发生成时(例如,基于对子文件夹a的更改),我无法告诉生成定义仅在子文件夹a中生成.sln文件
我可以为每个微服务创建一个单独的构建定义,并在单独的子文件夹上触发每个构建,但这会带来很大的开销,即我需要维护15个单独的构建定义(对于我构建的每个分支也是如此),我们的自主机构建代理现在需要的存储是NumberOfService x NumberOfBranchesBeingBuild x SizeOfRepo
有没有一种方法可以使用带有git“路径过滤器”的单个生成定义和定义的多个路径,从而启动多个生成实例,并将触发生成的路径的值输入到生成定义中,从而告诉生成实例要生成哪个.sln文件
我希望这是有道理的 你可以像下面这样做
microserviceupdated
=“False”、microservicebuupdated
=“False”等
- 将
变量更新为“true”(如果有) 文件在microserviceupdated
子文件夹A下更改
- 将
变量更新为“true”(如果只有MicroserviceBUpdated
文件在子文件夹A下更改
和(succeed(),eq(变量['microserviceupdated'],'True'))
用于MicroserviceB构建任务
“自定义条件”:
和(succeed(),eq(变量['MicroserviceBUpdated'],'True'))
等等
这样,如果变量的值为False
对于第2步
$files=$(git diff HEAD HEAD~ --name-only)
$temp=$files -split ' '
$count=$temp.Length
echo "Total changed $count files"
For ($i=0; $i -lt $temp.Length; $i++)
{
$name=$temp[$i]
echo "this is $name file"
if ($name -like "SubFolderA/*")
{
Write-Host "##vso[task.setvariable variable=MicroserviceAUpdated]True"
}
}
Jayendran的回答非常好!下面是执行步骤2的一种更强大的方法:
$editedFiles = git diff HEAD HEAD~ --name-only
$editedFiles | ForEach-Object {
Switch -Wildcard ($_ ) {
'SubFolderA/*' { Write-Output "##vso[task.setvariable variable=MicroserviceA]True" }
# The rest of your path filters
}
}
在“触发器”选项卡上,有一个选项可以指定要生成的项目的路径。指定该路径后,只有包含与包含/排除规则匹配的修改的提交才会触发生成 在我的例子中,这是一个比PowerShell脚本更好的解决方案,PowerShell脚本仍然会触发所有项目的构建和发布,垃圾处理我们的空闲时间,并用垃圾填充我们项目的历史
在bash中,您可以执行以下操作:
-任务:Bash@3
displayName:“确定更新了哪些应用”
投入:
targetType:“内联”
脚本:|
diff=“$(git diff HEAD~--仅限名称)”
[[“${diff[@]}”=~“包/共享”]&&echo“##vso[task.setvariable=shared_UPDATED]True”
[[“${DIFFS[@]}”=~“packages/mobile”]]&&echo“##vso[task.setvariable=mobile_UPDATED]True”
[[“${DIFFS[@]}”=~“packages/web”]]&&echo“##vso[task.setvariable=web_UPDATED]True”
这篇文章对我帮助很大,所以我想添加一些对流程所做的有用修改
我发现的第一个主要问题是,这个git diff命令不能同时处理多个提交
git diff HEAD HEAD~ --name-only
HEAD~只查看一次提交,一次推送可以同时包含多个提交
git diff HEAD HEAD~ --name-only
我意识到,自从管道上次成功运行以来,我需要在HEAD和commit id之间进行区分
此提交id可通过在/build/latest端点sourceVersion处调用Azure DevOps API获得
$response = (Invoke-RestMethod -Uri $url -Method GET -Headers $AzureDevOpsAuthenicationHeader)
$editedFiles = (git diff HEAD $response.sourceVersion --name-only)
我还修改了逻辑查找已更改的项目/模块文件夹。我不想每次通过硬编码项目名称添加新项目时都必须修改PowerShell脚本
$editedFiles | ForEach-Object {
$sepIndex = $_.IndexOf('/')
if($sepIndex -gt 0) {
$projectName = $_.substring(0, $sepIndex)
AppendQueueVariable $projectName
}
}
AppendQueueVariable将维护要返回管道的所有已更改项目的列表
最后,我获取排队项目的列表,并将它们传递到我的Maven多模块构建管道任务中
mvn -amd -pl [list returned from PS task] clean install
为了补充deleb的答案,下面是设置路径触发器的YAML代码:
trigger:
branches:
include:
- master
paths:
include:
- /path/to/src*
请注意,要使用路径触发器,还需要使用分支触发器
解决方案是在子文件夹中为每个服务提供一个azure-pipelines.yml。子文件夹中的每个azure-pipelines.yml必须具有以下触发器定义
trigger:
branches:
include:
- master
paths:
include:
- <service subfolder name>/*
触发器:
分支机构:
包括:
-主人
路径:
包括:
- /*
yaml的paths->include部分告诉azure管道只有在特定路径发生更改时才触发
没有必要在子文件夹中为azure-pipelines.yml指定不同的名称,可以保留相同的名称。类似地,没有必要将azure-pipelines.yml添加到repo的根目录中,除非在子文件夹之外的根目录中需要构建一些代码。在这种情况下,必须将以下触发器部分添加到
trigger:
branches:
include:
- master
paths:
exclude:
- <service subfolder name 1>/*
- <service subfolder name 2>/*