40

In Azure Pipelines, I have enabled git tags to trigger pipelines like so:

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

Now I want to know if there is a way to determine programmatically:

  1. Was the pipeline started from a git commit or git tag?
  2. If the pipeline was started from a git tag, what is the tag name?
Muhammad Rehan Saeed
  • 35,627
  • 39
  • 202
  • 311

11 Answers11

25

The other answers here cover the first part of the question, so as Alex Kaszynski has already pointed out, you can use a YAML condition:

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

Getting the tag name is now a bit easier than it was at the time the question was asked:

Build.SourceBranchName

This variable contains the last git ref path segment, so for example if the tag was refs/tags/1.0.2, this variable will contain 1.0.2: the tag name.

Full docs are now here.

Mark Bell
  • 28,985
  • 26
  • 118
  • 145
  • good solution, for anybody who's struggling variable needs to be consumed like that '$(Build.SourceBranchName)' – Mb175 Aug 31 '23 at 14:37
21

To check if the commit was from a tag, use:

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

From James Thurley:

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.

I've removed the original answer and replaced it with the correct one from James Thurley. I'd delete my answer, but it appears you can't delete an accepted answer.

Alex Kaszynski
  • 1,817
  • 2
  • 17
  • 17
  • 2
    This relies on tags sorting correctly and may not give you the name of the tag that actually triggered the build. – jrjohnson Nov 20 '19 at 19:48
  • 1
    New answer reflects sorting. Couldn't remove the answer, so I quoted James's answer. – Alex Kaszynski Dec 03 '19 at 23:26
  • I know this is a little bit old but are you using the first option? I'm having a lot of troubles trying to use it. I've found [this issue on GitHub](https://github.com/MicrosoftDocs/azure-devops-docs/issues/4951) but it is not very clear to me. – Jéf Bueno Mar 26 '21 at 11:25
11

git describe can provide you with the (closest) tag name for a given git hash and Azure can give you the current hash with $(Build.SourceVersion).

Use the --exact-match to limit git describe to only use a tag from the specific commit:

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

If there is a tag, it'll be returned on stdout:

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

If there is no tag, git describe --exact-match exits with exit code 128:

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

so you can use this in a test or simply fail the task in pipelines that trigger on more than just tagged revisions.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    If you have non-annotated tags you should use this comman: $ git describe --tags --exact-match cc1f9d2 – etalon11 Apr 20 '21 at 11:50
7

The accepted answer using git tag -l v* didn't work for me as it didn't order the tags correctly, instead giving 1.1, 1.11, 1.12, 1.2, 1.3, etc.

I found it better to do:

$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
  • 2,650
  • 26
  • 38
4

When you configure the pipeline to be triggers with tag the meaning that when new tag is pushed the pipeline start to run. so:

1) The pipeline will start from the git tag.

2) I don't understand the question, if you pushed tag test so the tag name will be test.

If you want to know programmatically if the build trigger was a tag and what is the tag name you can check the environment variable Build.SourceBranch if the build is from a tag the value will be: refs/tags/tagName.

So just add a PowerShell task and print the value:

Write-Host $env:Build_SourceBranch
Shayki Abramczyk
  • 36,824
  • 16
  • 89
  • 114
4

According the this doc the Tag which started the build can be found in 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.

jrjohnson
  • 2,401
  • 17
  • 23
4

To answer your second question. If you don't mind having a separate pipeline for triggering through tags, then you can enable continuous integration and override the YAML trigger like shown below. This example will trigger builds with tags having the pattern 'test-*' (regardless of branch).

enter image description here

By doing this, you can just execute git describe in your pipeline and it will output the name of the tag that triggered the build.

Here you can see the result:

enter image description here

Felza
  • 63
  • 7
  • DISCLAIMER: After some further testing, I have discovered that git describe will indeed take newest tag on that commit. But that also means if you push 2 tags to the same commit simultaneously, git describe will output the newest tag in both runs of the pipeline. – Felza Sep 17 '20 at 10:55
4

I realize my answer may not apply to everyone. However, I wanted to provide it as an alternative for those using an on prem install of Azure DevOps that does not have the replace function yet (2019).

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

This step uses the special syntax to call the setvariable logging command to setup a variable by the name of tag for use within the current job. It can be accessed as $(createTagVariableStep.tag).

If you are using a version of Azure DevOps that has the replace function (2020 on prem or Azure DevOps Services) then you can use something like the following:

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

For either of these options I would use them in combination with a condition

job: SomeAwesomeJob
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') # only run when there is a tag
Kirk Spencer
  • 511
  • 4
  • 7
3

This need to consider different situations. If you just push tag or create it with UI, the pipeline are started from git tag. Just commit without any tag, it will started from git commit. No doubt, the build will be triggered just once.

But if you push commit with tag, the build will be triggered twice. First is triggered by commit, and second is by tag. Check this pic. enter image description here

These means the pipeline started from a commit instead of tag.

All in all, no matter which is first, the tag which trigger the build are all you pushed or created.

For getting more intuitive view about this, you can add variable ' $(Build.SourceBranch)' in your build number. Here is my code about how to configure build number in YAML file:

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

Here is the result of what triggered the build. If tag, it will shows refs_tags_{tagname}, if it's commit, it will shows refs_heads_{branchname}.

enter image description here

Mengdi Liang
  • 17,577
  • 2
  • 28
  • 35
  • 1
    Perhaps I was not clear enough. I want to know programmatically if the pipeline was started with a tag and what the tag is. – Muhammad Rehan Saeed May 28 '19 at 07:45
  • You can check this info with one system variable - ' $(Build.SourceBranch) ' . For a more intuitive display, you can add it in your pipeline number to show it. I have update more details about this in my answer. – Mengdi Liang May 28 '19 at 09:08
3

The predefined variable Build.SourceBranchName contains alternatively tag name or branch name. Here is how to read it being sure the value it is always a tag.

variables:
- name: gitTag
  ${{ if startsWith(variables['Build.SourceBranch'], 'refs/tags/') }}:
    value: $[variables['Build.SourceBranchName']]
  ${{ else }}:
    value: ''
freedev
  • 25,946
  • 8
  • 108
  • 125
  • Thanks I like this solution. Your value line didn't work however, but this does: `value: ${{ variables['Build.SourceBranchName'] }}` – Lars Feb 22 '23 at 09:50
  • @Lars - this is quite strange, I have doublechecked right now and I can confirm my answer. I think in your case there should be a difference... – freedev Feb 24 '23 at 09:14
0

Some good answers already for your first question (determine if the build was triggered from a tag).

To get the name of the tag, you can use the predefined variable Build.SourceBranchName.

Check it out here: https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml

Dan Leonard
  • 99
  • 2
  • 2