5

Ho due progetti impostati in CruiseControl.NET: build CI e nightly build.Come posso condividere un valore di etichetta tra più build di CruiseControl.NET?

Entrambi eseguono lo stesso script NAnt, ma con parametri diversi.

L'etichetta CruiseControl.NET (attualmente generato dal DefaultLabeler) è integrata in AssemblyInfo come la parte generazione della versione (per esempio, MajorVersion.MinorVersion.CCNET_Label.SVN_Revision).

Per versioni di versioni più coerenti, vorrei che entrambi i progetti condividessero lo stesso valore di etichetta CruiseControl.NET.

Ho esaminato gli etichettatori disponibili come parte dell'installazione di CruiseControl.NET, ma non sono riuscito a trovarne uno che faccia ciò che voglio.

Come si condivide un valore di etichetta tra più build CruiseControl.NET?
Se c'è un modo migliore per farlo, mi piacerebbe sapere.

Ho trovato un modo. Vedi la mia risposta qui sotto.

risposta

9

Non sono riuscito a trovare una soluzione esistente per fare ciò che mi serviva, così ho finito per scrivere un'etichettatrice personalizzata CruiseControl.NET.

Ecco come si fa:

  1. Creare un nuovo progetto. Verrà utilizzato come libreria di plugin da CC.NET

  2. Il nome della DLL di output deve corrispondere a * ccnet. \ *. CruiseControl.plugin *. Vai al progetto e modifica "Nome Assemblaggio" in * ccnet. < inserire il nome qui > .CruiseControl.plugin *

  3. Nel progetto, aggiungere i riferimenti ai tre gruppi presenti nella directory di installazione del server CC.NET (di default è: C: \ Program Files \ CruiseControl.NET \ server) :
    • NetReflector.dll
    • ThoughtWorks.CruiseControl.Core.dll
    • ThoughtWorks.CruiseControl.Remote.dll

  4. creare una nuova classe pubblica come questa:
     
    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. compilare il progetto e copiare la DLL nella directory di installazione del server CC.NET (di default è: C: \ Program Files \ CruiseControl.NET \ server) servizio

  6. Riavvia CC.NET di Windows

  7. Creare un file di testo per memorizzare il numero di build corrente

  8. Aggiungere la nuova etichettatrice alla definizione del progetto in ccnet.file di configurazione:
     
        <labeller type="sharedLabeller"> 
         <syncronisationFilePath>C:\Program Files\CruiseControl.NET\server\shared\buildnumber.txt</syncronisationFilePath> 
    <incrementOnFailure>false</incrementOnFailure> 
        </labeller> 
    
    


3

ho incontrato lo stesso problema, ma ho trovato che utilizzando il <stateFileLabeller> in collaborazione con il <assemblyVersionLabeller> dimostrato di essere una soluzione molto più semplice.

L'unico trucchetto sull'utilizzo di stateFileLabeller è che non è possibile specificare una directory per i file di stato in un progetto, perché CruiseControl.NET non la troverà. L'ho lasciato nella directory predefinita e funziona benissimo.

3

Ho modificato la classe Arnold reso il che rende più di una replica del 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; 
     } 
    } 
} 

Il vantaggio dovrebbe essere che è ora possibile specificare prefisso così come "incrementonfailure". Inoltre ho aggiunto una proprietà "increment" che può essere utilizzata per build di implementazione che non dovrebbero affatto incrementare il numero di build. Se si desidera modificarlo da soli, consiglierei di dare un'occhiata alle loro implementazioni: CruiseControl.NET repository folder containing labellers

+0

Nice! Votato. –