2014-05-19 71 views
6

在構建服務器上,我已經設置了TeamCity(8.1.1),以便它在執行構建過程時,如果主服務器,其中一個功能分支或其中一個功能分支使用分支符請求分支:讓TeamCity下拉所有git分支

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

我已經打開生成代理選項:

teamcity.git.use.local.mirrors=true 

哪些克隆build目錄之外的目錄庫,然後從本地倉庫拉。

構建過程需要訪問git存儲庫和主分支,即使是構建其中一個功能分支或拉取請求分支。然而,TeamCity只有包含本地存儲庫中的改變的分支,從而使我的構建失敗,例如,當更改發生在issue/mycoolissue分支上時,那麼這是TeamCity工作空間中git存儲庫中唯一存在的分支。

我已經嘗試執行本地git fetch獲取主分支,但因爲本地存儲庫沒有主分支,這將失敗。雖然我可以添加遠程指向源(github私有存儲庫),這意味着我也必須處理憑據,我寧願讓TeamCity爲我處理所有這些。

我的問題是,是否有辦法告訴TeamCity只需將所有分支拉入本地存儲庫和工作存儲庫?

+1

Downvoter任何理由downvote這樣做呢?如果沒有意義,我會很樂意改進我的問題。 – Petrik

回答

0

事實證明(到目前爲止)在TeamCity中沒有辦法很好地做到這一點,因此同時通過在構建過程開始時運行額外的MsBuild腳本來解決該問題,該腳本驗證主分支存在於當前(本地)存儲庫中,如果不存在則獲取它。

腳本的樣子:

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

在這個腳本的GitHasMasterBranch的MSBuild聯腳本的樣子:

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

而且GitGetMasterBranch的MSBuild聯腳本的樣子:

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

基本上所有這最後的腳本確實是存儲curren t分支名稱,執行GIT fetch以獲取所有分支,執行主分支的GIT checkout,然後執行原始分支的GIT checkout

這不是最快的方法,但它現在工作。

4

從TeamCity的10.0.4開始,您可以通過增加配置參數teamcity.git.fetchAllHeads=trueSee here