Как получить штамп версии автоматизированной сборки CC.NET, записанный в файл Global Assembly Info и на который ссылаются несколько приложений .NET? - PullRequest
3 голосов
/ 22 марта 2011

В настоящее время я "автоматизирую сборку" нашего решения .NET (которое содержит много проектов, по крайней мере, 20. Некоторые winForms, некоторые веб-проекты, все с различными конфигурациями выпуска ... тьфу!). Я использую CruiseControl.NET (или CC.NET, whatevs) и NANT. Плюс, DOS, Powershell и несколько других волшебных бинов, в которые мы не должны вдаваться:)

Моя цель - создать метку сборки (которая, кстати, у меня уже есть полуработающая). Метка сборки состоит из номера Min / Maj и номера регистрации SVN. Это хорошо для нас, и мы счастливы с этим. Теперь мне нужно, чтобы мои проекты .NET ссылались на номер сборки, чтобы члены моей команды QA знали, с каким номером сборки они тестируют.

Моя задача обозначения версии nANT выглядит следующим образом:

<project name="updateassemblyversion" default="updateassemblyversion">
<target name="updateassemblyversion" description="generates the version number">
    <echo message="Setting the build version to ${CCNetLabel}..." />
    <attrib file="AssemblyInfo.cs" readonly="false" />
    <asminfo output="AssemblyInfo.cs" language="CSharp">
        <imports>
            <import namespace="System" />
            <import namespace="System.Reflection" />
        </imports>
        <attributes>
            <attribute type="AssemblyVersionAttribute" value="${CCNetLabel}" />
            <attribute type="AssemblyFileVersionAttribute" value="${CCNetLabel}" />
        </attributes>
    </asminfo>
    <attrib file="AssemblyInfo.cs" readonly="true" />
</target>

В любом случае, я пытаюсь установить информацию о сборке на моем сервере сборки. Я прочитал, что не рекомендуется использовать более 20 файлов AssemblyInfo.cs для записи, поэтому я вручную создал файл GlobalyAssemblyInfo.cs в качестве «элемента решения», который связан со всеми моими проектами через «Добавить .. Существующий элемент ... Добавить ссылку ". Я не думаю, что это то, что мне понадобится, так как мои версии будут выполняться на сервере сборки ...

Справедливо отметить, что моя текущая рабочая задача nANT (пример которой приведен выше), которую я тестировал, использует правильную метку версии, которая мне нужна, но эта задача неверна для моего сценария. Он создает НОВЫЙ файл AssemblyInfo.cs и ставит метку версии после того, как сборка уже скомпилирована. Я знаю, что это неправильно, но это, по сути, производит то, что мне нужно, но я не уверен, как использовать это в моем сценарии «сборки» и в том порядке, в котором я нуждаюсь. Я знаю, что это должно произойти ДО того, как произойдет компиляция, но как мне получить задачу компиляции, чтобы использовать только что сгенерированный файл? (см. вопрос № 4).

Вот что я не понимаю:

  1. Сохраняю ли я свои старые 20+ файлов AssemblyInfo.cs? Что их цель сейчас? Они мне не нужны, я делаю не верю. Я наверное не должен удалите их из файла решения, но они бесполезны, верно?
  2. Если я использую сгенерированный файл GlobalAssemblyInfo.cs, из моего NANT задача, как мне получить ссылка на него и версия для моей компиляции?
  3. Создает файл GlobalAssemblyInfo вручную (в мое решение), и ссылки на него из каждого проекта, недействительным для моего ситуация? Я думаю, что мне не нужно эти ссылки на файлы в моем решении а проекты вообще мне нужны только на моей рутине сборки на моей сборке сервер. Я уже произвожу Файл "AssemblyXYZ.cs" (из nANT) с правильной версией штампа. Разве я не должен использовать это для компиляции все мои проекты с?
  4. Если # 3 верно, как я могу реализовать это в моей конфигурации CC.NET файл (или NANT Боже?). В принципе, как мне сказать компилятору VS использовать мой новый GlobalAssemblyInfo.cs (генерируется NANT) для всех 20+ .NET проекты в моем решении?
  5. Как заставить мои проекты .NET ссылаться (внутренне) на новые генерируется, динамическая сборка номер / versionstamp? Мне нужно QA чтобы быть в состоянии увидеть это в приложении UI.

Как только это произойдет, я буду одним счастливым автостроителем :) Ура!

Ответы [ 3 ]

2 голосов
/ 25 марта 2011

1 - я бы сохранил ваши локальные файлы AssemblyInfo.cs.Некоторые из атрибутов (или могут быть) специфичны для каждой сборки, такие как Description и COM Guid.

2 - Ссылка на GlobalAssemblyInfo.cs (в корне или где-либо) из каждого проекта, как вы ужеописано.Поместите здесь общие атрибуты, такие как Продукт и Авторское право.Сборка должна взять биты от обоих и предупредить вас, если найдет дубликаты.Если вы используете задачу asminfo для генерации GlobalAssemblyInfo.cs и здесь она записывает общее значение AssemblyVersion, тогда все ваши проекты получат этот номер версии.

3 - Лично мне нравится запуск процесса сборки независимо от того,на сервере сборки или просто на коробке разработчика.Одна из причин в том, что приятно иметь возможность тестировать сборку, не запуская официальную сборку.Другим существом может быть необходимость обновить основную зависимость (версию SQL Server или любую другую) и посмотреть, все ли собирается, опять же без фактического обновления реального сервера сборки.

4 - См. Ответ 2

2 голосов
/ 09 апреля 2011

Вот как я это сделал.Это было не легко, но и не сложно.Я думаю, что я почти не верил в это, но, к счастью, это было довольно легко реализовать.

Вот окончательная версия моей задачи nANT, которую я назвал "updateassemblyinfo.build":

<?xml version="1.0"?>
<project name="updateassemblyversion" default="updateassemblyversion">
    <target name="updateassemblyversion" description="generates the version number">
        <echo message="Setting the build version to ${CCNetLabel}..." />
        <attrib file="AssemblyInfo.cs" readonly="false" />
        <asminfo output="C:\CruiseControl\ProjectFolders\MyBigBadSolution\GlobalAssemblyInfo.cs" language="CSharp">
            <imports>
                <import namespace="System" />
                <import namespace="System.Reflection" />
            </imports>
            <attributes>
                <attribute type="AssemblyVersionAttribute" value="${CCNetLabel}" />
                <attribute type="AssemblyFileVersionAttribute" value="${CCNetLabel}" />
            </attributes>
        </asminfo>
        <attrib file="GlobalAssemblyInfo.cs" readonly="true" />
    </target>
</project>

Я закончил тем, что использовал метод, проиллюстрированный Яухени Сивухой, здесь: C # Project Global AssemblyInfo

^ Я должен отметить одну вещь: ваши атрибуты сборки на уровне проекта будут конфликтоватьс вашими атрибутами сборки уровня решения.По сути, у вас будут дубликаты атрибутов, и компилятор выдаст ошибку.Просто удалите конфликтующие атрибуты из файла AssemblyInfo.cs уровня проекта и дайте файлу GlobalAssemblyInfo.cs переопределить их.Любые указанные в проекте атрибуты должны храниться в информации о сборке на уровне проекта.Информация об общей сборке попадает в файл глобальной сборки на уровне решения.Для кого-то совершенно нового это может сбить с толку.

Что касается моих 5-ти маркированных вопросов «Вот что я не понимаю», вот мои ответы:

  1. Да,Вы должны сохранить все файлы AssemblyInfo (уровня проекта).Они хранят информацию о сборке на уровне проекта.Некоторые из этих атрибутов могут не совпадать с другими проектами.Лучше хранить их в каждом конкретном проекте.
  2. Используя CruiseControl.NET и мою задачу nANT, вы просто используете тег «asminfo» и указываете элемент «output» на файл-файл GlobalAssemblyInfo.cs.файл (файл сборки уровня решения).
  3. Нет, в этой ситуации он недопустим.Использование файла глобальной сборки (уровень решения), совместно используемого несколькими проектами, очень удобно.Успешно реализовав это, я вижу, как это могло бы сбить с толку того, кто никогда не сталкивался с этим раньше.
  4. Я думаю, что важно отметить тег в ANT.Это для "Информация о сборке".Идите по цифре.
  5. Вот один ответ, на который никто не ответил, и это очень важно:

    Assembly asm = Assembly.GetExecutingAssembly();
    this.Text = asm.GetName().Version.ToString();
    
2 голосов
/ 22 марта 2011

Я боролся с той же проблемой с CC.NET ... Я закончил тем, что бросил NANT и написал собственный плагин CC.NET, который обновляет AssemblyInfo.cs для каждого проекта программно.Реализация плагина CC.NET очень проста.

using System.Collections.Generic; 
using System.IO; 
using Exortech.NetReflector; 
using ThoughtWorks.CruiseControl.Core;

namespace ccnet.AssemblyVersionUpdater.plugin {
[ReflectorType("assemblyRevisioner")]
  public class AssemblyRevisioner : ITask {
    public AssemblyRevisioner() {
    }

    [ReflectorProperty("rootFolder", Required = true)]
    public string RootFolder { get; set; }

    public void Run(IIntegrationResult result) {
        foreach (var file in GetAssemblyInfoFiles(RootFolder)) {
            var tmp = file + ".tmp";
            using (var sr = new StreamReader(file)) {
                using (var st = new StreamWriter(tmp)) {
                    string line;
                    var versionSet = false;
                    var fileVersionSet = false;
                    while ((line = sr.ReadLine()) != null) {
                        if (!versionSet && line.StartsWith("[assembly: AssemblyVersion(")) {
                            st.WriteLine("[assembly: AssemblyVersion(\"{0}\")]", result.Label);
                            versionSet = true;
                        } else {
                            if (!fileVersionSet && line.StartsWith("[assembly: AssemblyFileVersion(")) {
                                st.WriteLine("[assembly: AssemblyFileVersion(\"{0}\")]", result.Label);
                                fileVersionSet = true;
                            } else {
                                st.WriteLine(line);
                            }
                        }
                        st.Flush();
                    }
                    st.Close();
                }
                sr.Close();
            }
            File.SetAttributes(file, FileAttributes.Normal);
            File.Copy(tmp, file, true);
            File.Delete(tmp);
        }

    }

    private static IEnumerable<string> GetAssemblyInfoFiles(string b) {
        var result = new List<string>();
        var stack = new Stack<string>();
        stack.Push(b);
        while (stack.Count > 0) {
            var dir = stack.Pop();
            try {
                result.AddRange(Directory.GetFiles(dir, "AssemblyInfo.cs"));
                foreach (var dn in Directory.GetDirectories(dir)) {
                    stack.Push(dn);
                }
            } catch {
            }
        }
        return result;
    }

  } 
}

Скомпилируйте DLL и поместите ее в папку CruiseControl.NET \ server.Для установки плагина необходимо перезапустить CC.NET.Затем в соответствующем конфигурационном файле CC.NET:

<tasks>
   <assemblyRevisioner>
      <rootFolder>E:\Build\Source\Project1</rootFolder>
    </assemblyRevisioner>
     ...
</tasks>

Этот код редактирует AssemblyInfo.cs «на месте» и заменяет номер версии на один из CC.NET до того, как проект будет завершен.встроенный.Я уверен, что есть более элегантные способы увеличения номера версии, но у меня это хорошо работает.

...