Введение
Я начал расширять функциональность IBM® Rational Team Concert™, чтобы улучшить процесс непрерывной поставки ПО для одного из наших клиентов. Клиенту нужен был плагин, который воссоздавал бы пакет из предыдущей сборки с параметрами сборки для новой среды, чтобы создать версию для обновленной среды. Плагин должен был заменить ручной процесс, который длился два часа и был подвержен ошибкам.
Написанный мной плагин load workspace from label работал как участник предсборки. Участники этапов pre-build (предсборки), build (сборки) и post-build (постсборки) содержат Java-класс, способный выполняться в среде Jazz Build Engine как часть процесса сборки. Несколько участников составляют определение сборки (build definition). Исходный код в виде плагина содержится в папке eclipse, расположенной в каталоге установки Build Engines сервера сборки.
Участник сборки load workspace from label выполняет следующие функции:
- Принимает определение сборки и метку сборки (build label) в качестве параметров из пользовательского интерфейса Eclipse-клиента.
- Проверяет принадлежность входных данных одному результату успешной сборки.
- Создает новую рабочую область из снимка связанных результатов сборки, именуемых в Rational Team Concert SDK набором базовых показателей (baseline set).
- Меняет текущую рабочую область сборки на новую.
- Выполняется перед плагином jazzscm, который работает в обычном режиме, за исключением того, что теперь он загружает только что созданную рабочую область, содержащую тот же исходный код, что и первоначальная сборка, но связанный с предоставленным пользователем идентификатором определения и меткой.
Исходный код плагина load workspace from label находится на Github.
Исходный код решения build participant излишне сложен для данной статьи, поэтому я решил рассмотреть более простой сценарий и создал плагин my build participant. Рассматриваемый в статье плагин выполняет следующие функции:
- Принимает входные данные пользователя в Eclipse-клиенте.
- Записывает эти данные в журнал сборки.
- Получает имя инициировавшего сборку пользователя и идентификатор Universally Unique Identifier (UUID) рабочей области и при помощи программных интерфейсов Rational Team Concert API помечает сборку, используя имя пользователя и UUID рабочей области.
Исходный код плагина my build participant, рассматриваемый в данной статье, можно загрузить с Github.
Необходимые ресурсы
Для расширения плагина Rational Team Concert необходимо знание сред разработки Eclipse Plugin Development и Plugin Development Environment (PDE). В данной статье в пошаговом режиме описывается весь процесс реализации плагина, а также отмечаются действия, применимые к созданию стандартных Eclipse-плагинов, и действия, относящиеся к плагинам, специфичным для Rational Team Concert.
Настройка среды разработки
Необходимо загрузить SDK, Plain Java API, Jazz Build Engine и плагин Eclipse Client, соответствующие конкретной версии Rational Team Concert. Например, при использовании Rational Team Concert версии 4.0.0 нельзя использовать SDK версии 4.0.6.
Локальная установка Rational Team Concert и SDK
Для создания плагина необходима среда разработки. Rational Team Concert 4.x Extensions Workshop на Jazz.net содержит пошаговое руководство по настройке среды разработки (см. раздел Lab 1 - Настройка IBM Rational Team Concert SDK ). Я еще не работал с версией 5, поэтому сообщите, пожалуйста, в комментариях к данному руководству, нужна ли его корректировка. При установке Rational Team Concert необходимо выбирать вариант с установкой Jazz Build Engine.
Самым простым способом установки плагина Rational Team Concert Eclipse Client является его импорт как репозитория p2. Перейдите на страницу releases в вашей версии Rational Team Concert и нажмите All Downloads. Найдите файл RTC-Client-p2Repo-X.X.X.zip. Установите плагин в Eclipse, выбрав Help > Install New Software, и в качестве архива добавьте p2 repo.
Примечание.
Использовать Workshop Setup не обязательно.
Установка Rational Team Concert для работы в локальном режиме займет как минимум один час. Я рекомендую сделать это, поскольку, как вы вскоре убедитесь, разработка плагинов представляет собой итеративный процесс. Ни один разработчик не будет благодарен за этот плагин, если вы случайно нарушите его процесс сборки и испортите набор определений сборки.
Установка Jazz Build Engine
Jazz Build Engine инициализирует процесс, выполняющий сценарий сборки и собирающий выходную информацию. Он выполняется на сервере сборки как Java-процесс, ожидающий от клиента команды на сборку.
Установите Jazz Build Engine в локальном режиме. Рекомендуется скопировать его с целевого сервера сборки, чтобы иметь полную уверенность в идентичности версий. Можно также установить все через Rational Team Concert Setup, как описано в разделе Локальная установка Rational Team Concert и SDK.
В Linux создайте зашифрованный файл паролей, выполнив приведенную в листинге 1 команду и указав пароль созданного ранее пользователя Rational Team Concert, обладающего правами на сборку.
Листинг 1. bash-команда для создания зашифрованного файла пароля
${JBE_HOME}/jazz/buildsystem/buildengine/eclipse/jbe -createPasswordFile <выходной_файл_паролей>
Для запуска Jazz Build Engine в виде демона Linux выполните команды, приведенные в листинге 2. Замените соответствующие значения переменных
Листинг 2. bash-команда для инициализации Jazz Build Engine в виде демона
REPO="https://localhost:9443/ccm" # URL of your RTC Server JAVA_HOME="${JBE_HOME}/jazz/buildsystem/buildengine/eclipse/jdk/bin/java" ENGINE_ID="test-be" # соответствует имени механизма сборки в RTC ENGINE_USER="myadmin" # RTC использует идентификатор пользователя для механизма сборки ENGINE_PWFILE="<output_password_file>" # Сгенерировано во фрагменте кода 1 JBE_LOGFILE="/tmp/jazzbuildengine/jbe_test.log" # Расположение log-файлов JB JBE_WORKSPACE="/tmp/plugin_engine_workspace" # Рабочая область JBE Eclip daemon "$JBE_HOME/jazz/buildsystem/buildengine/eclipse/jbe -clean -Xmx512m \ -data $JBE_WORKSPACE -vm $JAVA_HOME -repository $REPO -userId $ENGINE_USER \ -passwordFile $ENGINE_PWFILE -engineId $ENGINE_ID -sleeptime 10 -clean -debug \ >$JBE_LOGFILE 2>&1 &"
Теперь механизм сборки готов к обработке запросов на сбор
Реализация расширения Rational Team Concert
В данном примере рассматривается создание:
- Специализированного редактора в клиенте Rational Team Concert, принимающего и проверяющего вводимые пользователем данные.
- Нового шаблона определения сборки, включающего участника сборки.
- Участника сборки, регистрирующего в log-файле вводимые пользователем данные и помечающего сборку с помощью идентификатора пользователя, инициировавшего сборку, и UUID рабочей области.
Расширение Rational Team Concert требует наличия трех отдельных плагинов:
- Ппагин engine, который устанавливается в каталог plugin установки Jazz Build Engine.
- Плагин client, который устанавливается как автономный Eclipse-плагин, импортированный в виде репозитория p2 (аналогично Rational Team Concert Client).
- Плагин common. Плагин common включается в репозиторий p2 и устанавливается в Jazz Build Engine как отдельный плагин.
При разработке Eclipse-плагинов указывайте целевую платформу, чтобы предоставить интегрированной среде разработки (IDE) контекст, в котором работает приложение - например, плагины и библиотеки, доступные во время выполнения. Проблема заключается в том, что мы разрабатываем плагин для двух целевых платформ (Jazz Build Engine и Rational Team Concert Eclipse Client). Они содержат различные библиотеки и плагины, и именно поэтому необходимо создавать как плагин engine, так и плагин client. Плагин common необходим для их интеграции.
В следующем разделе описывается создание данных плагинов и настройка необходимой для этого рабочей области Eclipse.
Настройка рабочей области Eclipse
Приступим непосредственно к разработке Eclipse-плагина. Для получения дополнительной информации о каждом описываемом мною действии обратитесь к Руководству по Eclipse-плагинам. Можно также обратиться к разделу 1.2 Настройка среды разработки в Rational Team Concert 4.x Extensions Workshop на сайте Jazz.net.
Перейдите в представление Plugin Development в Eclipse. Создайте две рабочие области my_build_participant_client и my_build_participant_engine, по одной для каждой целевой платформы.
В рабочей области client создайте два проекта my_build_participant_client и my_build_participant_common. В качестве целевой платформы укажите разархивированный Rational Team Concert SDK, который вы загрузили в разделе Настройка среды разработки. В настройках проекта для плагина client создайте зависимость проекта от плагина common. Также нужно добавить плагин common в манифест сборки плагина client.
Примечание.
Будьте внимательны при изменении проекта common в каждой рабочей области, поскольку изменения файлов могут быть несинхронными. Эту ситуацию можно исправить, выбрав project > clean. Если вам известен лучший способ управления проектом common, оставьте предложения в комментариях.
В рабочей области engine создайте проект engine под названием my_build_participant_engine и импортируйте плагин my_build_participant_common. Укажите целевую платформу ${JBE_HOME}/buildsystem/buildengine/eclipse/plugins. Создайте зависимость проекта от плагина common и импортируйте плагин, аналогично настройке рабочей области client.
Журналирование и отладка
После установки Jazz Build Engine создаются два log-файла, которые очень полезны при отладке плагина для Jazz Build Engine.
Плагин для Jazz Build Engine
В log-файл Jazz Build Engine (JBE_LOGFILE
в листинге 2) записывается информация, выводимая регистратором событий Rational Team Concert. Эта же информация отображается во время сборки в log-файле сборки.
Примечание.
Я попытался запустить Jazz Build Engines с открытым отладочным портом, однако безуспешно. Если у вас это получилось, опишите свое решение в комментариях.
Параметр -data
, предоставляемый механизму сборки (JBE_WORKSPACE
в листинге 2), очень важен при отладке Jazz Build Engine. В этом log-файле регистрируются все Eclipse-ошибки инициализации плагина.
Плагин для Rational Team Concert Eclipse Client
Теперь, после настройки рабочей области Eclipse, можно приступить к запуску и отладке плагина client как Eclipse-приложения. Щелкните правой кнопкой мыши на проекте и выберите Run As > Eclipse Application or Debug As > Eclipse Application.
Рекомендации по отладке и журналированию приведены во многих руководствах по разработке Eclipse-плагинов и на сайте Eclipse PDE.
Разработка плагина
Обзор плагина
Расширение Rational Team Concert состоит из трех описанных ниже плагинов.
- com.ibm.rtcexts.mybuildparticipant.common
- com.ibm.rtcexts.mybuildparticipant.client
- com.ibm.rtcexts.mybuildparticipant.engine
Для реализации компонента client в виде репозитория p2 в рамках описанного ниже (см. раздел Сборка и развертывание) процесса сборки плагинов client необходимы два дополнительных плагина.
- com.ibm.rtcexts.mybuildparticipant.feature
- com.ibm.rtcexts.mybuildparticipant.updatesite
Плагины engine и common размещаются в рабочей области my_build_participant_engine, а плагины client, common, feature и updatesite размещаются в рабочей области my_build_participant_client.
Как и для многих Eclipse-плагинов, для инициализации плагинов engine и client необходимы plugin.xml, манифест плагина и класс activator. Хотя компонент common также пакетируется как Eclipse-плагин, для него класс activator не требуется, поскольку он не инициализируется как автономный плагин, а используется только для вызова из плагинов engine и client. В следующих разделах я рассмотрю реализацию каждого Eclipse-плагина более подробно.
Плагин common
Плагин common связывает плагин, работающий в Jazz Build Engine, и плагин, работающий в Eclipse-клиенте. Плагин common используется только как расширение плагинов engine и client, поэтому для него не требуется класс activator. Более подробная информация о классах activator приведена ниже.
Самая важная часть плагина common находится в plugin.xml.
XML-файл плагина
Листинг 3. plugin.xml для плагина common
<plugin> <!--buildConfigurationElement--> <extension point="com.ibm.team.build.common.buildConfigurationElements"> <buildConfigurationElement id="com.ibm.rtcexts.mybuildparticipant.buildconfigelement" name="My build configuration element" description="my new element that is to be used by my build participant" buildPhase="PRE_BUILD" > <genericProperty genericEditAllowed="false" name="com.ibm.rtcexts.mybuildparticipant.common.buildConfigProperty1" description="A build property." required="true" /> <genericProperty genericEditAllowed="false" name="com.ibm.rtcexts.mybuildparticipant.common.buildConfigProperty2" description="Another build property." required="true" /> </buildConfigurationElement> </extension> <!--buildDefinitionTemplate --> <extension point="com.ibm.team.build.common.buildDefinitionTemplates"> <buildDefinitionTemplate id="com.ibm.rtcexts.mybuildparticipant.common.myTemplate" description="My new template containing my new build configuration element." name="my new build definition" > <buildConfigurationElement id="com.ibm.team.build.properties"/> <buildConfigurationElement id="com.ibm.team.build.general"/> <buildConfigurationElement id="com.ibm.rtcexts.mybuildparticipant.buildconfigelement" /> <buildConfigurationElement id="com.ibm.team.build.jazzscm"/> <buildConfigurationElement id="com.ibm.team.build.cmdline"/> <buildConfigurationElement id="com.ibm.team.build.ant"/> <buildConfigurationElement id="com.ibm.team.build.email"/> </buildDefinitionTemplate> </extension> </plugin>
Первой точкой расширения является расширение buildConfigurationElements путем добавления нового элемента конфигурации сборки. Более подробная информация о точках расширения приведена в статье Архитектура плагинов Eclipse (EN). Это самая важная часть всей информации plugin.xml, поскольку данный объект связывает все вместе и, следовательно, является обязательным в плагине common. Идентификатор id - это элемент, на который ссылаются оба плагина (client и engine). buildPhase переносит элемент конфигурации на заданный этап сборки, который должен быть таким же, как и у класса AbstractBuildEngineParticipant
, описанного в плагине engine ниже. Для связывания данных с Eclipse-формой в плагине client используются типовые свойства. Механизм сборки может затем обращаться к значениям buildConfigProperty1
и buildConfigProperty2
через объект элемента конфигурации сборки com.ibm.rtcexts.mybuildparticipant
.
Последней точкой расширения для плагина common является Rational Team Concert buildDefinitionTemplate. Она описывает дополнительный шаблон определения сборки. Шаблон определяет порядок выполнения участников сборки в жизненном цикле процесса сборки, поэтому он необходим для плагина engine. Позже вы увидите, что выбор buildDefinitionTemplate в Eclipse-клиенте при создании определения сборки делает доступной соответствующую конфигурацию участников сборки в пользовательском интерфейсе.
Функциональность участника сборки load workspace from label, разработанного мною в предыдущем проекте, зависит от очередности выполнения нового элемента конфигурации сборки. Плагин com.ibm.rtcexts.mybuildparticipant должен выполняться до плагина Jazz SCM, чтобы мой плагин мог изменить исходный код, извлекаемый при сборке. Поэтому my build participant стоит в списке выше. Оба эти плагина выполняются на этапе pre-build, поскольку являются участниками предсборки. Более подробная информация приведена в разделе Plugin engine.
Наконец, в плагине common я написал простой класс для хранения констант, используемых обоими плагинами (engine и client).
Реализация
Плагин common не предоставляет функциональность как таковую, а является местом хранения общих свойств плагинов engine и client. Например, в листинге 4 описаны свойства элемента конфигурации сборки.
Листинг 4. Класс элемента конфигурации
public abstract interface MyBuildParticipantsConfigurationElement { public static final BuildPhase BUILD_PHASE = BuildPhase.PRE_BUILD; public static final String NAME = "My new build participant"; public static final String ELEMENT_ID = "com.ibm.rtcexts.mybuildparticipant." + "buildconfigelement"; public static final String PROPERTY_1 = "com.ibm.rtcexts.mybuildparticipant." + "common.buildConfigProperty1"; public static final String PROPERTY_2 = "com.ibm.rtcexts.mybuildparticipant." + "common.buildConfigProperty2"; }
Шаблона определения сборки и элемента конфигурации сборки достаточно, чтобы шаблон появился в списке Available build templates при создании нового определения сборки (см. рисунок 1).
Рисунок 1. Снимок экрана со списком Available build templat
Плагин client
Плагин client содержит код для Eclipse-форм, который собирает свойства для элемента my build configuration, созданного ранее.
Класс activator
Класс activator необходим для инициализации плагина client
Листинг 5. Класс activator для плагина client
public class MyBuildParticipantClientPlugin extends AbstractUIPlugin { // Идентификатор плагина public static final String PLUGIN_ID = "com.ibm.rtcexts.mybuildparticipant.client"; // Общий экземпляр private static MyBuildParticipantClientPlugin plugin; //Конструктор public MyBuildParticipantClientPlugin() { } public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } // Возвращает общий экземпляр public static MyBuildParticipantClientPlugin getDefault() { return plugin; } // Возвращает дескриптор образа для файла образа public static ImageDescriptor getImageDescriptor(String path) { return imageDescriptorFromPlugin(PLUGIN_ID, path); } }
Класс activator аналогичен классу из примера hello world в Eclipse Plugin Development. Более подробная информация об этом классе приведена в документации по Eclipse Plugin Development.
Манифест
Теперь Bundle-Activator указывается в манифесте.
Листинг 6. Манифест для плагина clie
Manifest-Version : 1.0 Bundle-ManifestVersion : 2 Bundle-Name : com.ibm.rtcexts.mybuildparticipant.clientnt Bundle-SymbolicName : com.ibm.rtcexts.mybuildparticipant.client;singleton:=true Bundle-Version : 1.0.1 Bundle-Vendor : IBM Require-Bundle : org.eclipse.ui, org.eclipse.core.runtime, com.ibm.team.build.ui, org.eclipse.ui.forms, com.ibm.team.build.common, com.ibm.team.build.client, com.ibm.team.repository.client, com.ibm.team.repository.common, com.ibm.team.jface, com.ibm.rtcexts.mybuildparticipant.common Bundle-RequiredExecutionEnvironment : JavaSE-1.6 Bundle-Activator : com.ibm.rtcexts.mybuildparticipant.client.MyBuildParticipantClientPlugin Bundle-ActivationPolicy : lazy
XML-файл плагина
Файл plugin.xml для плагина client является базовым и описывает только сам редактор элемента конфигурации сборки.
Листинг 7. plugin.xml для плагина client
<plugin> <!--Вкладка editor в конфигурации сборки--> <extension point="com.ibm.team.build.ui.buildConfigurationElementEditors"> <buildConfigurationElementEditor configurationElementId="com.ibm.rtcexts.mybuildparticipant.buildconfigelement" name="my new element editor's name" class="com.ibm.rtcexts.mybuildparticipant.client.ConfigurationElementEditorFactory" /> </extension> </plugin>
Точкой расширения является buildConfigurationElementEditors. Редактор элемента конфигурации сборки имеет configurationElementId, указывающий на элемент конфигурации сборки из созданного нами ранее плагина common. Этот класс указывает полное имя класса, расширяющего AbstractConfigurationElementEditor.
Реализация
Применяя Eclipse-формы, мы создадим класс, расширяющий AbstractConfigurationElementEditor, для создания пользовательского интерфейса редактирования свойств элемента конфигурации сборки. Для этого я использовал BasicConfigurationElementEditor в com.ibm.team.build.client.
Листинг 8. Код плагина client для редактора элемента конфигурации
public class BuildIdAndLabelPreConfigurationElementEditor extends BasicConfigurationElementEditor { private static final String ERROR_PROPERTY_REQUIRED = "Property is required"; private static final String PROPERTY_1_AND_2_CONFIGURATION_SECTION_LABEL = "Build Definition ID and Label"; private static final String PROPERTY_1_CONFIG_LABEL = "property 1"; private static final String PROPERTY_2_CONFIG_LABEL = "property 2"; private static final String PROPERTY_1_AND_2_SECTION_DESCRIPTION = "The section containing my properties 1 and 2"; private static final String GENERIC_PROPERTY_DESCRIPTION = "A property required for build."; protected Text fBuildDefinitionIdText; protected Text fBuildLabelText; //конструктор редактора public BuildIdAndLabelPreConfigurationElementEditor(String elementId, String title) { super(elementId, title); } @Override public void createContent(Composite parent, FormToolkit toolkit) { parent.setLayout(new TableWrapLayout()); Section section = createSection(parent, PROPERTY_1_AND_2_CONFIGURATION_SECTION_LABEL, PROPERTY_1_AND_2_SECTION_DESCRIPTION, false); Composite composite = (Composite) section.getClient(); createBuildDefinitionIdWidgets(composite); createBuildLabelWidgets(composite); } private void createBuildDefinitionIdWidgets(Composite parent) { fBuildDefinitionIdText = createConfigPropertyTextField(parent, MyBuildParticipantsConfigurationElement.PROPERTY_1,PROPERTY_1_CONFIG_LABEL, GENERIC_PROPERTY_DESCRIPTION, false); } private void createBuildLabelWidgets(Composite parent) { createSpacer(parent, FIELD_SPACING, 2); fBuildLabelText = createConfigPropertyTextField(parent, MyBuildParticipantsConfigurationElement.PROPERTY_2,PROPERTY_2_CONFIG_LABEL, GENERIC_PROPERTY_DESCRIPTION, false); } @Override public boolean validate() { boolean isValid = true; if (fBuildDefinitionIdText.getText().trim().equals("")) { addErrorMessageForRequiredField(fBuildDefinitionIdText,ERROR_PROPERTY_REQUIRED, fBuildDefinitionIdText); isValid = false; } else { removeMessage(fBuildDefinitionIdText, fBuildDefinitionIdText); } if (fBuildLabelText.getText().trim().equals("")) { addErrorMessageForRequiredField(fBuildLabelText,ERROR_PROPERTY_REQUIRED, fBuildLabelText); isValid = false; } else { removeMessage(fBuildLabelText, fBuildLabelText); } setPageStatusIndicator(!isValid, false); return isValid; } @Override public Control getFocusControl() { return fBuildDefinitionIdText; } }
Попросту говоря, этот класс переопределяет два важных метода. Первый метод, createContent
, предназначен для создания формы для загрузки, а второй, validate
, - для проверки корректности вводимых пользователем данных. Данные связываются с элементом конфигурации сборки посредством метода createConfigPropertyTextField
, вызываемого в классе BasicConfigurationElementEditor
.
Имеющегося на данный момент кода достаточно, чтобы увидеть редактор элемента конфигурации для соответствующего шаблона определения сборки (см. рисунок 2).
Рисунок 2. Редактор нового элемента конфигурации сборки, связанный с шаблоном определения сборки
Плагин engine
Плагин engine содержит код, выполняющийся в рамках процесса сборки.
Класс activator
Помня о том, что Jazz Build Engine является Eclipse-приложением, мы должны расширить его посредством Eclipse-плагина. Для инициализации плагина необходим класс activator.
Листинг 9. Класс activator плагина engine
public class MyBuildParticipantEnginePlugin extends Plugin { // Идентификатор плагина public static final String PLUGIN_ID = "com.ibm.rtcexts.mybuildparticipant.engine"; // Общий экземпляр private static MyBuildParticipantEnginePlugin plugin; //Конструктор public MyBuildParticipantEnginePlugin() { } public void start(BundleContext context) throws Exception { super.start(context); @SuppressWarnings("unused") Plugin plugin = this; } public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } //Возвращает общий экземпляр public static MyBuildParticipantEnginePlugin getDefault() { return plugin; } }
Класс activator отличается от аналогичного класса плагина client только тем, что не имеет элементов пользовательского интерфейса и поэтому является более простым.
Манифест
Свойство Bundle-Activator
в манифесте тоже устанавливается в значение PLUGIN_ID
из класса activator.
Листинг 10. Манифест плагина enginet
Manifest-Version : 1.0 Bundle-ManifestVersion : 2 Bundle-Name : com.ibm.rtcexts.mybuildparticipant.engine Bundle-SymbolicName : com.ibm.rtcexts.mybuildparticipant.engine;singleton:=true Bundle-Version : 1.0.2 Bundle-RequiredExecutionEnvironment : JavaSE-1.6 Require-Bundle : com.ibm.team.build.common, org.eclipse.core.runtime, com.ibm.team.build.engine, com.ibm.team.repository.client, com.ibm.team.repository.common, com.ibm.team.build.client, com.ibm.rtcexts.mybuildparticipant.common;bundle-version="1.0.2", com.ibm.team.build.toolkit, com.ibm.team.scm.common, com.ibm.team.scm.client Bundle-ClassPath : . Bundle-Activator : com.ibm.rtcexts.mybuildparticipant.engine.MyPreBuildParticipantPlugin Bundle-ActivationPolicy : lazy
Помимо свойства Bundle-Activator
, в манифесте есть три важные части.
- Свойство
Bundle-ClassPath
должно быть установлено относительно базового каталога плагина.
- Свойство
Bundle-ActivationPolicy
должно быть установлено в значение lazy, что гарантирует создание экземпляра только в момент использования и значительно облегчает процесс отладки.
- Обратите внимание, что я удалил версии плагинов в
Require-Bundle
, чтобы плагин был более переносимым и меньше зависел от незначительных обновлений. Я оставил версию для плагина common на случай, если забуду удалить старую версию при обновлении плагина.
XML-файл плагина
Файл plugin.xml плагина engine содержит только участников механизма сборки.
Листинг 11. plugin.xml для плагина engine
<plugin> <extension point="com.ibm.team.build.engine.buildEngineParticipants"> <buildEngineParticipant id="com.ibm.rtcexts.mybuildparticipant.engine.MyPreBuildParticipant" class="com.ibm.rtcexts.mybuildparticipant.engine.MyPreBuildParticipant" buildPhase="PRE_BUILD" configurationElementId="com.ibm.rtcexts.mybuildparticipant.buildconfigelement" /> </extension> </plugin>
Точкой расширения является buildEngineParticipants. buildPhase может быть установлен в PRE_BUILD
, BUILD
или POST_BUILD
. configurationElementId
- это идентификатор элемента конфигурации сборки, определенного ранее в плагине common. Класс должен указывать полное имя созданного класса и расширять AbstractBuildEngineParticipant. Для идентификатора рекомендуется использовать то же имя, что и для класса участника сборки.
Реализация
В данном примере мы создадим участника предсборки для расширения класса AbstractPreBuildParticipant
(см. листинг 12).
Листинг 12. Java-класс участника предсборки
public class MyPreBuildParticipant extends AbstractPreBuildParticipant { private String property1; private String property2; @Override public BuildStatus preBuild(IProgressMonitor monitor) throws Exception { IBuildDefinitionInstance buildDefinitionInstance = getBuildRequest(). getBuildDefinitionInstance(); IBuildConfigurationElement element = buildDefinitionInstance.getConfigurationElement( MyBuildParticipantsConfigurationElement.ELEMENT_ID); property1 = element.getConfigurationProperty( MyBuildParticipantsConfigurationElement.PROPERTY_1).getValue(); property2 = element.getConfigurationProperty( MyBuildParticipantsConfigurationElement.PROPERTY_2).getValue(); if (property1 == null // property1.length() < 1) { throw new MissingPropertyException("property 1 is not valid!!"); } if (property2 == null // property2.length() < 1) { throw new MissingPropertyException("property 2 is not valid!!"); } BuildParticipantLogger.info(getBuildLog(), "user set property1 to \"" + property1 + "\""); BuildParticipantLogger.info(getBuildLog(), "user set property2 to \"" + property2 + "\""); ITeamRepository repo = getTeamRepository(); String buildRequesterUserId = repo.getUserId(); String currentWorkspaceUUID = buildDefinitionInstance.getProperty( IJazzScmConfigurationElement.PROPERTY_WORKSPACE_UUID).getValue(); String tag = (buildRequesterUserId.isEmpty() // currentWorkspaceUUID.isEmpty()) ? "" : buildRequesterUserId + "_" + currentWorkspaceUUID; if (tag!= null && !tag.isEmpty()) { IBuildResult buildResult = (IBuildResult) repo.itemManager().fetchCompleteItem( getBuildRequest().getBuildResult(), IItemManager.REFRESH, monitor); IBuildResult buildResultWorkingCopy = (IBuildResult) buildResult.getWorkingCopy(); String existingTags = buildResultWorkingCopy.getTags(); String tagStrippedInvalidChars = tag.trim().replace(' ', '_').replace(',', '_'); String fullTag = (existingTags != null && existingTags.isEmpty()) ? existingTags + "," + tagStrippedInvalidChars : tagStrippedInvalidChars; BuildParticipantLogger.info(getBuildLog(), "Tagging current build with tag: " + tagStrippedInvalidChars); buildResultWorkingCopy.setTags(fullTag + tagStrippedInvalidChars); ITeamBuildClient buildClient = (ITeamBuildClient) repo.getClientLibrary( ITeamBuildClient.class); buildClient.save(buildResultWorkingCopy, monitor); } return BuildStatus.OK; }
В зависимости от расширяемого класса AbstractBuildEngineParticipant
необходимо переопределить методы preBuild
, build
или postBuild
. Мы расширяем AbstractPreBuildParticipant
, поэтому переопределяется метод preBuild
. Метод preBuild
вызывается при выполнении нашего участника сборки сервером Jazz Build Engine.
Участник сборки получает buildDefinitionInstance, являющийся неизменяемым объектом в отличие от самого buildDefinition, который может меняться. Определение сборки используется для доступа к идентификатору элемента конфигурации сборки, который описывается в plugin.xml плагина common. В файле plugin.xml плагина common указываются также общие свойства, доступные участникам сборки посредством элемента конфигурации сборки. В данном примере они извлекаются участником сборки и выводятся в log-файл Jazz Build Engine специальной программой logger. Мы также используем класс элемента конфигурации в плагине common для получения ELEMENT_ID
и PROPERTY_X IDs
.
Затем участник получает UUID рабочей области на основании экземпляра определения сборки и имени пользователя Rational Team Concert, инициировавшего процесс сборки, посредством Jazz Team Repository API. После этого участник сборки получает локальную рабочую копию результатов текущей сборки и определяет наличие существующих тегов. Наконец, участник сборки создает строку tag, записывает в нее локальную рабочую копию результатов сборки и сохраняет ее, используя клиент сборки.
Результат
На рисунке 3 показаны результаты работы участника сборки.
Рисунок 3. Результаты успешной сборки с использованием плагина my new build participant
Обратите внимание, что в сборке помечены имя пользователя и рабочая область. Также обратите внимание, что в log-файл успешно помещены пользовательские свойства нашего элемента конфигурации сборки. Наконец, была соблюдена очередность выполнения плагина, т.е. перед плагином jazzscm.
Теперь, когда вы узнали, как добавить в Rational Team Concert нового участника сборки и распределить обязанности между плагинами client и engine, я завершу статью несколькими полезными рекомендациями по автоматизации сборки и развертыванию плагина.
Сборка и развертывание
Для автоматизации сборки, тестирования, упаковки и развертывания я рекомендую использовать программу Ant. Возможно, вы предпочтете идти по пути Maven и использовать для сборки своего проекта Tycho. На Web-сайте Vogella имеется хорошее руководство от создателей Tycho. Моим требованиям больше соответствуют специализированные Ant-сценарии.
Для создания Ant-сценариев щелкните правой кнопкой мыши на файлах plugin.xml каждого из трех плагинов и выберите PDE Tools > Create Ant Build File. build.update.jar создает плагин в виде jar-файла в каталоге build. Я внес в эти сценарии много изменений для улучшения консолидации свойств, таких как имя и версия плагинов, но они слишком объемны для включения в данную статью. Вы можете извлечь их из проекта my-build-participant на Github и модифицировать по собственному усмотрению.
Сборка плагина engine
Для развертывания в Jazz Build Engine выполните сборку плагина common, а затем плагина engine, используя build.update.jar Ant Targets. Затем скопируйте jar-архивы в каталог plugins Jazz Build Engine: ${JBE_HOME}/jazz/buildsystem/buildengine/eclipse/plugins
. Перезапустите демон Jazz Build Engine, активизированный в разделе Установка Jazz Build Engine.
В файлах build-engine.xml и build-common.xml прилагаемого проекта можно просто выполнить deploy.to.build.engine, который удаляет существующие плагины и развертывает новые. Но по-прежнему нужно будет вручную перезапустить Jazz Build Engine.
При использовании прилагаемого проекта убедитесь, что используется папка /config. Эта папка содержит свойства нашего плагина. Свойства в /config/host/local/<имяхоста>-build.properties имеют приоритет над /config/plugin-build-defaults.properties.
jar-файлы engine и common готовы к развертыванию на любом сервере, совместимом с Jazz Build Engine.
Сборка плагина client
Для запуска плагина client щелкните правой кнопкой мыши на проекте com.ibm.rtcexts.mybuildparticipant.client и выберите Run As > Eclipse Application. Откроется новый экземпляр Eclipse с загруженным плагином.
Пакетирование и выпуск плагина client
Для распространения плагина client создайте репозиторий p2. Для этого инфраструктура Eclipse должна удовлетворять ряду требований. Я рекомендую использовать рабочую область client в рабочей области load из проекта build label, поскольку многое там уже сделано. Создание репозитория p2 является задачей исключительно Eclipse Plugin Development. Я написал краткое руководство для тех, кто не знаком с Eclipse Plugin Development, поскольку это непростая задача.
Создайте репозиторий p2, используя проект updatesite. Для реального предоставления плагинов через репозиторий p2 используйте функциональность Eclipse. Создайте проект Eclipse Feature Project, выбрав File > New > Other.
Укажите свойства в соответствии с рисунком 4.
- В поле Project name введите
com.ibm.rtcexts.mybuildparticipant.feature
.
- Отметьте флажок Use default location.
- В поле Feature ID введите
com.ibm.rtcexts.mybuildparticipant.feature
.
- В поле Feature Name введите
com.ibm.rtcexts.mybuildparticipant.feature
.
- В поле Feature Version введите
1.0.0
.
- В поле Feature Provider введите
IBM
.
- Поле Install Handler Library оставьте незаполненным.
Рисунок 4. Свойства проекта My Build Participant
На следующей странице выберите плагины client и common и нажмите кнопку Finish.
Щелкните правой кнопкой мыши на feature.xml и выберите PDE Tools > Create Ant File.
Теперь создайте проект updatesite, выбрав File > New > Other, и назовите его com.ibm.rtxexts.mybuildparticipant.updatesite
. Откройте site.xml в проекте updatesite и нажмите Add Feature для выбора созданного ранее проекта feature.
Для сборки плагина с помощью Ant необходимо изменить конфигурацию выполнения Ant. Щелкните правой кнопкой мыши на желаемом назначении и выберите Run As > Ant build. Измените конфигурацию Ant, выбрав вкладку JRE и отметив флажок Run in the same JRE as the workspace в области Runtime JRE. Если этого не сделать, могут появляться ошибки taskdef not found для заданий Eclipse Ant.
Наконец, выполните сборку плагина client. Запустите Ant-задание build.update.jar для каждого проекта в следующем порядке:
build-common.xml > build-client.xml > build-feature.xml
Теперь откройте site.xml в проекте updatesite. Выделите feature в Site Map и нажмите Build.
Создайте zip-архив сгенерированных файлов в корневом каталоге проекта updatesite.
Листинг 13. Bash-команда для архивирования репозитория p2
zip -rp ~/load.workspace.from.label.client.p2Repo_1.0.1.zip features plugins artifacts.jar content.jar
Это все! Теперь можно передать этот репозиторий p2 другим пользователям Rational Team Concert, которые могут установить плагин client в Eclipse, выбрав Help > Install New Software и указав архивный файл.
Рисунок 5. Установка клиентского плагина my new build participant как репозитория p2 в Eclipse
Note:
Чтобы увидеть плагин, снимите отметку с флажка Group items by Category, поскольку мы не создавали категорию в проекте updatesite.
И последнее замечание по упаковке плагина client. Я не смог настроить автоматическую сборку updatesite с использованием Eclipse API для генерирования корректного репозитория p2. Однако я сохранил мои попытки в файле build.xml проекта updatesite в примере сборки load workspace from label. Если у вас получится это сделать, оставьте комментарий.