Сервер сборки: лучшие практики по управлению сторонними компонентами?

Я поддерживаю довольно большое устаревшее приложение. Исходное дерево - настоящий беспорядок. Я пытаюсь настроить сервер сборки.

В дереве исходников есть сторонний компонент с источниками (также в пути к проекту). Эти компоненты также установлены в среде IDE.

Мой вопрос: как управлять этими компонентами?

Я думал обойтись так:

  • Установите IDE на сервер сборки
  • Установите все сторонние компоненты
  • Удалите источники компонентов из дерева источников проекта (и сохраните их в корне проекта в отдельной папке, каждая из которых заархивирована)
  • Каждый раз, когда нам нужно настроить (или отладить) сторонний компонент, мы пересобираем пакет и переустанавливаем его в IDE сервера сборки (и на каждой рабочей станции разработчика)

В чем разница между наличием компонентов, установленных в IDE, и наличием источников в пути включения? Как линкер справится с этим делом?

4 ответа

Решение

Мы настроили наши ежедневные сборки, используя простые командные файлы.

  1. Каждый проект (.dpr) имеет связанный файл Build.cmd.
  2. Все файлы Build.cmd вызываются из нашего основного файла BuildServerRun.cmd.

Файл BuildServerRun.cmd заботится о

  1. Удаление всего исходного дерева на сервере сборки.
  2. Получение последней версии из нашего репозитория контроля версий.
  3. Вызовите каждый Build.cmd и передайте вывод в файл.
  4. Пошлите результаты всем разработчикам.

Все пути к внешним компонентам настраиваются в файле dcc32.cfg.

..    
-u"c:\Program files\Developer Express Inc\ExpressInplaceEditors\Delphi 5\Lib"
-u"c:\Program files\Developer Express Inc\ExpressQuantumGrid\Delphi 5\Lib"
..
-r"c:\Program Files\Borland\Delphi5\Lib"
-r"C:\Program Files\jvcl\jvcl\resources"
..
-i"C:\Program Files\jvcl\jvcl\run"
-i"C:\Program Files\jvcl\jcl\source"

Пример Build.cmd.

Примечание: у нас есть политика для компиляции в bin\dcu, exe в bin, отсюда и директивы -N, -E.

@echo on
dcc32speed -B -Q -W -H -Nbin\dcu -Ebin BpABA.dpr
@echo off

Пример снятого BuildServerRun.cmd

SET %Drive%=E:

:BuildServer
REM *************************************************
REM     Clear files
REM *************************************************
ECHO. > "%Temp%\BuildLieven.txt"
ECHO. > "%Temp%\TestRunLieven.txt"

REM *************************************************
REM     Set start time
REM *************************************************
echo | TIME | FIND "Huidige tijd" > "%Temp%\ResultLieven.txt"

REM *************************************************
REM     Get latest versions
REM *************************************************
IF %LatestVersion%==1 CALL %Drive%\buildserver\latestversion.cmd
ECHO "Latest versions opgehaald" >> "%Temp%\ResultLieven.txt"

REM *************************************************
REM     Build projects
REM *************************************************
CD %Drive%\Projects\

ECHO ***************************************************************** >> "%Temp%\BuildLieven.txt"
ECHO BpABA >> "%Temp%\BuildLieven.txt"
ECHO ***************************************************************** >> "%Temp%\BuildLieven.txt"
CD %Drive%\Projects\BPABA\production
ECHO Building BPABA\production
CALL Build.cmd >> "%Temp%\BuildLieven.txt"
CD %Drive%\Projects\BPABA\test
ECHO Building BPABA\test
CALL Build.cmd >> "%Temp%\BuildLieven.txt"
CD %Drive%\Projects\BPABA\test\dunit
ECHO Building BPABA\test\dunit
CALL Build.cmd >> "%Temp%\BuildLieven.txt"
ECHO BPABATests >> "%Temp%\TestRunLieven.txt"
ECHO Running BPABATests
CALL bin\BPABATests >> "%Temp%\TestRunLieven.txt"
CD %Drive%\Projects
ECHO. >> "%Temp%\BuildLieven.txt"
ECHO. >> "%Temp%\BuildLieven.txt"
ECHO. >> "%Temp%\BuildLieven.txt"

REM *****************************************************************
REM     Gather (Fatal)Errors/Hints/Warnings & Failures
REM *****************************************************************
ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
ECHO (Fatal)Errors/Hints/Warnings en Failures >> "%Temp%\ResultLieven.txt"
ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
ECHO Fatal errors during build >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND /c "Fatal:" >> "%Temp%\ResultLieven.txt"


ECHO Errors during build >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND /c "Error:" >> "%Temp%\ResultLieven.txt"

ECHO Warnings during build >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND /c "Warning:" >> "%Temp%\ResultLieven.txt"

ECHO Hints during build >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND /c "Hint:" >> "%Temp%\ResultLieven.txt"

ECHO Failures during test >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\TestRunLieven.txt" | FIND /c "Failures:" >> "%Temp%\ResultLieven.txt"
ECHO. >> "%Temp%\ResultLieven.txt"

ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
ECHO Controle #Projecten = #Compiles >> "%Temp%\ResultLieven.txt"
ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
ECHO #Projecten >> "%Temp%\ResultLieven.txt"
TYPE "%Drive%\buildserver\buildserverrun.cmd" | FIND /i "cmd >> " | FIND /i "Lieven" | FIND /i /v /c "FIND /i /v /c" >> "%Temp%\ResultLieven.txt"
ECHO #Compiles >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\buildLieven.txt" | FIND /i /c "dcc32" >> "%Temp%\ResultLieven.txt"
ECHO #Tests expected to run >> "%Temp%\ResultLieven.txt"
TYPE "%Drive%\buildserver\buildserverrun.cmd" | FIND /i "TestRunLieven" | FIND /i "CALL" | FIND /i /v /c "FIND /i /v /c" >> "%Temp%\ResultLieven.txt"
ECHO #Tests actually run >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\TestRunLieven.txt" | FIND /i /c "DUnit / Testing" >> "%Temp%\ResultLieven.txt"
ECHO. >> "%Temp%\ResultLieven.txt"
ECHO. >> "%Temp%\ResultLieven.txt"

ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
ECHO Detail (Fatal)Errors/Hints/Warnings en Failures >> "%Temp%\ResultLieven.txt"
ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND "Fatal:" >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND "Error:" >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND "Warning:" >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\BuildLieven.txt" | FIND "Hint:" >> "%Temp%\ResultLieven.txt"
TYPE "%Temp%\TestRunLieven.txt" | FIND "Failures:" >> "%Temp%\ResultLieven.txt"

REM *************************************************
REM     Set stop time
REM *************************************************
ECHO | TIME | FIND "Huidige tijd" >> "%Temp%\ResultLieven.txt"

REM *************************************************
REM     Send results
REM *************************************************
CALL %drive%\buildserver\Blat.cmd

Мой ответ более общий, чем ответ Ливена, специфичный для Дельфи. Я написал это вскоре после вопроса, но перед отправкой отправился к сотруднику;)

Я отказываюсь устанавливать любую IDE на наш основной агент сборки Windows. Звучит как кошмар для меня. Движок MSBuild хорошо обрабатывает все сценарии сборки, и, кроме.NET, вам просто нужно установить Windows SDK. Или вы можете использовать NAnt и даже CMake, что угодно. Просто не устанавливайте IDE. На сборочных серверах не весело.

Теперь вы пометили это как Delphi. Я не знаю, насколько хорошо он там работает, но, как писал Ливен, Delphi поставляется с компилятором командной строки. У меня просто нет опыта работы со сторонними компонентами, но я думаю, что Delphi поддерживает MSBuild в последней версии.

Я также не уверен, является ли полезным включение сторонних компонентов в управление версиями из-за занимаемого ими места - хотя вы также можете разместить их где-то еще и включить их как внешние, что делает его намного меньше, но также накладывает Проблема в том, что обновление компонентов для одного приложения приведет к их обновлению для всех - так что вам лучше иметь хорошие интеграционные тесты. Но в этом и заключается смысл сервера сборки.

Кроме того, всегда полезно оформить заказ и иметь все компоненты, необходимые для создания приложения. Вам не нужно устанавливать компоненты в IDE, если они были сделаны хорошо. В зависимости от того, какие это компоненты, во многих случаях вам даже не нужно устанавливать их на машины разработчика. Например, многие компоненты.NET доступны в конструкторе, когда вы добавляете на них ссылку. И лицензирование обычно не более, чем "поместите файл лицензии в один каталог". Ну, так и должно быть, по крайней мере. Если это не так, как сегодня работает в Delphi, это, вероятно, одна из причин, по которой Delphi выходит. Кроме хлопот Borland/Inprise/DevCo/Codegear/Embarcadero.

Подобная ситуация здесь, к счастью, началась не с большой неразберихи. Это правда, что настоящая проблема заключается в конфигурации IDE, которая должна указывать на правильные версии сторонних компонентов, если вы проверяете более старую версию. Единственное решение, о котором я слышал, - это использование разных веток реестра для разных конфигураций выпуска продукта.

Компоненты хранятся в отдельной структуре каталогов и по возможности используют номера версий в именах каталогов. Это облегчает проверку старых версий и позволяет сценариям сборки указывать на правильную версию.

Мы используем Apache Ant в качестве основного инструмента для сборки уже много лет, и он действительно делает все, что нам нужно, включая вызов модульного теста и генерацию сценария Innosetup.

Компиляция пакетов необходима только в том случае, если вы отправляете исполняемый файл вместе с BPL, иначе это не нужно на сервере сборки.

Установка компонентов в IDE также не требуется на сервере сборки.

Вы можете использовать инструмент Owly CI.

Это позволяет легко создавать проекты путем определения файла манифеста. Это также позволяет обрабатывать зависимости - вы можете обернуть сторонние компоненты в пакеты owlyci и пометить их как зависимости от основного проекта.

Есть пример, как использовать его с системой Jenkins CI.

Другие вопросы по тегам