2014-05-19 18 views
6

Na serwerze kompilacji skonfigurowałem TeamCity (8.1.1), tak aby wykonywał proces kompilacji, jeśli są zmiany w systemie głównym, jednej z gałęzi operacji lub jednej z opcji Żądanie branże wykorzystujące specyfikator Branża:Spraw, aby TeamCity usuwał wszystkie gałęzie git

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

ja włączyłem opcji agenta kompilacji:

teamcity.git.use.local.mirrors=true 

który klonuje repozytorium w katalogu spoza katalogu build a następnie wyciąga z tego lokalnego repozytorium.

Proces kompilacji wymaga dostępu do repozytorium git i gałęzi głównej, nawet w przypadku kompilacji jednej z gałęzi elementów lub gałęzi żądań pobierania. Jednak TeamCity ma tylko gałąź, która zawiera zmiany w lokalnym repozytorium, co powoduje, że moje kompilacje zawodzą, np. gdy zmiana dotyczyła gałęzi wydania/potentola, to jest to jedyna gałąź istniejąca w repozytorium git w przestrzeni roboczej TeamCity.

Próbowałem wykonać lokalny git fetch, aby uzyskać gałąź master, ale ponieważ lokalne repozytorium nie ma gałęzi master, to się nie powiedzie. Chociaż mógłbym dodać zdalne wskazywanie na pochodzenie (prywatne repozytorium github), co oznaczałoby, że również musiałem obsługiwać poświadczenia i wolałbym, aby TeamCity zajął się tym wszystkim dla mnie.

Moje pytanie brzmi: czy istnieje sposób na powiedzenie TeamCity, aby po prostu przeciągnęła wszystkie gałęzie do lokalnego repozytorium i do działającego repozytorium?

+1

Downvoter jakiejkolwiek przyczyny downvote? Z przyjemnością poprawię moje pytanie, jeśli to nie ma sensu. – Petrik

Odpowiedz

0

Okazuje się, że (jak na razie) nie ma sposobu, aby to zrobić ładnie w TeamCity, więc w międzyczasie problem ten został rozwiązany przez uruchomienie dodatkowego skryptu MsBuild na początku procesu budowania, który sprawdza, czy mistrz gałąź jest obecna w bieżącym (lokalnym) repozytorium i otrzymuje ją, jeśli nie jest.

Skrypt wygląda następująco:

<?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> 

W tym scenariuszu skrypt inline GitHasMasterBranch msbuild wygląda następująco:

<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's 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> 

i skrypt GitGetMasterBranch msbuild inline wygląda następująco:

<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's 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> 

Zasadniczo cały ten ostatni skrypt to magazyn curren t nazwa gałęzi, wykonaj GIT fetch, aby uzyskać wszystkie gałęzie, wykonaj GIT checkout gałęzi głównej, a następnie wykonaj GIT checkout oryginalnej gałęzi.

To nie jest najszybsze podejście, ale działa na razie.

4

Począwszy od TeamCity 10.0.4, można to zrobić poprzez dodanie parametru konfiguracyjnego teamcity.git.fetchAllHeads=trueSee here

Powiązane problemy