TeamCity REST API Reference 2024.07 Help

Start and Cancel Builds

In this article, we explore common use cases concerning starting and canceling builds via TeamCity REST API:

  • Starting a TeamCity build from an external software.

  • Implementing a complex build logic by invoking REST API from the Command Line build runner.

Start Regular Build

To be able to start a build, you need to access the build queue via this endpoint:

/app/rest/buildQueue

Queueing a new build requires two steps:

  1. Prepare the request payload (that is, the Build entity) which will represent the target build.

  2. Send a POST request with the payload.

Step 1:

The payload of this Build entity must include a reference to a build configuration (or, in REST API terms, BuildType). We will include it as a sub-entity of Build.

<build> <buildType id="buildConfID"/> </build>
{ "buildType": { "id": "buildConfID" } }

Step 2:

To add a build to the queue, send a POST request with the body specified in Step 1:

/app/rest/buildQueue

The request headers should include an authorization header (unless the guest authorization scheme is used) and, optionally, Content-Type/Accept headers.

The endpoint will respond with a short description of the launched build. It will also include the TCSESSIONID cookie: you can reuse it to skip authorization in the following runs.

Start Custom Build

A more complex example is when you need to run a build with settings that differ from those specified in its build configuration. In this case, you need to send extra data about the build in your request.

From the fields available for the Build entity, we will pass the following:

  • personal: to define that the build is personal

  • branchName: to launch a build in a non-default branch

  • agent: to select a specific agent for this build by sending an Agent sub-entity

  • comment: to supply a build with a description

  • properties: to set custom build parameters (or create them, if no such parameters are present) by sending a composite Properties entity.

Most of the data should be available locally. However, in this example we request a specific agent which requires knowing its ID. If you know an agent by name, you can find its ID by sending the following request:

/app/rest/agents?locator=name:myAgentName

Here, the ?locator=... part specifies an AgentLocator entity which is used to find the agent by name. The request will return the respective Agent entity from which you can parse out an ID.

The eventual payload for our POST request will look as follows:

<build personal="true" branchName="myBranch"> <buildType id="MyBuildConfigID"/> <comment> <text>Build for testing REST API</text> </comment> <agent id="286"/> <properties> <property name="system.existingParameter" value="myValue"/> <property name="env.newPasswordParameter" value="mySecret"> <type rawValue="password"/> </property> </properties> </build>
{ "branchName": "myBranch", "personal": true, "buildType": { "id": "MyBuildConfigID" }, "comment": { "text": "Build for testing REST API" }, "agent": { "id": 286 }, "properties": { "property": [{ "name": "system.existingParameter", "value": "myValue" }, { "name": "env.password", "value": "mySecret", "type": { "rawValue": "password" } } ] } }

Send it via a POST request as in the basic case. As a result, a personal build will be run in the myBranch branch on the specified agent and with two new build parameter values.

Rebuild All Dependencies

This sample demonstrates how to rerun a build that belongs to a build chain, and specify that it should run in a clean checkout folder with all dependency builds rebuilt anew.

To do so, specify the required triggeringOptions properties inside the Build entity. This fields accepts objects of the BuildTriggeringOptions type.

<build> <triggeringOptions cleanSources="true" rebuildAllDependencies="true" queueAtTop="true"/> <buildType id="buildConfID"/> </build>
{ "buildType": { "id": "buildConfID" }, "triggeringOptions": { "cleanSources": true, "rebuildAllDependencies": true, "queueAtTop": true } }

Run a Build for the Specific Changes Revision

When you trigger a build with the default settings, TeamCity runs it against the latest available changes. If you need to build a specific changes revision instead, POST a request with the following payload to the /app/rest/buildQueue endpoint. Note that to specify a branch name, you need a shortened (logical) branch name in the build object, and full branch name according to the VCS specification in the revision object.

<build branchName="feature1"> <buildType id="buildConfID"/> <revisions> <revision version="57ef8447c7e277eda9d4e3ce433795d5eb755a64" vcsBranchName="refs/heads/feature1"> <vcs-root-instance vcs-root-id="vcsRootId"/> </revision> </revisions> </build>
{ "branchName": "feature1", "buildType": { "id": "buildConfID" }, "revisions": { "revision": [ { "version": "57ef8447c7e277eda9d4e3ce433795d5eb755a64", "vcsBranchName": "refs/heads/feature1", "vcs-root-instance": { "vcs-root-id": "vcsRootId" } } ] } }

The sample payload above specifies one revision and one VCS root. If a triggered build uses multiple roots and/or triggers dependent configurations, all affected root instances that match the specified root will use the same revision as well. Other roots (roots for which you did not specify a revision) will use the latest repository version. You can add the failOnMissingRevisions="true" attribute to the revisions object to prevent roots with unspecified revisions from using the latest changeset a force a request with incomplete payloads to fail. In this case you need to specify revisions for all VCS roots involved. To do this, add multiple revision instances to the revisions collection.

<build> <buildType id="buildConfID"/> <revisions> <revision version="57ef8447c7e277eda9d4e3ce433795d5eb755a64" vcsBranchName="refs/heads/main"> <vcs-root-instance vcs-root-id="vcsRootId1"/> </revision> <revision version="9706526a5f3c428dc983d1d21123f7131a983240" vcsBranchName="refs/heads/main"> <vcs-root-instance vcs-root-id="vcsRootId2"/> </revision> <!-- other revisions --> </revisions> </build>
{ "buildType": { "id": "buildConfID" }, "revisions": { "revision": [ { "version": "57ef8447c7e277eda9d4e3ce433795d5eb755a64", "vcsBranchName": "refs/heads/main", "vcs-root-instance": { "vcs-root-id": "vcsRootId1" } }, { "version": "9706526a5f3c428dc983d1d21123f7131a983240", "vcsBranchName": "refs/heads/main", "vcs-root-instance": { "vcs-root-id": "vcsRootId2" } }, // other revisions ] } }

To invoke a Perforce Shelve Trigger and run a build against a specific changelist, use the following endpoint:

POST /app/perforce/runBuildForShelve?buildTypeId=<BuildConfigurationID>&vcsRootId=<VCSRootID>&shelvedChangelist=<ChangelistID>

Get Queued Build

After queueing a build, you can check its status:

/app/rest/buildQueue?locator=<BuildQueueLocator>

where BuildQueueLocator represents a queued build — you can supply the build ID you received on sending the POST request.

This request returns a Build entity. By default, TeamCity will return basic fields of the entity. For polling purposes, you might want to receive only the build status. You can limit the scope of fields available in the response by using the ?fields parameter in the request path (read more):

/app/rest/buildQueue?locator=id:<myBuildID>&fields=build(id,state)

As a result of the call, TeamCity will return the Build entity with only two fields populated: id and state.

Cancel Queued Build

To cancel a just queued build, send:

/app/rest/buildQueue/<queuedBuildLocator>

where a BuildCancelRequest entity is used as a payload.

This entity comprises two fields:

  • comment: to provide an optional comment on why the build was canceled

  • readdIntoQueue: a boolean property which declares if this is a request to restore a previously canceled build; as we are aiming to cancel the build, not to restore it, we will set it to false

The resulting payload:

<buildCancelRequest comment='Canceling a queued build' readdIntoQueue='false'/>
{ "comment": "Canceling a queued build", "readdIntoQueue": false }

To cancel a build by its ID, send:

/app/rest/buildQueue/id:<build ID>

Alternatively, you may choose to simply delete a queued build (if you don't need its metadata). To do so, run a DELETE request on the same endpoint:

/app/rest/buildQueue/id:<build ID>

Cancel Started Build

To cancel a build that has already started, send:

/app/rest/builds/<buildLocator>

with the same BuildCancelRequest entity as in the above example:

<buildCancelRequest comment='Canceling a running build' readdIntoQueue='false'/>
{ "comment": "Canceling a running build", "readdIntoQueue": false }

To cancel a build by its ID, send:

<TeamCity URL>:[<port>]/app/rest/builds/id:<build ID>

Trigger Chain Builds

In TeamCity, you can organize builds from different configurations to run in a single chain. For example, you can have a chain of three build configurations that ends with a composite build to aggregate build results: ConfigA → ConfigB → ConfigC → ChainABC.

To start an entire chain, trigger a new build for the last build configuration:

/app/rest/buildQueue
<build> <buildType id="ChainABC"/> </build>
{ "buildType": { "id": "ChainABC" } }

If you trigger a new build for a configuration that is not the last one in a chain, only this configuration and those on which it depends will run. For example, the following payload triggers only the ConfigA → ConfigB sequence (ConfigB depends on ConfigA).

<build> <buildType id="ConfigB"/> </build>
{ "buildType": { "id": "ConfigB" } }

Reusing Builds with Direct Dependencies

When triggering a dependent build, you can specify a finished build of a preceding configuration which this new build should reuse. For example, the following payload triggers a new ConfigB build that should reuse an existing ConfigA build with the "4976" ID.

<build> <buildType id="ConfigB"/> <snapshot-dependencies count="1"> <build id="4976" buildTypeId="ConfigA"/> </snapshot-dependencies> </build>
{ "buildType": { "id": "ConfigB" }, "snapshot-dependencies": { "count": 1, "build": [{ "id": 4976, "buildTypeId": "ConfigA" }] } }

You can specify multiple direct dependencies in the same request. For instance, if ConfigA and ConfigB are independent configurations and ConfigC depends on both of them, you can send the following payload:

<build> <buildType id="ConfigC"/> <snapshot-dependencies> <build id="4997" buildTypeId="ConfigA"/> <build id="4998" buildTypeId="ConfigB"/> </snapshot-dependencies> </build>
{ "buildType": { "id": "ConfigC" }, "snapshot-dependencies": { "build": [ { "id": 4997, "buildTypeId": "ConfigA" }, { "id": 4998, "buildTypeId": "ConfigB" }] } }
Reuse both direct builds

Reusing Builds with Indirect Dependencies

In the previous section, requests reused builds of a configuration on which triggered builds directly depend. However, you can also reuse builds in indirect dependencies.

For example, for the same ConfigA → ConfigB → ConfigC chain you can trigger ConfigC build that should reuse an existing ConfigA build.

/app/rest/buildQueue
<build> <buildType id="ConfigC"/> <snapshot-dependencies count="1"> <build id="4976" buildTypeId="ConfigA"/> </snapshot-dependencies> </build>
{ "buildType": { "id": "ConfigC" }, "snapshot-dependencies": { "count": 1, "build": [{ "id": 4976, "buildTypeId": "ConfigA" }] } }

A new ConfigB build will or will not run depending on ConfigC's dependency settings. If ConfigC allows reusing suitable builds, both ConfigA and ConfigB builds will be reused.

Reuse both builds

Otherwise, if ConfigC always requires a fresh build, a new ConfigB build will run (using results from an existing ConfigA build).

Reuse one build
Last modified: 17 July 2024