Как разделить значение метки между несколькими сборками CruiseControl.NET? - PullRequest
5 голосов
/ 10 ноября 2009

В CruiseControl.NET настроены два проекта: сборка CI и ночная сборка.

Оба они выполняют один и тот же скрипт NAnt, но с разными параметрами.

Метка CruiseControl.NET (в настоящее время генерируется DefaultLabeler ) встраивается в AssemblyInfo как часть сборки версии (например, MajorVersion.MinorVersion.CCNET_Label.SVN_Revision ) .

Для более согласованного управления версиями я бы хотел, чтобы оба проекта имели одинаковое значение метки CruiseControl.NET.

Я исследовал ярлыки, которые доступны как часть установки CruiseControl.NET, но я не смог найти тот, который делает то, что я хочу.

Как разделить значение метки между несколькими сборками CruiseControl.NET?
Если есть лучший способ сделать это, я хотел бы знать.

Я нашел способ. Смотрите мой ответ ниже.

Ответы [ 3 ]

9 голосов
/ 10 ноября 2009

Я не смог найти существующее решение, которое бы делало то, что мне нужно, поэтому я в итоге написал собственный ярлык CruiseControl.NET.

Вот как это делается:

  1. Создать новый проект. Это будет использоваться CC.NET как библиотека плагинов.

  2. Имя выходной DLL должно совпадать с * ccnet. \ *. CruiseControl.plugin *. Перейти к проекту Свойства и измените "Имя сборки" на * ccnet. <введите имя здесь> .CruiseControl.plugin *

  3. В своем проекте добавьте ссылки на три сборки, найденные в каталоге установки сервера CC.NET (по умолчанию: C: \ Program Files \ CruiseControl.NET \ server):
    • 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 \ server)

  6. Перезапустите службу Windows CC.NET

  7. Создать текстовый файл для хранения текущего номера сборки

  8. Добавьте новый ярлык к вашему определению проекта в файле ccnet.config:
        <labeller type="sharedLabeller">
            <syncronisationFilePath>C:\Program Files\CruiseControl.NET\server\shared\buildnumber.txt</syncronisationFilePath>
    <incrementOnFailure>false</incrementOnFailure>
        </labeller>
    
    


3 голосов
/ 16 мая 2013

Я изменил класс, который сделал Арнольд, сделав его более точной копией маркировки по умолчанию:

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". Также я добавил свойство «increment», которое можно использовать для сборок развертывания, которые вообще не должны увеличивать номер сборки. Если вы хотите изменить его самостоятельно, я бы посоветовал взглянуть на их реализации: Папка репозитория CruiseControl.NET, содержащая метки

3 голосов
/ 23 марта 2010

Я столкнулся с той же проблемой, но обнаружил, что использование <stateFileLabeller> в сочетании с <assemblyVersionLabeller> оказалось гораздо более простым решением.

Единственный недостаток использования stateFileLabeller заключается в том, что вы не можете указать каталог для файлов состояния в проекте, потому что CruiseControl.NET не найдет его. Я оставил его в каталоге по умолчанию, и он прекрасно работает.

...