The plugin provides support to develop TeamCity plugins, creating agent and server side archives, publishing them to plugins portal, downloading and installing a TeamCity server and tasks to deploy, start and stop the server and agent.
To build the plugin and run the unit tests run
./gradlew -s check
To run the functional tests run
./gradlew -s functionalTest
To test the samples run
./gradlew -s samplesTest
The plugin archive published to the Gradle Plugin Portal contains four plugins:
-
com.github.rodm.teamcity-server
- Provides tasks to package a TeamCity plugin, deploy and undeploy the plugin to a TeamCity server, and tasks to start and stop the server and default agent. -
com.github.rodm.teamcity-agent
- Provides tasks to package the Agent side of a TeamCity plugin. -
com.github.rodm.teamcity-common
- Adds thecommon-api
dependency to a project. -
com.github.rodm.teamcity-environments
- Adds tasks to download, install, start and stop a TeamCity Server and Build Agent.
Refer to the Gradle Plugin Portal for instructions on how to apply the server, agent, common and environments plugins.
The plugins add the following configurations.
-
provided
: Theprovided
configuration is used to define dependencies required at compile time but not to be included in the plugin. By default the plugins add theagent-api
andserver-api
dependencies when thejava
plugin is also applied. -
agent
: Theagent
configuration is used to define additional dependencies to be included in the agent plugin lib directory when used with the agent plugin. When used with the server plugin the dependencies are added to the agent directory of the plugin archive. -
server
: Theserver
configuration is used to define additional dependencies to be included in the server plugin lib directory when used with the server plugin. -
plugin
: Theplugin
configuration is used by the agent and server plugins to publish the agent and server plugin archives.
The following properties are defined in the teamcity
configuration block. The version property controls the version
of the TeamCity API dependencies added to the provided
configuration. The plugin descriptor can be specified as a
path to a file or by a configuration block within the build script.
-
version
: The version of the TeamCity API to build against. Defaults to '9.0'. -
defaultRepositories
: The defaultRepositories flag controls adding the default repositories to the build. By default Maven Central and the TeamCity repository, https://download.jetbrains.com/teamcity-repository, are configured for resolving dependencies. Setting this flag to false allows a local repository to be used for resolving dependencies.
The plugin when applied with the Java Plugin, adds the JetBrains Maven repository and adds the TeamCity server-api
,
server-web-api
and tests-support
dependencies to the provided
and testImplementation
configurations. If the
Java Plugin is not applied the plugin provides only the tasks to package and publish the server side plugin archive
if a plugin descriptor is defined.
The server plugin can be combined with the agent plugin in the same project but not with the Java Plugin.
The following properties can be defined in the server
configuration block.
-
descriptor
: The plugin descriptor, the descriptor can be defined within the build script or reference an external file. -
tokens
: The tokens property is a map of tokens to be replaced in the descriptor file with values. This only applies if the descriptor is referencing an external file. -
files
: The files property is a CopySpec that defines additional files to be included in the plugin archive. -
archiveName
: The archiveName property defines the name of the plugin archive output by theserverPlugin
task. Defaults to the name of the project and the project version.
The plugin descriptor properties are shown in the examples below and described in the TeamCity documentation for Server-Side Plugin Descriptor
-
serverPlugin
: Builds and packages a TeamCity plugin. The task performs validation of the plugin descriptor and outputs a warning if a required value is missing. -
publishPlugin
: Publishes a plugin to the JetBrains TeamCity Plugin Repository -
generateDescriptor
: If the descriptor is defined in the build script this task is enabled and will output the descriptor to the build directory. -
processDescriptor
: If the descriptor is defined as an external file this task is enabled and will copy the file to the build directory. ('build/descriptor/server')
The plugin enhances the jar
task to perform validation of the bean definition file and outputs a warning if
no beans are defined or if a class is missing from the jar file.
Plugin descriptor defined in the build script.
teamcity {
// Use TeamCity 2017.1 API
version = '2017.1'
// Plugin descriptor
server {
descriptor {
// required properties
name = project.name
displayName = 'TeamCity Plugin'
version = project.version
vendorName = 'vendor name'
// optional properties
description = 'Example TeamCity plugin'
downloadUrl = 'download url'
email = 'me@example.com'
vendorUrl = 'vendor url'
vendorLogo = 'vendor logo'
useSeparateClassloader = true
allowRuntimeReload = true
minimumBuild = '10'
maximumBuild = '20'
parameters {
parameter 'name1', 'value1'
parameter 'name2', 'value2'
}
dependencies {
plugin 'plugin1-name'
plugin 'plugin2-name'
tool 'tool1-name'
tool 'tool2-name'
}
}
// Additional files can be included in the server plugin archive using the files configuration block
files {
into('tooldir') {
from('tooldir')
}
}
}
}
Plugin descriptor defined in an external file at the root of the project. A map of tokens to be replaced in the
descriptor file can be provided using the tokens
property.
teamcity {
// Use TeamCity 2017.1 API
version = '2017.1'
server {
// Locate the plugin descriptor in the root directory of the project
descriptor = file('teamcity-plugin.xml')
tokens = [VERSION: project.version, VENDOR_NAME: 'vendor name']
}
}
The following example uses the Kotlin DSL.
teamcity {
version = "2017.1"
server {
descriptor {
// required properties
name = project.name
displayName = "TeamCity Plugin"
version = project.version as String?
vendorName = "vendor name"
// optional properties
description = "Example TeamCity plugin"
downloadUrl = "download url"
email = "me@example.com"
vendorUrl = "vendor url"
vendorLogo = "vendor logo"
useSeparateClassloader = true
allowRuntimeReload = true
minimumBuild = "10"
maximumBuild = "20"
parameters {
parameter("name1", "value1")
parameter("name2", "value2")
}
dependencies {
plugin("plugin1-name")
plugin("plugin2-name")
tool("tool1-name")
tool("tool2-name")
}
}
files {
into("tooldir") {
from("tooldir")
}
}
}
}
The publishPlugin
task is used to upload the plugin archive to the
JetBrains TeamCity Plugin Repository. Before publishing a plugin you will need
to create a JetBrains Account, follow the '#' link at the top of the plugin repository page.
The publishPlugin
task cannot be used to publish new plugins, the first upload must be completed using the
Upload plugin link on the plugin repository website.
The publishPlugin
task requires a username and password or a JetBrains Hub token to
publish a plugin to the repository as shown in the following examples. As of August 2019 the use of username
and
password
for publishing is deprecated and no longer supported by the
JetBrains TeamCity Plugin Repository.
The following example configures the publish task.
publishPlugin {
username = findProperty('jetbrains.username')
password = findProperty('jetbrains.password')
}
The following example uses the Kotlin DSL.
tasks.withType<PublishTask> {
username = findProperty("jetbrains.username") as String?
password = findProperty("jetbrains.password") as String?
}
The following example uses a Hub token.
publishPlugin {
token = findProperty('jetbrains.token')
}
The username and password or token can also be configured in the publish
section of the server
configuration as
shown in the following example. Optionally one or more channels can be specified using the channels
property,
by default the plugin is published to the 'Stable' channel.
teamcity {
server {
descriptor {
...
}
publish {
channels = ['Beta']
// either
username = findProperty('jetbrains.username')
password = findProperty('jetbrains.password')
// or
token = findProperty('jetbrains.token')
}
}
}
It is recommended that the credentials for the JetBrains Plugin Repository are stored in $HOME/.gradle/gradle.properties
.
The plugin when applied with the Java Plugin, adds the JetBrains Maven repository and adds the TeamCity agent-api
and
tests-support
dependencies to the provided
and testImplementation
configurations. If the Java Plugin is not
applied the plugin provides only the tasks to package the agent side plugin archive if a plugin descriptor is defined.
The following properties can be defined in the agent
configuration block.
-
descriptor
: The plugin descriptor, the descriptor can be defined within the build script or reference an external file. -
tokens
: The tokens property is a map of tokens to be replaced in the descriptor file with values. This only applies if the descriptor is referencing an external file. -
files
: The files property is a CopySpec that defines additional files to be included in the plugin archive. -
archiveName
: The archiveName property defines the name of the plugin archive output by theagentPlugin
task. Defaults to the name of the project, if theteamcity-agent
plugin andteamcity-server
plugin are applied to the same project the agent plugin archive is appended with '-agent' and the project version.
The plugin descriptor properties are shown in the examples below and described in the TeamCity documentation for Agent-Side Plugin Descriptor
-
agentPlugin
: Builds and packages the agent side of a TeamCity plugin. The artifacts defined on the 'agent' configuration are added to the lib directory of the agent plugin archive. The task performs validation of the plugin descriptor and outputs a warning if a required value is missing. -
generateAgentDescriptor
: If the descriptor is defined in the build script this task is enabled and will output the descriptor to the build directory. -
processAgentDescriptor
: If the descriptor is defined as an external file this task will copy the file to the build directory. ('build/descriptor/agent')
The plugin enhances the jar
task to perform validation of the bean definition file and outputs a warning if
no beans are defined or if a class is missing from the jar file.
Agent side plugin descriptor
teamcity {
version = teamcityVersion
agent {
descriptor {
pluginDeployment {
useSeparateClassloader = false
executableFiles {
include 'file1'
include 'file2'
}
}
dependencies {
plugin 'plugin-name'
tool 'tool-name'
}
}
}
}
Agent tool descriptor
teamcity {
version = teamcityVersion
agent {
descriptor {
toolDeployment {
executableFiles {
include 'tooldir/file1'
include 'tooldir/file2'
}
}
dependencies {
plugin 'plugin-name'
tool 'tool-name'
}
}
// Additional files can be included in the agent plugin archive using the files configuration block
files {
into('tooldir') {
from('tooldir')
}
}
}
}
The following example uses the Kotlin DSL.
extra["teamcityVersion"] = findProperty("teamcity.version") ?: "10.0"
teamcity {
version = extra["teamcityVersion"] as String
agent {
descriptor {
pluginDeployment {
useSeparateClassloader = false
executableFiles {
include("file1")
include("file2")
}
}
dependencies {
plugin("plugin-name")
tool("tool-name")
}
}
files {
into("tooldir") {
from("tooldir")
}
}
}
}
Applying this plugin provides tasks to download, install, start and stop a TeamCity Server and Build Agent. This allows a plugin to be debugged or tested against multiple versions of TeamCity.
The environments configuration is available by applying the com.github.rodm.teamcity-environments
plugin.
The following properties can be defined in the environments
configuration block.
-
downloadsDir
: The directory the TeamCity installers are downloaded to. Defaults todownloads
-
baseDownloadUrl
: The base URL used to download the TeamCity installer. Defaults tohttps://download.jetbrains.com/teamcity
. -
baseHomeDir
: The base directory for a TeamCity install. Defaults toservers
. -
baseDataDir
: The base directory for a TeamCity Data directory. Defaults todata
.
The following Gradle properties can be used to override the shared environment properties from the command line or by setting a value in a gradle.properties file.
-
teamcity.environments.downloadsDir
-
teamcity.environments.baseDownloadUrl
-
teamcity.environments.baseDataDir
-
teamcity.environments.baseHomeDir
Within the environments
configuration block multiple TeamCity environments can be defined, each environment
supports the following properties
-
version
: The TeamCity version, the version of TeamCity to download and install locally. Defaults to '9.0'. -
downloadUrl
: The URL used to download the TeamCity installer. Defaults to${baseDownloadUrl}/TeamCity-${version}.tar.gz
. -
homeDir
: The path to a TeamCity install. Defaults to${baseHomeDir}/TeamCity-${version}
-
dataDir
: The path to the TeamCity Data directory. Defaults to${baseDataDir}/${version}
, version excludes the bug fix digit. -
javaHome
: The path to the version of Java used to run the server and build agent. Defaults to the Java used to run Gradle. -
serverOptions
: Options passed to the TeamCity server via theTEAMCITY_SERVER_OPTS
environment variable. Default '-Dteamcity.development.mode=true -Dteamcity.development.shadowCopyClasses=true' these plugin development settings are described on the Development Environment page. -
agentOptions
: Options passed to the TeamCity agent via theTEAMCITY_AGENT_OPTS
environment variable. -
plugins
: The collection of plugins to be deployed to the TeamCity server for this environment. Defaults to the plugin output by theserverPlugin
task when thecom.github.rodm.teamcity-server
plugin is also applied.
For each environment the following tasks are created based on the environment name:
-
deployTo<environment>
: Deploys one or more plugin archives to the TeamCity server for the environment, requires the environmentdataDir
property. If the environment is using TeamCity version 2018.2 or later and the server is running, the deploy task will send unload and load requests to the server. This allows changes to be made to the plugin without having to restart the server. Note that this feature currently relies on the file name of the plugin not changing between deploys. -
undeployFrom<environment>
: Un-deploys one or more plugin archives from the TeamCity server for the environment, requires the environmentdataDir
property. -
start<environment>Sever
: Starts the TeamCity Server for the environment, requires the environmenthomeDir
anddataDir
properties to be defined. -
stop<environment>Server
: Stops the TeamCity Server for the environment, requires the environmenthomeDir
property to be defined. -
start<environment>Agent
: Starts the default TeamCity Build Agent for the environment, requires the environmenthomeDir
property to be defined. -
stop<environment>Agent
: Stops the default TeamCity Build Agent for the environment, requires the environmenthomeDir
property to be defined. -
install<environment>
: Downloads and installs TeamCity for the environment, this tasks uses thedownloadBaseUrl
and the environmenthomeDir
properties.
teamcity {
// Use TeamCity 2017.1 API
version = '2017.1'
server {
// Locate the plugin descriptor in the root directory of the project
descriptor = file('teamcity-plugin.xml')
}
environments {
// use a local web server for downloading TeamCity distributions
baseDownloadUrl = "http://repository/"
// store the downloaded TeamCity distributions in /tmp
downloadsDir = '/tmp'
// base properties for TeamCity servers and data directories
baseHomeDir = 'teamcity/servers'
baseDataDir = 'teamcity/data'
teamcity91 {
version = '9.1.7'
javaHome = file('/opt/jdk1.7.0_80')
// Add to the default server options
serverOptions '-Dproperty=value'
serverOptions '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5500'
}
teamcity20172 {
version = '2017.2.4'
downloadUrl = 'http://repository/teamcity/TeamCity-2017.2.4.tar.gz'
homeDir = file("$rootDir/teamcity/servers/TeamCity-2017.2.4")
dataDir = file("$rootDir/teamcity/data/2017.2")
javaHome = file('/opt/jdk1.8.0_202')
// Replace the default server options
serverOptions = '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5500'
}
'teamcity2018.2' {
version = '2018.2.2'
javaHome = file('/opt/jdk1.8.0_202')
}
}
}
The following example shows environments being configured using the Kotlin DSL.
extra["downloadsDir"] = project.findProperty("downloads.dir") ?: "${rootDir}/downloads"
extra["java7Home"] = project.findProperty("java7.home") ?: "/opt/jdk1.7.0_80"
extra["java8Home"] = project.findProperty("java8.home") ?: "/opt/jdk1.8.0_202"
teamcity {
version = "2017.1"
server {
descriptor = file("teamcity-plugin.xml")
}
environments {
baseDownloadUrl = "http://repository/"
downloadsDir = extra["downloadsDir"] as String
baseHomeDir = "teamcity/servers"
baseDataDir = "${rootDir}/data"
operator fun String.invoke(block: TeamCityEnvironment.() -> Unit) {
environments.create(this, closureOf(block))
}
"teamcity9" {
version = "9.1.7"
javaHome = file(extra["java7Home"])
// Add to the default server options
serverOptions("-Dproperty=value")
serverOptions("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5500")
}
"teamcity2017.2" {
version = "2017.2.4"
javaHome = file(extra["java8Home"] as String)
// Replace the default server options
setServerOptions("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5500")
}
"teamcity2018.2" {
version = "2018.2.2"
}
}
}
fun Project.teamcity(configuration: TeamCityPluginExtension.() -> Unit) {
configure(configuration)
}
The samples directory contains a number of projects using the plugin.
The following projects use the plugin.