5

我有兩個項目在CruiseControl.NET中建立:CI構建和每晚構建。如何在多個CruiseControl.NET版本之間共享標籤值?

它們都執行相同的NAnt腳本,但具有不同的參數。

的CruiseControl.NET標籤(目前由DefaultLabeler生成的)被嵌入到集信息作爲版本生成部(例如,MajorVersion.MinorVersion.CCNET_Label.SVN_Revision)。

對於更一致的版本控制,我希望兩個項目都共享相同的CruiseControl.NET標籤值。

我已經研究了作爲CruiseControl.NET安裝的一部分提供的標籤,但是我找不到滿足要求的標籤。

如何在多個CruiseControl.NET版本之間共享標籤值?
如果有更好的方法來做到這一點,我想知道。

我找到了一個方法。請參閱下面的答案。

回答

9

我找不到現成的解決方案來完成我所需要的工作,所以我最終編寫了一個定製的CruiseControl.NET貼標機。

下面是它是如何做的:

  1. 創建一個新項目。這將用作CC.NET的插件庫

  2. 輸出DLL的名稱需要匹配* ccnet。\ *。CruiseControl.plugin *。轉至項目 屬性並將「程序集名稱」更改爲* ccnet。 <插入名稱這裏> .CruiseControl.plugin *

  3. 在你的項目中,添加在CC.NET服務器安裝目錄中找到三個組件引用(默認爲C:\ Program Files文件\ CruiseControl.NET \服務器) :
    • NetReflector.dll
    • ThoughtWorks.CruiseControl.Core.dll
    • ThoughtWorks.CruiseControl.Remote.dll

  4. 創建一個新的公共類如這樣:
     
    using ThoughtWorks.CruiseControl.Core; 
    using ThoughtWorks.CruiseControl.Remote; 
    
    // this is the labeller name that will be used in ccnet.config 
    [ReflectorType("customLabeller")] 
    public class CustomLabeller : ILabeller 
    { 
    [ReflectorProperty("syncronisationFilePath", Required = true)] 
    public string SyncronisationFilePath { get; set; } 
    
    #region ILabeller Members 
    
    public string Generate(IIntegrationResult previousResult) 
    { 
        if (ShouldIncrementLabel(previousResult)) 
        return IncrementLabel(); 
    
        if (previousResult.Status == IntegrationStatus.Unknown) 
        return "0"; 
    
        return previousResult.Label; 
    } 
    
    public void Run(IIntegrationResult result) 
    { 
        result.Label = Generate(result); 
    } 
    
    #endregion 
    
    private string IncrementLabel() 
    { 
        if(!File.Exists(SyncronisationFilePath)) 
        return "0"; 
    
        using (FileStream fileStream = File.Open(SyncronisationFilePath, 
         FileMode.OpenOrCreate, 
         FileAccess.ReadWrite, 
         FileShare.None)) 
        { 
        // read last build number from file 
        var bytes = new byte[fileStream.Length]; 
        fileStream.Read(bytes, 0, bytes.Length); 
    
        string rawBuildNumber = Encoding.ASCII.GetString(bytes); 
    
        // parse last build number 
        int previousBuildNumber = int.Parse(rawBuildNumber); 
        int newBuildNumber = previousBuildNumber + 1; 
    
        // increment build number and write back to file 
        bytes = Encoding.ASCII.GetBytes(newBuildNumber.ToString()); 
    
        fileStream.Seek(0, SeekOrigin.Begin); 
        fileStream.Write(bytes, 0, bytes.Length); 
    
        return newBuildNumber.ToString(); 
        } 
    } 
    
    private static bool ShouldIncrementLabel(IIntegrationResult previousResult) 
    { 
        return (previousResult.Status == IntegrationStatus.Success || 
        previousResult.Status == IntegrationStatus.Unknown) 
    } 
    } 
    


  5. 編譯您的項目和DLL複製到CC.NET服務器的安裝目錄(默認爲C:\ Program Files文件\ CruiseControl.NET \服務器)

  6. CC.NET重新啓動Windows服務

  7. 創建一個文本文件來存儲當前的版本號

  8. 將ccbel中的新標籤添加到您的項目定義中。配置文件:
     
        <labeller type="sharedLabeller"> 
         <syncronisationFilePath>C:\Program Files\CruiseControl.NET\server\shared\buildnumber.txt</syncronisationFilePath> 
    <incrementOnFailure>false</incrementOnFailure> 
        </labeller> 
    
    


3

我碰到了同樣的問題,但我發現,在證明了<assemblyVersionLabeller>結合使用<stateFileLabeller>成爲一個更簡單的解決方案。

關於使用stateFileLabeller的唯一問題是,您無法爲項目中的狀態文件指定目錄,因爲CruiseControl.NET無法找到它。我將它放在默認目錄中,並且效果很好。

3

我修改更多的defaultlabeller的副本的類阿諾德造使其:

using System.IO; 
using System.Text; 

using Exortech.NetReflector; 
using ThoughtWorks.CruiseControl.Core; 
using ThoughtWorks.CruiseControl.Remote; 

// This namespace could be altered and several classes could be put into the same if you'd want to combine several plugins in one dll 
namespace ccnet.SharedLabeller.CruiseControl.plugin 
{ 
    [ReflectorType("sharedLabeller")] 
    public class SharedLabeller : ILabeller 
    { 
     /// <summary> 
     /// The path where the file that holds the shared label should be located 
     /// </summary> 
     /// <default>none</default> 
     [ReflectorProperty("sharedLabelFilePath", Required = true)] 
     public string SharedLabelFilePath { get; set; } 

     /// <summary> 
     /// Any string to be put in front of all labels. 
     /// </summary> 
     [ReflectorProperty("prefix", Required = false)] 
     public string Prefix { get; set; } 

     /// <summary> 
     /// If true, the label will be incremented even if the build fails. Otherwise it will only be incremented if the build succeeds. 
     /// </summary> 
     [ReflectorProperty("incrementOnFailure", Required = false)] 
     public bool IncrementOnFailure { get; set; } 

     /// <summary> 
     /// If false, the label will never be incremented when this project is builded. This is usefull for deployment builds that 
     /// should use the last successfull of two or more builds 
     /// </summary> 
     [ReflectorProperty("increment", Required = false)] 
     public bool Increment { get; set; } 

     /// <summary> 
     /// Allows you to set the initial build number. 
     /// This will only be used when on the first build of a project, meaning that when you change this value, 
     /// you'll have to stop the CCNet service and delete the state file. 
     /// </summary> 
     /// <default>0</default> 
     [ReflectorProperty("initialBuildLabel", Required = false)] 
     public int InitialBuildLabel { get; set; } 

     public SharedLabeller() 
     { 
      IncrementOnFailure = false; 
      Increment = true; 
      InitialBuildLabel = 0; 
     } 

     #region ILabeller Members 

     public string Generate(IIntegrationResult integrationResult) 
     { 
      if (ShouldIncrementLabel(integrationResult.LastIntegration)) 
      { 
       return Prefix + this.GetLabel(); 
      } 
      else 
      { 
       return integrationResult.LastIntegration.Label; 
      } 
     } 

     public void Run(IIntegrationResult integrationResult) 
     { 
      integrationResult.Label = Generate(integrationResult); 
     } 

     #endregion 

     /// <summary> 
     /// Get and increments the label, unless increment is false then it only gets the label 
     /// </summary> 
     /// <returns></returns> 
     private string GetLabel() 
     { 
      ThoughtWorks.CruiseControl.Core.Util.Log.Debug("About to read label file. Filename: {0}", SharedLabelFilePath); 
      using (FileStream fileStream = File.Open(this.SharedLabelFilePath, 
        FileMode.OpenOrCreate, 
        FileAccess.ReadWrite, 
        FileShare.None)) 
      { 
       // Read last build number from file 
       var bytes = new byte[fileStream.Length]; 
       fileStream.Read(bytes, 0, bytes.Length); 

       string rawBuildNumber = Encoding.UTF8.GetString(bytes); 

       // Parse last build number 
       int previousBuildNumber; 
       if (!int.TryParse(rawBuildNumber, out previousBuildNumber)) 
       { 
        previousBuildNumber = InitialBuildLabel - 1; 
       } 

       if (!Increment) 
       { 
        return previousBuildNumber.ToString(); 
       } 

       int newBuildNumber = previousBuildNumber + 1; 

       // Increment build number and write back to file 
       bytes = Encoding.UTF8.GetBytes(newBuildNumber.ToString()); 

       fileStream.Seek(0, SeekOrigin.Begin); 
       fileStream.Write(bytes, 0, bytes.Length); 

       return newBuildNumber.ToString(); 
      } 
     } 

     private bool ShouldIncrementLabel(IntegrationSummary integrationSummary) 
     { 
      return integrationSummary == null || integrationSummary.Status == IntegrationStatus.Success || IncrementOnFailure; 
     } 
    } 
} 

的好處應該是你現在可以指定前綴以及「incrementonfailure」。此外,我還添加了一個「增量」屬性,可用於部署構建,不應增加構建編號。如果你想自己修改它,我會建議看看他們的實現: CruiseControl.NET repository folder containing labellers

+0

不錯!投了票。 – 2013-06-01 03:08:55

相關問題