【问题标题】:Make TeamCity pull down all git branches让 TeamCity 拉下所有 git 分支
【发布时间】:2014-07-07 04:34:15
【问题描述】:

在构建服务器上,我设置了 TeamCity (8.1.1),以便在使用分支说明符的主分支、功能分支之一或拉取请求分支之一发生更改时执行构建过程:

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

我已打开构建代理选项:

teamcity.git.use.local.mirrors=true

它将存储库克隆到构建目录之外的目录中,然后从该本地存储库中提取。

构建过程需要访问 git 存储库和主分支,即使是构建功能分支之一或拉取请求分支也是如此。但是,TeamCity 只有包含本地存储库中更改的分支,从而使我的构建失败,例如当更改发生在 issue/mycoolissue 分支上时,这是 TeamCity 工作空间中 git 存储库中唯一存在的分支。

我尝试执行本地git fetch 来获取主分支,但由于本地存储库没有主分支,因此失败。虽然我可以添加一个远程指向源(一个 github 私有存储库),但这意味着我还必须处理凭据,我宁愿让 TeamCity 为我处理所有这些。

我的问题是是否有办法告诉 TeamCity 将所有分支拉入本地存储库和工作存储库?

【问题讨论】:

  • Downvoter 否决票的任何理由?如果没有意义,我很乐意改进我的问题。

标签: git teamcity


【解决方案1】:

从 TeamCity 10.0.4 开始,您可以通过添加配置参数 teamcity.git.fetchAllHeads=true See here 来做到这一点

【讨论】:

    【解决方案2】:

    事实证明,(到目前为止)在 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>
    

    本质上,最后一个脚本所做的只是存储当前分支名称,执行GIT fetch 以获取所有分支,执行主分支的GIT checkout,然后执行原始分支的GIT checkout

    这不是最快的方法,但现在可以。

    【讨论】:

      猜你喜欢
      • 2016-08-09
      • 1970-01-01
      • 2010-12-27
      • 2021-02-26
      • 2013-12-29
      • 2014-06-18
      • 2013-09-24
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多