我们的应用程序在 CI 流程中使用 VSTS,并且我们要求每次代码合并回 master 时补丁版本都应增加一。
我们创建了一个 shell 脚本,它将更改应用程序的版本并标记存储库,但现在我们正在寻找流程中注入它的最佳位置。我们想到了以下几点:
Master commit hook build - 把它放在这里的问题是我们用某些策略保护了 master 分支(必须解决所有评论,项目必须构建等)。因此,构建代理运行脚本无权推送更改。
拉取请求构建 - 此选项会将脚本集成到用于验证构建的构建作业中。这实际上是有效的,但是当更新被推送到分支时,这会触发无限构建循环,因为 PR 会自动重建分支。总的来说,这个选项看起来比较脆弱。
我很想解决方案 1,但尽管尽一切努力授予代理适当的角色,但它仍然无法访问存储库。我们收到以下错误:
TF402455: Pushes to this branch are not permitted; you must use a pull request to update this branch.
有没有我缺少的标准方法来做到这一点?
要通过 CI 构建更新文件版本并为新提交添加标签,您可以添加 PowerShell 任务。详细步骤如下:
在构建定义中设置权限并配置
首先进入版本控制选项卡,为构建服务允许以下项目:
然后在构建定义中,在变量选项卡中将变量
system.prefergit
添加为 true
,并在选项选项卡中启用 允许脚本访问 OAuth 令牌。
更多详细信息,您可以参考在脚本中运行Git命令。
添加powershell脚本
git -c http.extraheader="AUTHORIZATION: bearer %SYSTEM_ACCESSTOKEN%" fetch
git checkout master
# Get the line of the file that contain the version
# split the line, and only get the version number major.minor.patch.
# check the version numbers (such as if patch less than 9) and increase the version
#replace the old version with new version in the file
git add .
git commit -m 'change the version as $newVersion'
git tag $newVersion
git push origin master --tags
注意: 即使新版本和标签可以成功推送到远程仓库,PowerShell 任务也可能会失败。因此,您应该在具有自定义选项的 PowerShell 任务之后将任务设置为即使前一个任务失败。
这是我对类似问题的回答的交叉帖子,以防万一。
@Kailash Uniyal 对他们的答案没有足够的支持,@Newteq Developer 对他们的评论也没有足够的支持。
首先,您必须向构建服务用户授予正确的权限:
有关访问系统令牌的签出步骤的 Microsoft 文档
如果您要创建 git 标签或执行任何可能持续存在的操作,则结帐步骤的
clean: true
配置选项至关重要。 “构建管道不会自动清除对本地存储库的某些类型的更改”
这是 2024 年提供的所有答案中唯一对我有用的方法。(下面的 YAML 是一个非常基本的自定义脚本,用于基于包含常规提交消息的合并 PR 来增加语义版本控制)。
trigger:
- main
pool:
vmImage: "ubuntu-latest"
jobs:
- job: PreMergeValidation
displayName: "Pre-Merge Validation"
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
steps:
- task: PowerShell@2
inputs:
targetType: "inline"
script: |
if ($env:SYSTEM_PULLREQUEST_PULLREQUESTID) {
# PR Validation context
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:BUILD_REPOSITORY_ID)/pullRequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)?api-version=7.0"
$headers = @{
Authorization = "Bearer $($env:SYSTEM_ACCESSTOKEN)"
}
$pullRequestInfo = Invoke-RestMethod -Uri $url -Method 'GET' -ContentType 'application/json' -Headers $headers
# Write-Host "Pull Request Info: $($pullRequestInfo | ConvertTo-Json -Depth 100)"
$title = $pullRequestInfo.title
Write-Host "PR Title: $title"
# Regular expression for conventional commits
$regex = "^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert|BREAKING CHANGE)(\(.+\))?!?: .+"
if ($title -notmatch $regex) {
Write-Error "PR title does not follow Conventional Commit guidelines. Please ensure the title starts with one of the allowed types (e.g., feat, fix) followed by an optional scope and a colon."
exit 1
} else {
Write-Host "PR title follows Conventional Commits format"
}
}
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: "Validate PR Title against Conventional Commits"
- job: PostMergeActions
displayName: "Post-Merge Actions"
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
steps:
- checkout: self
persistCredentials: true #Important - Persist creds to run further git command
clean: true #Important - Certain kinds of changes to the local repository aren't automatically cleaned up by the build pipeline
- task: PowerShell@2
inputs:
targetType: "inline"
script: |
git config --global user.email "[email protected]"
git config --global user.name "ADO pipeline"
# Fetch the latest changes
git fetch --all
# Ensure the branch exists and switch to it
git checkout main
# Read and increment the version number
$versionFilePath = "version.txt"
$version = Get-Content $versionFilePath
$versionParts = $version -split '\.'
$major = [int]$versionParts[0]
$minor = [int]$versionParts[1]
$patch = [int]$versionParts[2]
$commitMessage = git log -1 --pretty=%B
Write-Host "Latest commit message: $commitMessage"
if ($commitMessage -match "(?i)^Merged PR \d+: BREAKING CHANGE") {
$major++
$minor = 0
$patch = 0
} elseif ($commitMessage -match "(?i)^Merged PR \d+: feat") {
$minor++
$patch = 0
} else {
$patch++
}
# Update the version number
$newVersion = "$major.$minor.$patch"
Set-Content -Path $versionFilePath -Value $newVersion
Write-Host "Bumping version to $newVersion"
# Commit and tag the new version
git add $versionFilePath
git commit -m "chore(release): bump version to $newVersion [skip ci]"
# git tag -a "v$newVersion" -m "Release $newVersion"
# Push changes and tags
git push --follow-tags
displayName: "Validate Commit Message and Bump Version"