Make TeamCity popping all git branches

On the build server, I configured TeamCity (8.1.1) so that it executes the build process if there are changes in the main, one of the function branches or in one of the request request branches, using the branch specifier:

+:refs/heads/* +:refs/pull/(*/merge) 

I turned on the build agent option:

 teamcity.git.use.local.mirrors=true 

which clones the repository in a directory outside the assembly directory and then extracts it from this local repository.

The build process requires access to the git repository and the main branch, even to build one of the function branches or request request branches. However, TeamCity only has a branch that contains changes to the local repository, thereby causing my builds to fail, for example. when the change was in the issue / mycoolissue branch, then this is the only branch that exists in the git repository in the TeamCity workspace.

I tried to do local git fetch to get the main branch, but since the local repository does not have a master branch, this fails. Although I could add a remote pointer to the origin (a private github repository), which would mean that I would also have to process the credentials, and I would prefer TeamCity to take care of all this for me.

My question is, is there a way to tell TeamCity to simply pull all branches to the local repository and production repository?

+6
source share
2 answers

It turns out that there is still no way to do this in TeamCity, so at the same time this problem was solved by running an additional MsBuild script at the beginning of the build process, which checks if the master branch is present in the current (local) repository and receives it if this is not true.

The script looks like this:

 <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Run" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <DirWorkspace>$(MSBuildProjectDirectory)</DirWorkspace> <DirRepository Condition=" '$(DirRepository)' == '' ">$(DirWorkspace)</DirRepository> <DirGit Condition=" '$(DirGit)' == '' ">c:\Program Files (x86)\Git\bin</DirGit> </PropertyGroup> <Import Project="$(DirWorkspace)\GitHasMasterBranch.msbuild" Condition="Exists('$(DirWorkspace)\GitHasMasterBranch.msbuild')"/> <Import Project="$(DirWorkspace)\GitGetMasterBranch.msbuild" Condition="Exists('$(DirWorkspace)\GitGetMasterBranch.msbuild')"/> <Target Name="Run" DependsOnTargets="_DisplayInfo;_FetchOriginMasterIfNotExists"> <!-- Do nothing here --> </Target> <!-- Display info --> <Target Name="_DisplayInfo"> <Message Text="Preparing workspace ..." /> </Target> <PropertyGroup> <ExeGit>$(DirGit)\git.exe</ExeGit> </PropertyGroup> <Target Name="_FetchOriginMasterIfNotExists" DependsOnTargets="_DisplayInfo"> <GitHasMasterBranch LocalPath="$(DirRepository)"> <Output TaskParameter="HasMaster" PropertyName="HasMaster" /> </GitHasMasterBranch> <Message Text="Not fetching master branch because it already exists" Condition="($(HasMaster))" /> <Message Text="Fetching master branch because it does not exist" Condition="(!$(HasMaster))" /> <GitGetMasterBranch LocalPath="$(DirRepository)" Condition="(!$(HasMaster))"/> </Target> </Project> 

In this script, the GitHasMasterBranch MsBuild inline script line looks like this:

 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="4.0"> <UsingTask TaskName="GitHasMasterBranch" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> <ParameterGroup> <LocalPath ParameterType="System.String" Required="true" /> <HasMaster ParameterType="System.Boolean" Output="true" /> </ParameterGroup> <Task> <Code Type="Method" Language="cs"> <![CDATA[ public override bool Execute() { var info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = "branch", WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; var text = new System.Text.StringBuilder(); var process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { text.Append(e.Data); }; process.ErrorDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { Log.LogError(e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); HasMaster = text.ToString().Contains("* master"); // Log.HasLoggedErrors is true if the task logged any errors -- even if they were logged // from a task constructor or property setter. As long as this task is written to always log an error // when it fails, we can reliably return HasLoggedErrors. return !Log.HasLoggedErrors; } ]]> </Code> </Task> </UsingTask> </Project> 

And the GitGetMasterBranch MsBuild inline script looks like this:

 <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="4.0"> <UsingTask TaskName="GitGetMasterBranch" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> <ParameterGroup> <LocalPath ParameterType="System.String" Required="true" /> </ParameterGroup> <Task> <Code Type="Method" Language="cs"> <![CDATA[ public override bool Execute() { // Get the name of the current branch var info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = "symbolic-ref --short -q HEAD", WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; var text = new System.Text.StringBuilder(); var process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { text.Append(e.Data); }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); var currentBranch = text.ToString().Trim(); // git fetch info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = "fetch origin", WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { Log.LogMessage(MessageImportance.High, e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); // git checkout master info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = "checkout master", WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { Log.LogMessage(MessageImportance.High, e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); // git pull info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = "pull", WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { Log.LogMessage(MessageImportance.High, e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); // git checkout <CURRENT_BRANCH> info = new System.Diagnostics.ProcessStartInfo { FileName = "git", Arguments = string.Format("checkout {0}", currentBranch), WorkingDirectory = LocalPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; process = new System.Diagnostics.Process(); process.StartInfo = info; process.OutputDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { Log.LogMessage(MessageImportance.High, e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); // Log.HasLoggedErrors is true if the task logged any errors -- even if they were logged // from a task constructor or property setter. As long as this task is written to always log an error // when it fails, we can reliably return HasLoggedErrors. return !Log.HasLoggedErrors; } ]]> </Code> </Task> </UsingTask> </Project> 

Essentially, all this last script is to save the current branch name, do a GIT fetch to get all branches, do a GIT checkout main branch, and then do a GIT checkout original branch.

This is not the fastest approach, but it works now.

0
source

Starting with TeamCity 10.0.4 you can do this by adding the configuration parameter teamcity.git.fetchAllHeads=true See here

+4
source

Source: https://habr.com/ru/post/969508/


All Articles