如何在 Azure Pipelines 中获取 Git 标签

How to get Git Tag in Azure Pipelines

在 Azure Pipelines 中,我启用了 git 标记来触发管道,如下所示:

trigger:
  branches:
    include:
    - '*'
  tags:
    include:
    - '*'

现在我想知道是否有一种方法可以通过编程方式确定:

  1. 管道是从 git 提交或 git 标记开始的吗?
  2. 如果管道是从 git 标签启动的,标签名称是什么?

当您将管道配置为带标签的触发器时,这意味着当新标签被推送时管道开始到 运行。所以:

1) 管道将从 git 标记开始。

2) 我不明白这个问题,如果你推送标签 test 那么标签名称将是 test.

如果您想以编程方式知道构建触发器是否是标签以及标签名称是什么,您可以检查环境变量 Build.SourceBranch 如果构建来自标签,则值为:refs/tags/tagName.

所以只需添加一个 PowerShell 任务并打印值:

Write-Host $env:Build_SourceBranch

这个需要考虑不同的情况。如果你只是推送标签或使用 UI 创建它,管道从 git 标签开始。只提交不带任何标签,它将从 git 提交开始。毫无疑问,构建只会被触发一次。

但是如果你用标签推送提交,构建将被触发两次。第一个是由提交触发的,第二个是由标签触发的。检查这张照片。

这意味着管道从提交而不是标记开始。

总而言之,无论哪个先,触发构建的标签都是你推送或创建的。

为了更直观地了解这一点,您可以在内部版本号中添加变量 ' $(Build.SourceBranch)'。这是我关于如何在 YAML 文件中配置内部版本号的代码:

name: $(Build.SourceBranch)-$(date:yyyyMMdd)$(rev:.r)
trigger:
  branches:
    include:
    - '*'
  tags:
    include:
    - '*'

这是触发构建的结果。如果是tag,会显示refs_tags_{tagname},如果是commit,会显示refs_heads_{branchname}.

要检查提交是否来自标签,请使用:

startsWith(variables['Build.SourceBranch'], 'refs/tags/')

来自詹姆斯·瑟利:

Get the name of the tag with:

$tags = git tag --sort=-creatordate
$tag = $tags[0]

This sorts the tags correctly for both annotated and unannotated tags, and so the first result is the most recent tag.

我删除了原始答案并将其替换为 James Thurley 的正确答案。我会删除我的答案,但您似乎无法删除已接受的答案。

使用 git tag -l v* 接受的答案对我不起作用,因为它没有正确排序标签,而是给出 1.1, 1.11, 1.12, 1.2, 1.3, etc.

我发现这样做更好:

$tags = git tag --sort=-creatordate
$tag = $tags[0]

这会为带注释和未带注释的标签正确排序,因此第一个结果是最新的标签。

根据 this doc 可以在 BUILD_SOURCEBRANCH 中找到启动构建的标签。

If this build was queued by the creation of a tag then this is the name of that tag. For Azure Pipelines, the BUILD_SOURCEBRANCH will be set to the full Git reference name, eg refs/tags/tag_name.

git describe 可以为给定的 git 散列提供(最接近的)标签名称,而 Azure 可以为您提供当前散列 $(Build.SourceVersion).

使用 --exact-match 限制 git describe 仅使用来自特定提交的标签:

git describe --exact-match $(Build.SourceVersion)

如果有标签,它将在标准输出上返回:

$ git describe --exact-match d9df242
v1.0.0

如果没有标签,git describe --exact-match退出,退出代码为128:

$ git describe --exact-match cc1f9d2
fatal: no tag exactly matches 'cc1f9d23854c37dec000485c6c4009634516a148'
$ echo $?
128

因此您可以在测试中使用它,或者简单地使管道中的任务失败,而不仅仅是标记的修订。

这里的其他答案涵盖了问题的第一部分,因此正如 Alex Kaszynski 已经指出的那样,您可以使用 YAML 条件:

startsWith(variables['Build.SourceBranch'], 'refs/tags/')

现在获取标签名称比提出问题时更容易一些:

Build.SourceBranchName

此变量包含最后一个 git 引用路径段,因此例如如果标签是 refs/tags/1.0.2,此变量将包含 1.0.2:标签名称。

Full docs are now here.

回答你的第二个问题。 如果您不介意使用单独的管道通过标签触发,那么您可以启用持续集成并覆盖 YAML 触发器,如下所示。此示例将触发带有模式 'test-*' 标签的构建(无论分支如何)。

通过这样做,您只需在管道中执行 git describe,它将输出触发构建的标签的名称。

这里可以看到结果:

我知道我的回答可能并不适用于所有人。但是,我想为那些使用 Azure DevOps 的本地安装但还没有 replace 功能(2019)的人提供它作为替代方案。

steps:
- powershell: |
    $tag = "$(Build.SourceBranch)"
    $tag = $tag -replace "refs/tags/", ""
    echo "##vso[task.setvariable variable=tag;isOutput=true]$tag"
  name: createTagVariableStep

此步骤使用特殊语法调用 setvariable 日志命令以设置名称为 tag 的变量以在当前作业中使用。它可以作为 $(createTagVariableStep.tag).

访问

如果您使用的是具有替换功能的 Azure DevOps 版本(2020 on prem 或 Azure DevOps Services),那么您可以使用如下内容:

variables:      
  tag: $[replace(variables['Build.SourceBranch'], 'refs/tags/', '')]

对于这些选项中的任何一个,我都会将它们与条件结合使用

job: SomeAwesomeJob
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') # only run when there is a tag