Calling Git commands from your Azure DevOps pipeline script

Thanks to new features in Azure DevOps (notice for me: subject for another article...) I was working on pipeline which should clone and push to git repo. After solving different things like where to store the script, where to store the pipeline YAML file etc. I hit another issue - authentication.

Azure DevOps Access Token

May be you already know, that there is system variable  System.AccessToken which you can use during pipeline to access the resources of Azure DevOps. This AccessToken is token you can use in "bearer" authentication. To use it in PowerShell script, you need to assign it into some environment variable e.g. like this:

    - task: PowerShell@2 
      inputs:
          targetType: 'filePath'
          filePath: 'myscript.ps1'
          arguments: ${{ format('-Param ''{0}''',parameters.MyParam) }}
      displayName: Run my script
      name: runScript
      env:
        SYSTEM_ACCESSTOKEN: $(System.AccessToken)      

How to use Access Token when using git command

When you use git as you are used to, e.g. by calling "git clone myrepourl repopath" during the pipeline run, you will get error that the repo doesn't exists or you do not have access. Yes, because the git cannot correctly authenticate. How to force usage of the Access Token? 

Git have wide configuration possibilities and some internet research will guide you to setting with name http.extraheader. Through this config you can set your own Authorization header for the call. Result could look like this:

git -c http.extraheader="Authorization: Bearer $($env:ACCESS_TOKEN)" clone $RepoURL $RepoPath

Using the -c parameter will set the configuration for this call only. This makes it more secure than setting the configuration by calling "git config" because this will store the settings permanently. 

Ok, you have set the authentication, but you still get error that repo doesn't exists or you do not have access. What now?

Access Token permissions

The access token have permissions, which are set for the Build service account. There are two accounts "xxx Build Service" - one is "Project Collection Build Service" and one is "Project Build Service". As you can see, one is project specific, one is collection wide. Which one is used? All depends on setting, which tells Azure DevOps if you want to give permissions to build pipeline to access all resources in the collection or only in the specific project. This is set on project level or on organization level. If you limit it on organization level, you cannot widen it on project level, of course.

Organization level setting:

Project level setting:

By default, pipeline have access to whole collection and thus is using the "Project Collection Build Service" account. How to set different permissions for this account?

Set permissions for repositories

Picture is better than thousands words:

If you set correct permissions, the access token should have access to the repo and the command will work when running as part of your pipeline. Of course, in same way you can set permissions for other resources, if you want to access them from pipeline by using the Access Token, e.g. when calling Azure DevOps REST API. But this is for another article again...

Conclusion

I needed to use git clone and git push in my pipeline, because I have created pipeline to create new BC App for me (or my colleagues) in automated way when we need to create it, e.g. when we are starting to develop some new PTE for our customer. The script creates not only the App repository, but set the App Id, ID Range and other things, create necessary build and release pipelines... You can do whatever you want... By using the http.extraheader in git you can use authorization as you want. And if you need some other specific setting for the http communication, you know now that there are plenty of settings you can use.

I wish you happy building!

Anonymous