基于提交记录递增Azure Pipelines版本号的实现问题
实现双仓库驱动的Azure DevOps流水线版本号规则
问题背景
我有一个关联两个仓库的Azure DevOps流水线:
- code仓库:存储应用代码
- config仓库:存储环境变量配置文件
需要实现以下版本号规则,格式为{major}.{minor}.{codeVersion}.{configVersion}:
major和minor由开发者手动指定- 当
major.minor不变时,code仓库有新提交则自动递增codeVersion - 当
major.minor.codeVersion不变时,config仓库有新提交则自动递增configVersion - 无代码/配置变更时,重复运行流水线生成相同版本号
示例版本序列:
- MyApp 0.1.0.0(首次运行)
- MyApp 0.1.1.0(code仓库有提交)
- MyApp 0.1.1.1(config仓库有提交)
- MyApp 0.1.2.0(code仓库有提交)
- MyApp 0.1.2.0(无变更重复运行)
原方案使用counter函数,但每次运行流水线不管code仓库是否有提交,codeVersion都会递增,导致configVersion始终为0,无法满足需求。核心问题是counter函数只要输入键不变就会自动递增,无法关联仓库提交的变更。
解决方案
核心思路是基于仓库提交哈希的变化来触发版本号递增,通过查询历史流水线的运行记录,对比当前与上一次的提交哈希,决定是否递增对应版本段。
完整流水线实现
name: '$(Build.DefinitionName)-$(major).$(minor).$(codeVersion).$(configVersion)' variables: - name: major value: 0 - name: minor value: 1 # 声明后续步骤会赋值的变量 - name: codeCommitHash value: '' - name: codeVersion value: '' - name: configCommitHash value: '' - name: configVersion value: '' resources: repositories: - repository: configRepo type: git name: YourProject/ConfigRepo # 替换为你的config仓库项目路径 stages: - stage: CalculateVersion displayName: 计算版本号 jobs: - job: VersionCalculationJob displayName: 生成版本组件 steps: # 拉取code仓库(默认仓库) - checkout: self fetchDepth: 1 displayName: 拉取代码仓库 # 拉取config仓库 - checkout: configRepo fetchDepth: 1 displayName: 拉取配置仓库 # 计算版本号的PowerShell脚本 - powershell: | $orgUrl = "$(System.TeamFoundationCollectionUri)" $projectName = "$(System.TeamProject)" $definitionId = "$(System.DefinitionId)" $pat = "$(System.AccessToken)" # 构建API请求头 $headers = @{ Authorization = "Bearer $pat" } # 查询最近一次成功的流水线运行记录 $runsUrl = "$orgUrl/$projectName/_apis/build/builds?definitions=$definitionId&statusFilter=completed&resultFilter=succeeded&`$top=1&api-version=7.1-preview.7" $response = Invoke-RestMethod -Uri $runsUrl -Headers $headers -Method Get # 初始化历史变量 $prevCodeCommit = "" $prevCodeVersion = 0 $prevConfigCommit = "" $prevConfigVersion = 0 # 获取上一次运行的变量值 if ($response.count -gt 0) { $prevRun = $response.value[0] $varsUrl = "$orgUrl/$projectName/_apis/build/builds/$($prevRun.id)/variables?api-version=7.1-preview.1" $prevVars = Invoke-RestMethod -Uri $varsUrl -Headers $headers -Method Get $prevCodeCommit = $prevVars.value.codeCommitHash.value $prevCodeVersion = [int]$prevVars.value.codeVersion.value $prevConfigCommit = $prevVars.value.configCommitHash.value $prevConfigVersion = [int]$prevVars.value.configVersion.value } # 获取当前仓库的提交哈希 $currentCodeCommit = $(git rev-parse HEAD) $currentConfigCommit = $(git -C "$(Build.SourcesDirectory)/configRepo" rev-parse HEAD) # 计算codeVersion:代码提交变更则递增,否则沿用历史值 $currentCodeVersion = $prevCodeVersion if ($currentCodeCommit -ne $prevCodeCommit) { $currentCodeVersion = $prevCodeVersion + 1 } # 计算configVersion:代码版本不变且配置提交变更则递增,否则重置为0或沿用历史值 $currentConfigVersion = 0 if ($currentCodeVersion -eq $prevCodeVersion) { if ($currentConfigCommit -ne $prevConfigCommit) { $currentConfigVersion = $prevConfigVersion + 1 } else { $currentConfigVersion = $prevConfigVersion } } # 设置当前流水线的输出变量 Write-Host "##vso[task.setvariable variable=codeCommitHash;isOutput=true]$currentCodeCommit" Write-Host "##vso[task.setvariable variable=codeVersion;isOutput=true]$currentCodeVersion" Write-Host "##vso[task.setvariable variable=configCommitHash;isOutput=true]$currentConfigCommit" Write-Host "##vso[task.setvariable variable=configVersion;isOutput=true]$currentConfigVersion" displayName: 计算版本号组件 name: VersionCalc - stage: BuildAndDeploy displayName: 构建与部署 dependsOn: CalculateVersion variables: # 传递版本变量到当前阶段 codeVersion: $[ stageDependencies.CalculateVersion.VersionCalculationJob.outputs['VersionCalc.codeVersion'] ] configVersion: $[ stageDependencies.CalculateVersion.VersionCalculationJob.outputs['VersionCalc.configVersion'] ] codeCommitHash: $[ stageDependencies.CalculateVersion.VersionCalculationJob.outputs['VersionCalc.codeCommitHash'] ] configCommitHash: $[ stageDependencies.CalculateVersion.VersionCalculationJob.outputs['VersionCalc.configCommitHash'] ] jobs: - job: BuildJob displayName: 构建应用 steps: - script: | echo "当前应用版本:$(major).$(minor).$(codeVersion).$(configVersion)" echo "代码提交哈希:$(codeCommitHash)" echo "配置提交哈希:$(configCommitHash)" displayName: 打印版本信息 # 这里添加你的构建、打包、部署步骤
关键逻辑说明
- 提交哈希获取:通过
git rev-parse HEAD获取两个仓库的最新提交ID,作为判断变更的依据。 - 历史流水线查询:调用Azure DevOps REST API获取最近一次成功运行的流水线变量,包括历史提交哈希和版本号。
- 版本号计算:
codeVersion:仅当当前code提交哈希与历史不同时递增,否则沿用历史值。configVersion:若codeVersion未变化,且config提交哈希与历史不同则递增;若codeVersion变化,直接重置为0。
- 变量传递:通过阶段输出变量将计算好的版本号传递到构建部署阶段。
权限说明
确保流水线的服务账号拥有读取构建记录的权限,否则无法查询历史流水线变量。可以在项目设置的权限管理中,为构建服务账号分配对应的权限。
内容的提问来源于stack exchange,提问作者Colin Smith
相关产品推荐
相关产品推荐

