我开始扩展IBM®Rational Team Concert™,以改善客户的连续交付过程。 客户端需要一个插件,该插件将使用新的环境构建参数从以前的构建中重新创建软件包,以便为更高环境创建发行版。 该插件将取代耗时2个小时且容易出错的手动流程。
我写的标签插件的加载工作区是作为预构建参与者运行的。 构建前,构建和构建后参与者包含一个Java类,该Java类可在构建过程中由Jazz Build Engine运行。 几个构建参与者组成一个构建定义。 此代码作为插件存在于eclipse文件夹中,该文件夹位于构建服务器上Build Engines安装目录内。
标签构建参与者加载工作空间的功能如下:
- 从Eclipse客户端UI中将构建定义和构建标签作为用户参数。
- 验证输入是否属于单个成功的构建结果
- 从关联的构建结果的快照(在Rational Team Concert SDK中称为基准集)创建一个新的工作空间。
- 使用新工作空间更新当前构建的工作工作空间。
- 在jazzscm插件之前执行,因此jazzscm插件将继续正常运行,不同之处在于,它现在加载了新创建的工作空间,该工作空间包含与与用户提供的构建定义ID和构建标签相关联的原始构建相同的源代码。
标签插件中加载工作区的源代码在Github上可用。
该解决方案的构建参与者代码在本文中是多余的,因此我决定逐步介绍一个简单的方案,并创建了我的构建参与者插件。 本文介绍的插件功能如下:
- 在Eclipse客户端中接受用户输入
- 将用户输入记录到构建日志中
- 获取启动构建的用户的名称以及工作空间的通用唯一标识符(UUID),并使用Rational Team Concert API用用户名和工作空间UUID标记构建。
可以在Github上下载本文讨论的我的构建参与者插件的源代码。
先决条件
为了扩展Rational Team Concert插件,对Eclipse插件开发和插件开发环境(PDE)的了解将非常有价值。 我将在本文中以逐步指南的形式描述完整的实现,并且为了清楚起见,我已经确定了创建通用Eclipse插件的细节,而不是特定于Rational Team Concert插件开发的细节。
搭建开发环境
必须为您的Rational Team Concert版本下载正确的SDK,Plain Java API,Jazz Build Engine和Eclipse客户端插件。 例如,如果您正在使用Rational Team Concert的4.0.0,则不能使用4.0.6 SDK。
Rational Team Concert和SDK的本地安装
需要用于创建插件的开发环境。 Jazz.net上的Rational Team Concert 4.x扩展研讨会包含分步安装指南,用于在实验1-设置IBM Rational Team Concert SDK中设置开发环境。 我尚未在版本5中尝试过此操作,因此如果本指南需要任何更改,请添加到注释中。 在安装Rational Team Concert时,请确保选择选项以同时安装Jazz Build Engine。
安装Rational Team Concert Eclipse客户端插件的最简单方法是将其导入为p2存储库。 浏览至您的Rational Team Concert版本的发行页面,然后单击All Downloads 。 找到然后下载RTC-Client-p2Repo-XXXzip文件。 在Eclipse中的帮助>安装新软件中安装插件,然后将p2存储库添加为归档文件。
使Rational Team Concert在本地运行至少需要一个小时。 我建议您这样做,因为您将了解,开发插件是一个反复的过程。 如果您在创建过程中无意中破坏了每个构建并弄乱了构建定义,那么没有开发人员会感谢您。
Jazz Build Engine安装
Jazz Build Engine初始化运行构建脚本并收集输出的过程。 它在构建服务器上作为Java进程运行,并等待来自客户端的构建指令。
在本地安装Jazz Build Engine。 建议您从目标构建服务器复制此文件,以便100%确信您正在使用同一版本,但是也可以通过Rational Team Concert 本地安装中的Rational Team Concert安装程序和SDK部分。
在Linux中,通过发出清单1中所示的命令并输入先前在安装说明中创建的Rational Team Concert用户(即构建用户)的密码来创建加密的密码文件。
清单1.用于创建加密密码文件的bash命令
${JBE_HOME}/jazz/buildsystem/buildengine/eclipse/jbe -createPasswordFile <output_password_file>
要在Linux中将Jazz Build Engine作为守护程序启动,请使用清单1中的命令发出命令。请确保替换适当的变量值。
清单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" # matches the build engine name in RTC
ENGINE_USER="myadmin" # RTC user ID to use for the build engine
ENGINE_PWFILE="<output_password_file>" # Generated in Code Snippet 1
JBE_LOGFILE="/tmp/jazzbuildengine/jbe_test.log" # Location to write JBE log files
JBE_WORKSPACE="/tmp/plugin_engine_workspace" # JBEs Eclipse Workspace
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客户机中的定制编辑器,它接受并验证用户输入。
- 一个新的构建定义模板,包括构建参与者。
- 记录用户输入并使用以下内容标记构建的构建参与者:触发它的用户ID和工作区UUID。
这个Rational Team Concert扩展需要3个独立的插件:
- 安装在Jazz Build Engine的安装插件目录中的引擎插件。
- 一个客户端插件,它作为独立的Eclipse插件安装,并作为p2存储库导入(与Rational Team Concert Client相同的过程)。
- 通用插件。 通用插件包含在p2存储库中,并作为单独的插件安装在Jazz Build Engine中。
在开发Eclipse插件时,请指定目标平台,该平台向集成开发环境(IDE)提供应用程序在其中运行的上下文。 例如,插件和库在运行时可用。 这里的问题是,您正在针对两个目标平台进行开发,即Jazz Build Engine和Rational Team Concert Eclipse客户端。 它们包含不同的库和插件,这就是为什么您必须同时创建引擎和客户端插件的原因。 需要公共插件以确保两个插件之间的无缝集成。
在下一节中,我将提供创建此方法的方法以及开发它所需的Eclipse工作区设置。
Eclipse工作区设置
至此,您已深入到Eclipse插件开发领域。 为了进一步清晰起见,请参阅Eclipse插件教程,以获取有关我提到的每个步骤的指南。 您还可以参考Jazz.net上的Rational Team Concert 4.x Extensions Workshop中的1.2开发设置一节。
切换到Eclipse中的插件开发视图。 创建两个工作区,每个目标平台一个,分别称为my_build_participant_client和my_build_participant_engine 。
在客户端工作空间中,创建两个项目my_build_participant_client和my_build_participant_common 。 将目标平台设置为在“ 设置开发环境”部分中下载的解压缩的Rational Team Concert SDK。 在客户端插件的项目设置中,在通用插件上创建项目依赖项。 您还需要将通用插件添加到客户端插件构建清单。
在引擎工作区中,创建名为my_build_participant_engine的引擎项目,然后导入my_build_participant_common插件。 将目标平台设置为$ {JBE_HOME} / buildsystem / buildengine / eclipse / plugins 。 在common上创建项目依赖项,然后根据客户端工作区设置导入插件。
记录和调试
现在已经安装了Jazz Build Engine,在调试Jazz Build Engine的插件时,有2条日志对您最有用。
Jazz Build Engine插件
清单2中的Jazz Build Engine日志文件JBE_LOGFILE
是写入Rational Team Concert记录器输出的信息的位置。 该信息还在构建时显示在构建日志中。
清单2中提供给构建引擎的-data
参数JBE_WORKSPACE
在初始化Jazz Build Engine时非常重要。 在此日志中可以识别出有关插件初始化的所有Eclipse错误。
Rational Team Concert Eclipse客户端插件
既然您已经设置了Eclipse工作区,就可以将客户端插件作为Eclipse应用程序启动和调试了。 右键单击客户机项目,然后选择运行方式> Eclipse应用程序或调试方式> Eclipse应用程序 。
可以在许多Eclipse插件教程和Eclipse PDE站点上找到有关调试和日志记录的提示。
开发插件
插件概述
Rational Team Concert扩展分为以下三个插件。
- com.ibm.rtcexts.mybuildparticipant.common
- com.ibm.rtcexts.mybuildparticipant.client
- com.ibm.rtcexts.mybuildparticipant.engine
要在客户端插件构建过程中将客户端组件作为p2存储库发布,还需要另外两个插件,如下面的“ 构建和分发”部分所述。
- com.ibm.rtcexts.mybuildparticipant.feature
- com.ibm.rtcexts.mybuildparticipant.updatesite
引擎插件和通用插件存在于my_build_participant_engine工作空间中,而客户端插件,通用插件,功能插件和updatesite插件存在于my_build_participant_client工作空间中。
像许多Eclipse插件一样,引擎插件和客户端插件也需要plugin.xml,插件清单和激活器类进行初始化。 尽管公共组件也打包为Eclipse插件,但是不需要激活器,因为它永远不会作为独立插件进行初始化,而是仅由引擎和客户端插件引用。 在以下各节中,我将详细描述每个Eclipse插件的实现。
通用插件
通用插件绑定了Jazz Build Engine中运行的插件和Eclipse客户端中运行的插件。 通用插件仅由引擎和客户端插件的扩展使用,因此不需要激活器。 有关激活剂的更多信息,请参见下面。
通用插件最重要的部分是在plugin.xml中。
插件XML
清单3.通用插件的plugin.xml
<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 Plugin Architecture上的这篇文章中了解有关扩展点的更多信息。 这是所有plugin.xml信息中最重要的部分,因为它是将所有内容绑定在一起的对象,因此应存在于通用插件中。 id是客户端和引擎插件如何引用元素的方法。 buildPhase
将配置元素的作用域buildPhase
为给定的构建阶段,该阶段必须与下面的引擎插件中描述的AbstractBuildEngineParticipant
类具有相同的阶段。 通用属性用于将数据绑定到客户端插件中编写的Eclipse表单。 然后,构建引擎可以通过com.ibm.rtcexts.mybuildparticipant
构建配置元素对象访问buildConfigProperty1
和buildConfigProperty2
值。
通用插件的最后一个扩展点是Rational Team Concert buildDefinitionTemplate 。 该扩展点描述了附加的构建定义模板。 该模板规定了在构建生命周期中执行构建参与者的顺序,因此引擎插件要求该模板。 稍后您将看到,在创建构建定义时在Eclipse客户端中选择buildDefinitionTemplate会导致UI选项卡中相关构建参与者的配置可用。
对于我在上一个项目中开发的标签构建参与者的加载工作区,新构建配置元素的运行顺序对其功能至关重要。 com.ibm.rtcexts.mybuildparticipant必须在Jazz SCM插件之前运行,以便我的插件可以更改通过构建检索的源代码。 为了在此进行演示, 我的构建参与者存在于列表的前面。 这两个插件都是预构建参与者,因此它们都在预构建阶段运行。 您可以在“ 引擎插件”部分中找到有关此信息的更多信息。
最后,在通用插件中,我编写了一个简单的类来存储引擎插件和客户端插件都使用的常量。
实施
通用插件不提供这种功能,但是它是在引擎插件和客户端插件之间存储通用属性的好地方。 例如,清单4描述了Build Configuration元素上的属性。
清单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";
}
仅保留构建定义模板和构建配置元素,当创建新的构建定义时,您已经足够看到该模板出现在“ 可用构建模板”列表中,如图1所示。
图1.屏幕快照显示了我的新构建定义作为Available build模板

客户端插件
客户端插件包含Eclipse表单的代码,这些代码捕获了上面创建的我的构建配置元素的属性。
活化剂
eclipse需要activator类来初始化客户端插件。
清单5.客户端插件的Activator类
public class MyBuildParticipantClientPlugin extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "com.ibm.rtcexts.mybuildparticipant.client";
// The shared instance
private static MyBuildParticipantClientPlugin plugin;
//The constructor
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);
}
// Returns the shared instance
public static MyBuildParticipantClientPlugin getDefault() {
return plugin;
}
// Returns an image descriptor for the image file at the given
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
}
激活程序类与您在Eclipse Plugin Development hello world示例中可以找到的类似。 有关此类的更多详细信息,请参阅Eclipse Plugin Development文档和教程 。
清单
然后在清单中指定Bundle-Activator 。
清单6.客户端插件清单
Manifest-Version : 1.0
Bundle-ManifestVersion : 2
Bundle-Name : com.ibm.rtcexts.mybuildparticipant.client
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是基本的,仅描述构建配置元素编辑器本身,这是我们期望客户端提供的内容。
清单7.客户端插件的plugin.xml
<plugin>
<!--The editor tab in the build configuration-->
<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 ,它指向我们之前创建的通用插件中的构建配置元素。 该类指向扩展AbstractConfigurationElementEditor的类的完全限定类名。
实作
我们利用Eclipse表单并创建一个扩展AbstractConfigurationElementEditor的类,以创建用于编辑构建配置元素属性的UI。 为此,我利用了com.ibm.team.build.client中的BasicConfigurationElementEditor 。
清单8.配置元素编辑器的客户端代码
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;
//editor constructor
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
,是用来验证用户的输入。 数据通过在BasicConfigurationElementEditor
类上调用的createConfigPropertyTextField
方法绑定到构建配置元素。
此时,存在足够的代码来实际查看关联的构建定义模板的配置元素编辑器,如图2所示。
图2.与构建定义模板关联的新的构建配置元素编辑器

引擎插件
引擎插件包含在构建过程中实际运行的代码。
活化剂
记住Jazz Build Engine是基于Eclipse的应用程序,您需要通过Eclipse插件对其进行扩展。 需要激活器来初始化插件。
清单9.引擎插件的激活器类
public class MyBuildParticipantEnginePlugin extends Plugin {
// The plug-in ID
public static final String PLUGIN_ID = "com.ibm.rtcexts.mybuildparticipant.engine";
// The shared instance
private static MyBuildParticipantEnginePlugin plugin;
//The constructor
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);
}
//Returns the shared instance
public static MyBuildParticipantEnginePlugin getDefault() {
return plugin;
}
}
激活器类仅与客户端插件不同,因为它没有UI元素,因此更简单。
清单
清单中的Bundle-Activator
属性再次设置为来自激活程序类的PLUGIN_ID
的值。
清单10.引擎的插件清单
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
删除了插件的版本,以使插件更易于移植,并且不易受到较小的升级的影响。 我保留了通用插件的版本,以防万一升级插件时忘记删除旧版本。
插件XML
引擎的plugin.xml仅包含构建引擎参与者。
清单11.引擎插件的plugin.xml
<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
是我们先前在通用插件中定义的构建配置元素的ID。 该类必须指向您创建的标准类名称,并应扩展AbstractBuildEngineParticipant 。 最好将ID与构建参与者类名相同。
实施
在此示例中,您将创建一个预构建参与者以扩展清单12中的AbstractPreBuildParticipant
类。
清单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
方法。 当Jazz Build Engine执行您的构建参与者时,将调用preBuild
方法。
生成参与者要做的第一件事是获取buildDefinitionInstance ,它是一个不可变的对象,与buildDefinition本身相反,后者可能会发生变化。 构建定义用于访问构建配置元素ID,这在通用的plugin.xml中进行了描述。 然后,在公共的plugin.xml中指定的通用属性也可以通过构建配置元素供构建参与者使用。 在这里,这些由构建参与者检索,并通过定制记录器输出到Jazz Build Engine日志。 我们还利用通用插件中的configuration元素类来获取ELEMENT_ID
和PROPERTY_X IDs
。
参与者继续通过构建定义实例获取工作空间UUID,然后通过Jazz Team Repository API获得启动构建的用户的Rational Team Concert用户名。 然后,构建参与者获取当前构建的构建结果的本地工作副本,并确定是否存在任何现有标签。 参与者最终创建标签字符串,并将标签设置在构建结果的本地工作副本上,并通过构建客户端保存它。
结果
图3显示了运行构建参与者时的输出。
图3.构建结果显示成功使用了我的新构建参与者插件

注意使用用户名和工作空间标记的构建。 还要注意,我们的构建配置元素上的用户属性已成功记录。 最后,有趣的是,该插件确实确实按预期的顺序运行,即在jazzscm插件之前。
既然您已经了解了如何使用新的构建参与者扩展Rational Team Concert,以及如何在客户端和引擎插件之间划分职责,我将在本文的结尾处提供一些有用的技巧,以自动化插件的构建和部署。
建立和分配
在自动化构建,测试,打包和部署步骤时,我选择使用Ant。 您可能会选择沿着Maven路线走,并使用Tycho构建项目。 Tyg的创建者Vogella的网站上有一个很好的教程 。 使用自定义的Ant脚本可以更好地满足插件要求。
要创建Ant脚本,请右键单击三个插件中的每个plugin.xml,然后选择PDE Tools> Create Ant Build File 。 目标build.update.jar在build目录中将插件创建为jar文件。 我对这些脚本进行了许多修改,以更好地整合诸如插件名称和版本之类的属性。 这些太大,无法包含在本文中。 您可以从Github上的“ my-build-participant ”项目中提取和修改它们。
引擎插件构建
要部署到Jazz Build Engine,先构建通用插件,然后使用build.update.jar的每个Ant Targets来构建引擎插件。 然后将罐子复制到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/<hostname>-build.properties中的属性优先,其后是/config/plugin-build-defaults.properties 。
现在可以将引擎和通用jar部署到任何兼容的Jazz Build Engine中。
客户端插件构建
要启动客户机插件,请右键单击com.ibm.rtcexts.mybuildparticipant.client项目,然后选择Run As > Eclipse Application 。 这将打开一个新的Eclipse实例,其中已加载了插件。
客户端打包和发布
要分发客户端插件,请创建一个p2存储库。 为此,Eclipse框架有一些要求。 我建议在构建标签项目的加载工作空间中使用客户端工作空间 ,因为许多工作已经完成。 创建p2存储库纯粹是Eclipse插件开发任务。 我为那些不熟悉Eclipse插件开发的人写了一份简短的指南,因为我发现这是一项艰巨的任务。
通过更新站点项目创建p2存储库。 为了通过p2存储库实际公开插件,请使用Eclipse功能。 通过选择File> New> Other创建一个Eclipse Feature Project。
输入图4所示的属性。
- 在项目名称字段中,输入
com.ibm.rtcexts.mybuildparticipant.feature
。 - 选择使用默认位置复选框。
- 在功能部件ID字段中,输入
com.ibm.rtcexts.mybuildparticipant.feature
。 - 在“ 功能名称”字段中,输入
com.ibm.rtcexts.mybuildparticipant.feature
。 - 在功能版本字段中,输入
1.0.0
。 - 在功能提供者字段中,输入
IBM
。 - 将“ 安装处理程序库”字段保留为空。
图4. My Build Participant的Eclipse Feature Project属性

在下一页上,选择客户端和常用插件,然后单击“ 完成”按钮。
右键单击feature.xml,然后选择PDE工具>创建Ant文件 。
现在,在File> New> Other下创建更新站点项目,并将其命名为com.ibm.rtxexts.mybuildparticipant.updatesite
。 在updatesite项目中打开site.xml,然后单击“ 添加功能”以选择先前创建的功能项目。
使用Ant构建插件时,需要修改Ant运行配置。 右键单击所需目标,然后选择运行方式> Ant build 。 通过选择JRE选项卡并选择Runtime JRE下与工作区相同的JRE中的Run来编辑Ant配置。 如果不这样做,则可能会发现在Eclipse Ant任务上出现taskdef not found错误。
最后,您可以构建客户端插件。 按以下顺序为每个项目运行build.update.jar Ant任务:
build-common.xml> build-client.xml> build-feature.xml
现在,在更新站点项目中打开site.xml。 在“ 站点地图”中突出显示该功能,然后单击“ 构建” 。
压缩在updatesite项目的根目录中生成的文件。
清单13.用于压缩p2存储库的Bash命令
zip -rp ~/load.workspace.from.label.client.p2Repo_1.0.1.zip features plugins artifacts.jar content.jar
而已! 现在,您可以将该p2存储库分发给其他Rational Team Concert用户,他们可以通过在Help> Install New Software中将其选择为Archive文件来在Eclipse中安装客户端插件。
图5.安装我的新构建参与者客户端插件,作为Eclipse中的p2存储库

关于包装客户的最后说明。 我还没有设法使用Eclipse API自动构建更新站点来生成有效的p2存储库。 但是,我已经将我的尝试留在了标签构建示例的加载工作空间中的更新站点项目的build.xml文件中。 如果成功,请添加到评论中。