0

I'm using a local TFS 2018 instance for a customer project in which he owns the source code. I want him to have complete access to this code in the event I become unexpectedly unavailable.

My proposal for this is to create a TFS release step that syncs my TFS origin with a repo in his VSTS account.

I've been able to do this manually, from my workstation, using this approach:

cd /path/to/local/repo git remote add tfs url://tfs/git/repo git push --mirror tfs 

But I'm prompted for his VSTS credentials, which obviously won't work in a TFS release step.

Also, I encounter this error when attempting to remote add from the desktop of my TFS server:

D:\Agent\_work\37\s>git remote add Application https://customer.visualstudio.com/Applications/_git/Application Rename from 'D:/Agent/_work/37/s/.git/config.lock' to 'D:/Agent/_work/37/s/.git/config' failed. Should I try again? (y/n) 

I can add it at my workstation, although it doesn't show up as a change that can be committed for a push to TFS. So it seems I'm unable to tell TFS about the remote VSTS repository.

How can I fully automate this task in a TFS release step?

1 Answer 1

0

I was able to get this working using a combination of these answers:

  1. https://stackoverflow.com/a/45224858/722393
  2. https://stackoverflow.com/a/50925741/722393

The trick is to use the Personal Access Token (PAT), found in the security section of the VSTS user profile.

Here're the scripts I ended up with:

SyncCode.ps1, called from the build step

[CmdletBinding()] param( [Parameter(Mandatory)][string] $Application, [Parameter(Mandatory)][string] $LocalPath, [Parameter(Mandatory)][string] $Token ) . \\SERVER\Scripts\TfsBuild\Invoke-Git.ps1 $RemoteExists = $false $AllRemotes = git remote ForEach($Remote in $AllRemotes) { If($Remote = $Application) { $RemoteExists = $true Break } } If($RemoteExists) { Invoke-Git -Command "remote remove $Application" } Invoke-Git -Command "remote add $Application https://Personal%20Access%20Token:[email protected]/Applications/_git/$Application" Set-Location $LocalPath Invoke-Git -Command "push --mirror HydraMonitor" 

Invoke-Git.ps1, called from SyncCode.ps1

<# .Synopsis Invoke git, handling its quirky stderr that isn't error .Outputs Git messages, and lastly the exit code .Example Invoke-Git push .Example Invoke-Git "add ." #> Function Invoke-Git { param( [Parameter(Mandatory)] [string] $Command ) Write-Output "##[command]. git $Command" Try { $Exit = 0 $Path = [System.IO.Path]::GetTempFileName() Invoke-Expression "git $Command 2> $Path" $Exit = $LASTEXITCODE If ( $Exit -gt 0 ) { Write-Error (Get-Content $Path).ToString() } Else { Get-Content $Path } "Exit code: $Exit" } Catch { Write-Host "Error: $_`n$($_.ScriptStackTrace)" } Finally { If ( Test-Path $Path ) { Remove-Item $Path } } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.