Управление сборкой проектов вместе с teamcity. Часть 3

Материал из DOM

Перейти к: навигация, поиск


Эта статья завершит собой серию материалов посвященных рассказу о том, как teamcity помогает управлять проектами разработки программного обеспечения и, в частности, автоматизирует процесс сборки проекта, запуска тестов и интегрирует эти шаги в жизненный цикл разработки приложения. Прошлые две статьи были посвящены рассказу о том, какое место занимают в ходе разработки программного обеспечения продукты класса “build management and continuous integration ” вообще и teamcity в частности. Мы разобрались с основными понятиями teamcity, научились создавать билд-конфигурации и запускать их на выполнение. Этого должно быть достаточно для повседневной работы, так что сегодняшней статье осталось только “зашлифовать” некоторые не раскрытые моменты.

Прошлую статью я завершил на том, что мы создали билд-конфигурацию и запустили ее на выполнение. После того как свободный билд-агент закончил сборку maven-проекта, мы получили в свое распоряжение несколько отчетов. Во-первых, отчет о результатах запуска автоматических тестов, затем идет отчет о списке изменений в репозитории cvs/svn, которые были включены в текущую сборку. И, в конце концов, у нас в распоряжении оказался полный журнал всех сообщений, которые были сгенерированы билд-сценарием. Остался последний “смешной” вопрос: а где, собственно, находится сам результат выполнения сборки проекта, тот исполнимый файл, архив веб-приложения или “что там мы хотим отдать клиенту”? Если мы вспомним рассказ о maven, то сможем уверенно сказать, что конечный файл сборки проекта может быть найден или в локальном maven-репозитории либо в каталоге target самого проекта. Т.е. мы можем “руками залезть” внутрь каталога "C:\Documents and Settings\MyUserName\.m2\repository" или каталога “E:\Program_Files_2\TeamCity\buildAgent\work\5fa592b1ed40a411” и там найдем результат выполнения сборки. Но, очевидно, что ни один из этих способов неприемлем. Есть два возможных способа дать удобный способ доступа к результатам выполнения билд-сценария, но каждый из них требует небольшого отхода от возможностей, собственно teamcity, и рассмотрения того какие средства предусмотрены, именно, внутри maven. Как часть жизненного цикла сборки maven-проекта входит и фаза deploy – это фаза размещения сгенерированных артефактов на специальном, внешнем, сервере. В том случае, если вам достаточно собрать проект и поместить результат сборки в локальный репозиторий, то используется команда “m2 clean install”. В случае, если вы хотите скопировать результат сборки на удаленный сервер, то используйте команду “m2 clean deploy” (естественно, что вызов deploy включает в себя и фазу install). Теперь нам осталось разобраться с тем, как подсказать maven-у расположение удаленного репозитория, как сообщить имя и пароль для доступа к нему. Начнем с того, что внутри pom.xml файла нужно добавить новую секцию distributionManagement, указав в ней адрес ftp-сервера. Если вы ни разу еще не работали и не знакомы с каким-либо из ftp-серверов, то я могу порекомендовать filezilla (http://sourceforge.net/projects/filezilla/) – бесплатный, простой в настройке и широко известный. Возвращаясь к настройке pom.xml файла, затем в секции build сразу после настройки плагина, выполняющего компиляцию проекта, я подключил еще и плагин “ wagon-ftp”, умеющий работать с ftp-протоколом:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>blackzorro</groupId>
 <artifactId>testartifact1</artifactId>
 <packaging>jar</packaging>
 <version>1.0</version>
 <name>Simple Maven 2 Artifact</name>
 <url>http://maven.apache.org</url>
 <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.4</version>
    <scope>test</scope>
   </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
       < source >1.5< / source >
       <target>1.5</target>
     </configuration>
   </plugin>
  </plugins>
  <extensions>
    <extension>
     <groupId>org.apache.maven.wagon</groupId>
     <artifactId>wagon-ftp</artifactId>
     <version>1.0-alpha-6</version>
   </extension>
  </extensions>
 </build>
  <!-- use ftp repository -->
 <distributionManagement>
   <repository>
     <id>ftp-repository</id>
     <url>ftp://center/m2-repo</url>
     <layout>default</layout>
   </repository>
  </distributionManagement>
</project>

Предполагается, что ftp-сервер содержит каталог “m2-repo”, куда и будут складываться артефакты. Последний штрих связан с настройкой учетной записи, используемой для подключения к ftp-серверу. Для этого я отредактировал файл settings.xml, добавив в секцию “servers” имя и пароль пользователя. Обратите внимание на то, что и в файле pom.xml и в файле settings.xml я использовал одинаковое имя репозитория “ftp-repository”, чтобы maven смог между ними поставить соответствие.

<servers>
  <server>
   <id>ftp-repository</id>
   <username>vasyano</username>
   <password>secret</password>
  </server>
</servers>

После того как была выполнена команда “m2 clean deploy”, то на ftp-сервере появится следующая иерархия файлов "m2-repo\blackzorro\testartifact1\1.0\testartifact1-1.0.jar". Как видите, файл артефакта был сохранен по стандартным правилам maven в каталоги с именами сначала группы артефактов, затем каталога с названием самого проекта-артефакта и, наконец, каталог с номером версии проекта. Обратите внимание еще раз на файл pom.xml и, в частности, на строку “<layout>default</layout>” при регистрации репозитория. Вторым возможным значением кроме “default” является “legacy”, в этом случае файл артефакта будет сохранен под следующим именем " m2-repo\blackzorro\jars\testartifact1-1.0.jar". Если вы обратитесь к сайту со справочной документацией maven, то сможете по аналогии настроить копирование сгенерированных артефактов не только на ftp-сервер, но и через ssh-соединение. Увы, но показанный выше пример ни на что более сложное, чем пример (извиняюсь за тавтологию) просто не тянет. Поскольку я обошел молчанием два ключевых момента связанных с подготовкой сборки проекта. Во-первых, как быть с нумерацией версий сборок? Второй проблема связана с тем, что только для очень простых, учебных заданий конечный файл сборки представляет собой исполнимый jar-файл или архив веб-приложения. Гораздо чаще сборка – это архив, например, zip, со сложной структурой и в состав которого входят и jar-файлы приложения и каталоги со справочной документацией, и каталоги с библиотеками, и всевозможные инсталляционные сценарии и т.д. Что касается управления упаковкой проекта, то я могу посоветовать обратиться, прежде всего, к восьмой статье в моей серии рассказывающей о maven, а также к справочной документации на официальном сайте maven по плагину “maven-assembly-plugin”. Т.к. задача упаковки проекта слабо связана с настройкой интеграции teamcity и maven, то я не буду подробно на ней останавливаться и сразу перейду к вопросу правильной нумерации версий проекта. Напомню, что версия артефакта (а, следовательно, и имя файла под которым он будет сохранен), например “1.2.67”, состоит из двух частей. Последняя цифра версии – это всегда номер сборки, т.е.“67” – номер билда, а предшествующая ему часть кодирует, собственно, номер версии приложения (здесь это “1.2”). Если с первой частью версии приложения вопросов нет, и мы должны ее явно указать внутри pom.xml файла:

<version>1.0</version>

То вот с номером билда обойтись средствами только maven не возможно: поскольку сборки запускаются из teamcity и teamcity хранит историю сборок и номера их билдов. Значит, мы должны так настроить maven и teamcity, чтобы организовать передачу между ними информации. К счастью, перед тем как выполнить запуск билда, teamcity передает внутрь maven-сценария ряд переменных, среди которых есть и “build.number”, т.е. порядковый номер билда. Сначала я задал зависимость версии проекта-артефакта от переменной “version.long”:

<version>${version.long}</version>

Сама же переменная состоит из двух частей, и как я обещал, вторая часть равна значению служебной teamcity переменной ”build.number”:

<properties>
  <version.short>1.0</version.short>
  <version.long>${version.short}B${build.number}</version.long>
</properties>

Таким образом, после завершения билда у меня на ftp-сервере окажется файл со следующим именем: ftp://center/m2-repo/blackzorro/jars/testartifact1-1.0B10.jar и где 10 - порядковый номер билда. Небольшим недостатком показанной методики указания версии проекта в том, что при запуске билда не с помощью teamcity, а на локальной машине с помощью команды “m2 clean install”, конечный файл проекта будет иметь имя “target\testartifact1-1.0Bnull.jar”. Больших проблем “поломанная версия” проекта не вызывает, но все же смотрится не красиво. Простым способом решения является создание “умной” maven-конфигурации, которая сначала проверит доступность teamcity-переменной “build.number” и если это не так, то назначает номер версии проекта как простое число “1.0” или равной слову “local” т.е. без номера билда. К сожалению, в составе maven нет явно выделенной функциональности условных операторов как в “настоящих языках программирования”, но можно их имитировать с помощью профилей. Напомню, что профиль в терминологии maven – это небольшая модификация жизненного цикла проекта, точнее плагинов и их настроек, привязанных к фазам жизненного цикла. К примеру, мы можем внутри pom.xml файла с проектом определить кроме жизненного цикла по-умолчанию еще и профиль ”for-customer”. Такой профиль сформирует файл проекта уже готовый к непосредственной доставке заказчику когда, например, в состав проекта будет внедрена справка, а компиляция проекта будет выполнена с исключением отладочной информации или с “запутыванием” кода. Обфускация (Obfuscate) - это запутывание кода программы, при котором исполнимый файл приводится к виду, сохраняющему исходную функциональность приложения, но усложняющей анализ и модификацию. Подобные меры противодействия нужны для защиты приложений от “злых” хакеров, которые ломают защиту программы. Применительно к сегодняшней статье я буду использовать профиль только лишь для того, чтобы задать другое значение переменной “version.long” в том случае если переменная “build.number” неопределенна. Когда же запуск maven-сценария будет выполняться на локальной машине без помощи teamcity, то файл проекта будет иметь имя “target\testartifact1-local.jar”.

<profiles>
 <profile>
  <id>default-version</id>
  <activation>
    <property>
     <name>!build.number</name>
   </property>
  </activation>
  <properties>
   <version.long>local</version.long>
   </properties>
 </profile>
</profiles>

В своей практике я использовал как показанный выше способ сохранения результатов сборки проекта на ftp-сервере, так и методику, когда файл на ftp-сервер копируется не средствами maven (точнее плагина отвечающего за фазу “deploy”), а с помощью специального ant-сценария. Т.е. я создавал в teamcity такую build-конфигурацию, что запускала maven-проект на сборку с профилем, например, saveToFtp. Технически, я должен был при создании build-конфигурации на закладке ”Build runner” в графе “Additional Maven command line parameters” я вписал имя профиля, под которым нужно запустить билд “-PsaveToFtp”. Сам же профиль определен внутри файла pom.xml и вся его работа состоит в том, что при наступлении фазы “package” maven запускает ant-сценарий. Который последовательно копирует с помощью команды “copy” файл проекта на другой компьютер по сети \\center\SharedDocs\my-app. Вторым шагом идет копирование файла проекта на ftp-сервер (команда “ftp”). Как раз для того, чтобы последняя команда отработала как требуется, мне пришлось подключить к плагину “maven-antrun-plugin” зависимость от библиотек “ant-commons-net” и “commons-net”.

<profile>
   <id>saveToFtp</id>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.2</version>
            <dependencies>
               <dependency>
                  <groupId>ant</groupId>
                  <artifactId>ant-commons-net</artifactId>
                  <version>1.6.5</version>
               </dependency>
               <dependency>
                  <groupId>commons-net</groupId>
                  <artifactId>commons-net</artifactId>
                  <version>2.0</version>
               </dependency>
            </dependencies>
            <executions>
               <execution>
                  <phase>package</phase>
                  <goals>
                     <goal>run</goal>
                  </goals>
               </execution>
            </executions>
            <configuration>
               <tasks>
                  <copy file="target/testartifact1-${version.long}.jar" todir="\\center\SharedDocs\my-app"/>
                  <ftp server="center" binary="true" verbose="true" userid="vasyano" password="secret" remotedir="/">
                     <fileset dir="target">
                        <include name="*.jar"/>
                     </fileset>
                  </ftp>
               </tasks>
            </configuration>
         </plugin>
      </plugins>
   </build>
</profile>

В отдельных случаях можно не выполнять копирование файла с результатами сборки на какой-то ftp-сервер, а попросить teamcity сохранить его как артефакт где-то внутри самого teamcity сервера. У teamcity тоже есть понятие артефактов и по своему значению оно сходно с тем, что под артефактами понимает maven. В последующем любой пользователь может зайти через веб-интерфейс teamcity-сервера на страничку с результатами сборки и увидит там ссылки на все файлы, полученные в ходе выполнения сборки и заявленные как артефакты. Применительно к нашему случаю я хочу зарегистрировать как артефакт файлы, находящиеся в каталоге “target”. Для этого я от имени администратора teamcity захожу на страницу редактирования свойств билд-конфигурации, затем на закладку “General Settings” и в графе “Artifact Paths” я ввел следующие две строки:

target/*.jar
target/surefire-reports/**/*.* => test reports

Каждая строка состоит из двух частей, которые разделены символами “=>”. Первая часть (“target/*.jar” или “target/surefire-reports/**/*.*”) представляют собой пути к файлам или каталогам, которые мы хотим пометить как артефакты. При задании путей мы можем использовать символы подстановок, такие как * и ** (каталоги на любом уровне вложенности). Вторая же часть выражения (обратите внимание, что в первом примере она отсутствует) задает имя файла или “виртуального” подкаталога в который teamcity скопирует файлы артефактов. Так первой строкой я попросил teamcity сохранить все файлы с расширением jar внутри подкаталога target под теми же именами, которые они имеют. А вторая строка скопировала все файлы из подкаталога “surefire-reports” в подкаталог “ test reports” (это файлы с отчетами по результатам выполнения тестов). На рис.1

Изображение:Teamcity_3_1.png

я показал то, как выглядит страничка с перечнем доступных артефактов, каждый из которых вы можете загрузить к себе на компьютер. Что касается сроков хранения артефактов, равно как и хранения истории запуска билдов, то это можно настроить в панели управления teamcity на странице “Administration -> Clean-up process settings”.

Следующая часть статьи будет посвящена средствам интеграции teamcity со средами разработки. Приятно, что хотя, создавшая teamcity, компания jet brains разрабатывает также и среду для java программистов под названием intellij idea, но jet brains решила не обижать невниманием также и тех программистов, кто предпочитает для работы среду IDE eclipse или даже программирует не на java, а на visual studio. Для того, чтобы установить к себе на компьютер плагин teamcity, необходимо зайти в панели управления teamcity на страницу “My Settings & Tools”, и там вы увидите ряд ссылок для загрузки плагинов. Я скачал файл “TeamCity-IDEAplugin.zip ” плагина для idea, затем распаковал содержимое архива каталог idea/plugins, и после перезапуска среды idea получил в свое распоряжение новое меню “teamcity”. Первым шагом настройки интеграции idea и teamcity является регистрация пользователя. Для этого я выбрал меню “Teamcity -> Login” и в появившемся диалоговом окне указал адрес подключения к teamcity, свое имя и пароль. Первое что мы настроим – это систему извещений о таких событиях как запуск билда и результат его выполнения. Teamcity может посылать сообщения об перечисленных выше событиях, например, по email или jabber клиенту, но гораздо удобнее если извещения показываются в среде разработки т.к. мы получаем дополнительный функционал быстрого перехода к списку изменений произошедших в проекте с момента прошлого билда. Итак, выбираем меню “teamcity -> Edit Notification Rules” затем в открывшемся окне браузера мы вводим свое имя и пароль, чтобы попасть внутрь teamcity и, наконец, перед нами открывается страница редактирования правил извещений. Нас интересует закладка “IDE notifier” (см. рис. 2),

Изображение:Teamcity_3_2.png

где мы можем выбрать то, когда teamcity пошлет нам извещение. Я выбрал события “The build is successful”, “Responsibility changes” и “The build fails”. Теперь после того как билд будет завершен, то я увижу всплывающее окошко с сообщением об этом. Более того, teamcity плагин предоставил мне доступ к панели наблюдения за статусом билдов. Так на рис. 3

Изображение:Teamcity_3_3.png

я показал момент, когда сборка проекта завершилась неудачей, и я решил взять на себя ответственность за этот сбой. Т.е. я сообщаю teamcity о том, что именно мои изменения являлись причиной сбоя. После того как я исправлю ошибку в коде и сохраню изменения в cvs|svn, то я смогу попросить teamcity пометить следующий билд как содержащий исправления для предыдущего. Как приятный бонус после установки плагина интеграции teamcity и idea мы получаем функцию быстрого перехода из окна браузера, например, со страницы с перечнем измененных файлов, в окно java редактора. Также панель teamcity содержит функцию просмотра списка последних файлов, а также позволяет просмотреть различия между ними с помощью удобного diff-редактора (см. рис. 4).

Изображение:Teamcity_3_4.png

Крайне полезна в практике и функция “Remote Run”. Так если я внутри редактора idea изменю какой-то файл и выберу в меню пункт “teamcity -> remote run” то idea отправит файлы с изменениями кода не в cvs/svn репозиторий, а непосредственно на машину с билд агентом. На рис. 5

Изображение:Teamcity_3_5.png

я показал пример диалогового окна, где я настраиваю параметры Remote Run, так я указал, что если запуск билда с моими правками будет успешен и ни один из тестов не будет провален, то изменения нужно автоматически сохранить и в cvs/svn репозиторий.


На этом я завершаю рассказ об teamcity и том какое место оно занимает в процессе управления сборкой проектов. Естественно, что три статьи серии не могут претендовать на достаточно полное описание возможностей teamcity, но я надеюсь на то, что вы поняли, зачем нужны продукты класса “Build management and continuous integration” вообще и, в частности, один из лучших представителей этого семейства – teamcity.

Subscribe Now!

 

ObMachine projects & articles (java, flash, flex, php, ...)  -- black-zorro.com