azure-pipelines-agent: Cannot call git tag/push in yaml build

  - powershell: |
      Write-Host "git tag $env:tag"
      git tag $env:tag
      Write-Host "git push origin $env:tag"
      git push origin $env:tag
    displayName: Git Tag
    workingDirectory: $(Build.SourcesDirectory)
    env:
      tag: '$(PACKAGE_VERSION)'
      SYSTEM_ACCESSTOKEN: $(system.accesstoken)
    ignoreLASTEXITCODE: false
    errorActionPreference: Stop
    failOnStderr: true

This command freezes forever no matter what permissions I add. I’m able to call the same command from the UI build and it works without any issues, this is only a problem in yaml builds.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 22 (6 by maintainers)

Most upvoted comments

For the sake of completeness: We had a similar issue with git failing. Here is how re resolved it! 🎉

  1. Our build agent had the standard permissionset, but as we enabled custom policies on our branch (such as disallowing direct pushes without a PR), the agent needed additional permissiosn:
  • bypass policies when pushing
  • and bypass policies when completing pull requests
  1. Then, we did not have to pass the bearer token using git -c .... as described above. Rather, we just had to add a task checkout with persistCretentials:true.

  2. Finally, there was one more important step: We had a powershell inline script which was essentially calling

git tag $(GitVersion.NuGetVersion)
git push --tags

this ALWAYS failed with the error code 1 as it is described above in this thread. The only way we could get rid of this error was to split those comands into two separate powershell scripts

So for you guys, here is the essential parts of our yaml file:


# run on PRs and whenever a feature branch is pushed
trigger:
- master
- feature/*

pool:
  vmImage: 'windows-latest'

variables:
  solution: 'Sample.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:

# NOTE: You need tos pecify 'persistCredentials:true' to allow your build agent to has access to git commands for pull/tag/push
# see https://docs.microsoft.com/en-us/azure/devops/pipelines/scripts/git-commands?view=azure-devops&tabs=yaml
- checkout: self
  persistCredentials: true
  clean: true

# create semantic version
- task: GitVersion@5
  inputs:
    runtime: 'full'

# ...
# ... run all your crazy build stuff here 
# ...

# tag the current branch with the version number
- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      git tag $(GitVersion.NuGetVersion)
      Write-Host "Successfully created tag $(GitVersion.NuGetVersion)" 

# push created tag to origin
# NOTE: you need to set 'persistCredentials: true' in the checkout task. Otherwise git will fail with error code 1.
# NOTE: You cannot run both "git tag xyz" AND "git push --task" in the same powershell command. If you do, git will fail with error code 1
# NOTE: IF you get an error from this git command, make sure, that your build user has the required permissions!
#       In our case, the build agent needs the additional permissions for "bypass policies when pushing" and "bypass policies when completing pull requests"
#       because we have a custom policy in place. (See: https://opti-q.visualstudio.com/<your_project_name>/_settings/repositories)
- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      git push --tags
      Write-Host "Successfully pushed tag $(GitVersion.NuGetVersion) to origin"      


Just for reference, there’s another way of doing this…

- checkout: self
  persistCredentials: true

## Rest of pipeline ##

- script: |
     git tag $(GitVersion.NugetVersionV2)
     git push origin $(GitVersion.NugetVersionV2)
  workingDirectory: $(Build.SourcesDirectory)

The persistCredentials allows the token to be automatically passed to other git commands. Note the assignment of workingDirectory, otherwise I had an error that the location was not a git repository.

For an annotated tag rather than lightweight tag, the syntax would look like this…

- script: |
     git tag -a <tagname> -m <message>

To get a user/date against it you need to set the user name/email as well e.g.

- script: |
    git config --global user.name "BuildService"
    git config --global user.email "autobuild@fabrikam.com"
    git tag -a <tagname> -m <message>

For this to work, the Project Collection Build Server account (not the Project Build Service Accounts group) needs to be allocated the Contribute permission for the Repositories

failOnStderr: false fixed the issue

Thanks for all the help

@AceHack it’s available in ENV for yaml build for now, we are working on repository checkout option for preserver git credential, for now, i guess you need to run git -c http.extraheader="AUTHORIZATION: bearer $(System.AccessToken)" tag MyTag

UPDATE: Redirecting git stderr to stdout is error-prone because it hides errors and progress, and modifies output of git commands. It’s better to rely on failOnStderr like others pointed out.

OK. Apparently git writes progress to stderr… (just test/google it for more info)

But failOnStderr: false is like trying to kill a fly with a bazooka.

And there is an environment variable called GIT_REDIRECT_STDERR.

You could add it in your powershell:

$env:GIT_REDIRECT_STDERR` = '2>&1'

Or in the variables section of your pipeline (which also injects it in the environment):

variables:
  GIT_REDIRECT_STDERR: 2>&1

Thanks for helpful conversation. Found this on https://stackoverflow.com/a/58492632/880524

@TingluoHuang FYI, I’ve included my command as I did previously and you can see I’m already doing what you suggested.

- powershell: |
    git --version
    Write-Host "git tag $env:tag"
    **git -c http.extraheader="AUTHORIZATION: bearer $env:SYSTEM_ACCESSTOKEN" tag $env:tag**
    Write-Host "git push origin $env:tag"
    git -c http.extraheader="AUTHORIZATION: bearer $env:SYSTEM_ACCESSTOKEN" push origin $env:tag
  displayName: Git Tag
  workingDirectory: $(Build.SourcesDirectory)
  env:
    tag: '$(PACKAGE_VERSION)'
    SYSTEM_ACCESSTOKEN: $(system.accesstoken)
  ignoreLASTEXITCODE: false
  errorActionPreference: Stop
  failOnStderr: true

Also as I’ve stated earlier I’ve tried every combination of adding -c http.extraheader="AUTHORIZATION: bearer $env:SYSTEM_ACCESSTOKEN", only on the tag, only on the push, on both the tag and push and on neither the tag nor push. They all fail in some way.

I will try turning off failOnStderr and report back.

Thanks.