Как я могу автоматически увеличить версию сборки C# через нашу платформу CI (Hudson)?
Я и моя группа ужасны при увеличении номеров версий сборки, и мы часто отправляем сборки с версиями 1.0.0.0. Очевидно, что это вызывает много головных болей.
мы получаем намного лучше с нашими практиками через наш CI платформа и я действительно хотел бы настроить его на автоматическое увеличение значений в пределах assemblyinfo.cs
файл, Чтобы версии наших сборок автоматически обновлялись с изменениями кода в этой сборке.
Я ранее настройка (прежде чем мы нашли Гудзон) способ увеличить значение через любой msbuild
или в командной строке (не помню), но с Hudson, который будет обновлять репозиторий SVN и запускать другую сборку. Это приведет к медленному бесконечному циклу, поскольку Хадсон опрашивает SVN каждый час.
имеет ли Хадсон увеличить номер версии плохая идея? Каков был бы альтернативный способ сделать это?
В идеале, мои критерии для решения будет один что:
- увеличивает номер сборки в
assemblyinfo.cs
перед сборкой - только увеличивает номер сборки в сборках, которые были изменены. Это может быть невозможно, так как Hudson стирает папку проекта каждый раз, когда он выполняет сборку
- фиксирует измененный assemblyinfo.cs в репозиторий кода (в настоящее время VisualSVN)
- не вызывает Гудзон, чтобы вызвать новую сборку в следующий раз, когда он высматривает изменения
работая над этим в моей голове, я мог бы легко придумать решение для большинства из них с помощью пакетных файлов / команд, но все мои идеи заставят Hudson запускать новую сборку при следующем сканировании. Я не ищу кого-то, чтобы сделать все для меня, просто укажите мне в правильном направлении, возможно, технику, чтобы заставить Хадсона игнорировать определенные SVN-коммиты и т. д.
все, что я нашел до сих пор это просто статья, объясняющая, как получить версию число автоматически увеличивается, ничто не учитывает платформу CI, которая может быть развернута в бесконечный цикл.
12 ответов:
простой альтернативой является позволить среде C# увеличить версию сборки для вас, установив атрибут version в
major.minor.*
(как описано в шаблоне файла AssemblyInfo.)вы можете искать более комплексное решение, хотя.
EDIT (ответ на вопрос в комментарии):
С
AssemblyInfo.cs
:// Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")]
вот что я сделал, для штамповки атрибута AssemblyFileVersion.
удалил AssemblyFileVersion из AssemblyInfo.cs
Добавить новый, пустой файл с именем AssemblyFileInfo.cs к проекту.
установить задачи сообщества MSBuild набор инструментов на машине сборки hudson или как зависимость NuGet в вашем проекте.
отредактируйте файл проекта (csproj), это просто файл msbuild, и добавьте следующий.
где-то там будет
<PropertyGroup>
С указанием версии. Измените это так, чтобы он читал, например<Major>1</Major> <Minor>0</Minor> <!--Hudson sets BUILD_NUMBER and SVN_REVISION --> <Build>$(BUILD_NUMBER)</Build> <Revision>$(SVN_REVISION)</Revision>
Hudson предоставляет те переменные env, которые вы видите там, когда проект построен на hudson (предполагая, что он извлекается из subversion).
В нижней части файла проекта, добавить
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')" /> <Target Name="BeforeBuild" Condition="Exists('$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets')"> <Message Text="Version: $(Major).$(Minor).$(Build).$(Revision)" /> <AssemblyInfo CodeLanguage="CS" OutputFile="AssemblyFileInfo.cs" AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyConfiguration="$(Configuration)" Condition="$(Revision) != '' " /> </Target>
Это использует MSBuildCommunityTasks для создания AssemblyFileVersion.cs для включения атрибута AssemblyFileVersion перед построением проекта. Вы можете сделать это для любого/всех атрибутов версии, если хотите.
в результате всякий раз, когда вы выпускаете сборку hudson, результирующая сборка получает AssemblyFileVersion 1.0.HUDSON_BUILD_NR.SVN_REVISION например 1.0.6.2632 , что означает 6'th build # в hudson, buit из версии 2632 subversion.
вот элегантное решение, которое требует небольшой предварительной работы при добавлении нового проекта, но обрабатывает процесс очень легко.
идея заключается в том, что каждый проект ссылается на файл решения, который содержит только информацию о версии сборки. Таким образом, ваш процесс сборки должен обновлять только один файл, и все версии сборки извлекаются из одного файла при компиляции.
действия:
- добавьте класс в файл решения *.cs-файл, я назвал min Поделились своими вещами.cs
- удалите всю информацию cs из этого нового файла
- вырезать информацию о сборке из файла AssemblyInfo: [собрание: AssemblyVersion("1.0.0.0")] [собрание: AssemblyFileVersion("1.0.0.0")]
- добавить оператор " использование системы.Отражение; " в файл, а затем вставьте данные в новый файл cs (ex SharedAssemblyProperties.cs)
- добавить существующий элемент в проект (подождите... читайте дальше перед добавлением файл)
- Выберите файл и прежде чем нажать кнопку Добавить, нажмите на стрелку рядом с кнопкой Добавить и выберите "Добавить ссылку".
- повторите шаги 5 и 6 для всех существующих и новых проектов в решении
когда вы добавляете файл в качестве ссылки, он сохраняет данные в файле проекта и при компиляции извлекает информацию о версии сборки из этого файла.
в системе управления версиями вы добавляете файл bat или файл сценария, который просто увеличивает Поделились своими вещами.файл CS и все ваши проекты будут обновлять информацию о сборке из этого файла.
Hudson можно настроить для игнорирования изменений в определенных путях и файлах, чтобы он не запрашивал новую сборку.
на странице конфигурация задания в разделе Управление Исходным Кодом, нажмите кнопку Advanced. В Исключенные Регионы поле Введите одно или несколько регулярных выражений для сопоставления исключений.
например, чтобы игнорировать изменения версия.свойства
.NET делает это за вас. В файле AssemblyInfo.cs-файл, установите версию сборки в major.незначительный.* (например: 1.0.*).
при создании проекта версия генерируется автоматически.
номера сборки и ревизии генерируются на основе даты, используя эпоху unix, я считаю. Сборка основана на текущем дне, а ревизия основана на количестве секунд с полуночи.
Я никогда не видел, что 1.0.* функция работы в VS2005 или VS2008. Есть ли что-то, что нужно сделать, чтобы установить VS для увеличения значений?
Если AssemblyInfo.cs жестко закодирован с 1.0.* , тогда где хранятся реальные сборки / ревизии?
после установки 1.0.* в AssemblyInfo мы не можем использовать следующий оператор, потому что ProductVersion теперь имеет недопустимое значение - он использует 1.0.* а не значение, присвоенное VS:
Version version = new Version(Application.ProductVersion);
вздох - это кажется, это одна из тех вещей, о которых все спрашивают, но почему-то никогда нет твердого ответа. Несколько лет назад я видел решения для генерации номера редакции и сохранения его в AssemblyInfo как часть процесса после сборки. Я надеялся, что такой танец не потребуется для VS2008. Может быть, VS2010?
Я предполагаю, что можно сделать с помощью текст шаблона где вы создаете атрибуты сборки в вопросе на лету из среды, как AssemblyVersion.tt делает ниже.
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #> <# var build = Environment.GetEnvironmentVariable("BUILD_NUMBER"); build = build == null ? "0" : int.Parse(build).ToString(); var revision = Environment.GetEnvironmentVariable("SVN_REVISION"); revision = revision == null ? "0" : int.Parse(revision).ToString(); #> using System.Reflection; [assembly: AssemblyVersion("1.0.<#=build#>.<#=revision#>")] [assembly: AssemblyFileVersion("1.0.<#=build#>.<#=revision#>")]
как продолжение ответа микрофоны, я хотел бы добавить, что против + визуальная студия визуализации и моделирования СДК должен быть установлен для этого, чтобы работать, и вы должны изменить файл проекта, а также. Следует также упомянуть, что я использую Jenkins в качестве сервера сборки, работающего на сервере windows 2008 R2 с модулем версии, где я получаю BUILD_NUMBER.
мой текстовый файл шаблона version.tt выглядит так
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #> <# var build = Environment.GetEnvironmentVariable("BUILD_NUMBER"); build = build == null ? "0" : int.Parse(build).ToString(); var revision = Environment.GetEnvironmentVariable("_BuildVersion"); revision = revision == null ? "5.0.0.0" : revision; #> using System.Reflection; [assembly: AssemblyVersion("<#=revision#>")] [assembly: AssemblyFileVersion("<#=revision#>")]
у меня есть следующее В собственности Группы
<PropertyGroup> <TransformOnBuild>true</TransformOnBuild> <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles> <TransformOutOfDateOnly>false</TransformOutOfDateOnly> </PropertyGroup>
после импорта Microsoft.CSharp.цели, у меня есть это (в зависимости от того, где вы устанавливаете VS
<Import Project="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
на моем сервере сборки у меня есть следующий скрипт для запуска преобразования текста перед фактической сборкой, чтобы получить последний номер набора изменений на TFS
set _Path="C:\Build_Source\foo" pushd %_Path% "%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe" history . /r /noprompt /stopafter:1 /Version:W > bar FOR /f "tokens=1" %%foo in ('findstr /R "^[0-9][0-9]*" bar') do set _BuildVersion=5.0.%BUILD_NUMBER%.%%foo del bar popd echo %BUILD_NUMBER% echo %_BuildVersion% cd C:\Program Files (x86)\Jenkins\jobs\MyJob\workspace\MyProject MSBuild MyProject.csproj /t:TransformAll ... <rest of bld script>
таким образом, я могу отслеживать сборки и наборы изменений, поэтому, если я ничего не проверял с момента последней сборки, последняя цифра не должна меняться, однако я мог бы сделать изменения в процессе сборки, следовательно, необходимость во втором последнем номере. Конечно, если вы сделаете несколько возвратов перед сборкой, вы получите только последнее изменение, отраженное в версии. Я думаю, вы могли бы объединить это требуется.
Я уверен, что вы можете сделать что-то более причудливое и вызвать TFS непосредственно из шаблона tt, однако это работает для меня.
затем я могу получить свою версию во время выполнения, как это
Assembly assembly = Assembly.GetExecutingAssembly(); FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); return fvi.FileVersion;
мое решение не требует добавления внешних инструментов или языков сценариев-это в значительной степени гарантирует работу на вашей машине сборки. Я решаю эту проблему в нескольких частях. Во-первых, я создал сборку.BAT-файл, который преобразует параметр Jenkins BUILD_NUMBER в переменную среды. Я использую функцию Дженкинса "выполнить пакетную команду Windows" для запуска пакетного файла сборки, введя следующую информацию для сборки Дженкинса:
./build.bat --build_id %BUILD_ID% -build_number %BUILD_NUMBER%
в сборке окружающая среда, у меня есть сборка.bat файл, который начинается следующим образом:
rem build.bat set BUILD_ID=Unknown set BUILD_NUMBER=0 :parse_command_line IF NOT "%1"=="" ( IF "%1"=="-build_id" ( SET BUILD_ID=%2 SHIFT ) IF "%1"=="-build_number" ( SET BUILD_NUMBER=%2 SHIFT ) SHIFT GOTO :parse_command_line ) REM your build continues with the environmental variables set MSBUILD.EXE YourProject.sln
как только я это сделал, я щелкнул правой кнопкой мыши на проекте, который будет построен в области обозревателя решений Visual Studio и выбранных свойствах, выберите события сборки и введите следующую информацию в качестве командной строки события предварительной сборки, которая автоматически создает a .cs-файл, содержащий информацию о номере сборки на основе текущих параметров переменной среды:
set VERSION_FILE=$(ProjectDir)\Properties\VersionInfo.cs if !%BUILD_NUMBER%==! goto no_buildnumber_set goto buildnumber_set :no_buildnumber_set set BUILD_NUMBER=0 :buildnumber_set if not exist %VERSION_FILE% goto no_version_file del /q %VERSION_FILE% :no_version_file echo using System.Reflection; >> %VERSION_FILE% echo using System.Runtime.CompilerServices; >> %VERSION_FILE% echo using System.Runtime.InteropServices; >> %VERSION_FILE% echo [assembly: AssemblyVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE% echo [assembly: AssemblyFileVersion("0.0.%BUILD_NUMBER%.1")] >> %VERSION_FILE%
возможно, вам придется приспособиться к вашей сборке вкус. Я строю проект вручную один раз, чтобы создать начальную версию.cs-файл в каталоге свойств основного проекта. Наконец, я вручную включаю версию.cs-файл в решение Visual Studio, перетащив его на панель Обозреватель решений под вкладкой свойства для этого проекта. В будущих сборках Visual Studio затем читает это .cs-файл во время сборки Jenkins и получает из него правильную информацию о номере сборки.
Итак, у нас есть проект решения, который содержит несколько проектов, сборок с разными номерами версий.
после изучения нескольких из вышеперечисленных методов я только что реализовал шаг сборки для запуска сценария Powershell, который выполняет поиск и замену в AssemblyInfo.cs-файл. Я все еще использую 1.0.* номер версии в системе управления версиями, и Дженкинс просто вручную обновляет номер версии перед запуском msbuild.
dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyVersion\("(.*)\.\*"\)', "`[assembly: AssemblyVersion(`"`.$build`")"} | Out-File $_ -Encoding "UTF8" } dir **/Properties/AssemblyInfo.cs | %{ (cat $_) | %{$_ -replace '^(\s*)\[assembly: AssemblyFileVersion\("(.*)\.\*"\)', "`[assembly: AssemblyFileVersion(`"`.$build`")"} | Out-File $_ -Encoding "UTF8" }
Я добавил-кодировка "UTF8" вариант, потому что git начал лечение.cs-файл в виде двоичных файлов, Если я этого не сделал. конечно, это не имело значения, так как я никогда не фиксировал результат; он просто появился, когда я тестировал.
наша среда CI уже имеет возможность связать сборку Jenkins с конкретным git commit (спасибо Stash plugin!), поэтому я не волнуюсь, что нет git commit с номером версии, прикрепленным к нему.
Это более простой механизм. Он просто включает в себя добавление шага сборки задачи пакетной команды Windows перед шагом MSBuild и использование простой программы поиска и замены (FART).
Пакетный Шаг
fart --svn -r AssemblyInfo.cs "[assembly: AssemblyVersion(\"1.0.0.0\")]" "[assembly: AssemblyVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]" if %ERRORLEVEL%==0 exit /b 1 fart --svn -r AssemblyInfo.cs "[assembly: AssemblyFileVersion(\"1.0.0.0\")]" "[assembly: AssemblyFileVersion(\"1.0.%BUILD_NUMBER%.%SVN_REVISION%\")]" if %ERRORLEVEL%==0 exit /b 1 exit /b 0
Если вы используете систему управления версиями, отличную от svn, измените параметр --svn на соответствующий для вашей среды scm.
Я решил использовать несколько методов, используя предварительно построенный сценарий Powershell(https://gist.github.com/bradjolicoeur/e77c508089aea6614af3) для увеличения на каждой успешной сборки, то в глобальном.асакс я собираюсь что-то вроде этого:
// We are using debug configuration, so increment our builds. if (System.Diagnostics.Debugger.IsAttached) { string version = System.Reflection.Assembly.GetExecutingAssembly() .GetName() .Version .ToString(); var psi = new ProcessStartInfo(@"svn", "commit -m \"Version: " + version + "\n \""); psi.WorkingDirectory = @"C:\CI\Projects\myproject"; Process.Start(psi); }
Я все еще думаю, что весь процесс слишком сложен, и я собираюсь изучить более эффективный метод достижения того же результата. Я хотел это в основном на прохождения версии в SVN, а затем в Дженкин без много дополнительных инструментов.