Disable/enable build feature via API

Answered

Listing "build features" assigned to a build config can be done by

http://teamcity:8111/app/rest/buildTypes/<buildTypeLocator>/features/<id>

But is it a way to enable/disable existing build feature over the REST api?

Alternatively how to make a conditional in disabling/enabling build feature?
I'd like to have a prompt parameter to decide (use/not use the build feature).

Thanks,

0
11 comments
Avatar
Fedor Rumyantsev

Hello Tomasz,

Yes, you can update the build feature to set its "disabled" property to true or false. The method is described here; as an easy option, you could first retrieve the build feature in question:

[GET] http://localhost/app/rest/buildTypes/id:<build configuration ID>/features/

and then send a request to update the feature by amending the retrieved feature body (for example, this is my Assembly Patcher feature with an updated "disabled" property:

[PUT] http://localhost/app/rest/buildTypes/id:<build configuration ID>/features/JetBrains.AssemblyInfo
<feature id="JetBrains.AssemblyInfo" type="JetBrains.AssemblyInfo" disabled="true">
<properties count="1">
<property name="assembly-format" value="%system.build.number%"/>
</properties>
</feature>

Unfortunately, build features may not run on a condition; could you please share the use case where this would come handy to you? 

0

I'm runing on 2020.1.1 and I'd like to use conditionally feature VCSlabeling. I know it can be setup after work (in the Action) but I'd like to give users an option (by prompt parameter). The parameter content would be my label to VCS, if empty the feature needs to be disabled (for this run) to do not generate error on Results/Changes page. 

0

I'm able to list my feature

curl --silent --header "Authorization: Bearer xxxxxxxx" --header "Accept: application/json" -X GET https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features|jq

{
"count": 1,
"feature": [
{
"id": "BUILD_EXT_611",
"type": "VcsLabeling",
"properties": {

...

What changes after disabling in UI to

{
"count": 1,
"feature": [
{
"id": "BUILD_EXT_611",
"type": "VcsLabeling",
"disabled": true,
"properties": {

...

I'm able to DELETE the feature with

curl --silent --header "Authorization: Bearer xxxxxxxx" --header "Accept: application/json" -X DELETE https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features/BUILD_EXT_611

But not able to manage only disabled flag.

The other problem is the feature VCSlabeling becomes a new ID every time it is recreated. After deletion and again define (in UI) the id become BUILD_EXT_612. Which is not a case for other features where id==type

0
Avatar
Fedor Rumyantsev

Hello Tomasz,

I see, thank you! Speaking of the use case - unfortunately, the conditional build features are not supported, but you could consider the following setup - suppose you have two configurations based on a common build configuration template, with the only difference of one having VCS labeling feature and another one not. You could then set up a third build configuration - a "starter" - which would consist of a single build step with a command line script, invoking either first or second build configuration basing on the user input. I do agree this workaround has some overhead, though, so I have created a feature request - please feel free to vote or comment as you see fit.

Speaking of the REST API update issue - could you please share the PUT payload you have used? 

0

Thanks for the advice Fedor - it's quite an elegant workaround :)

The PUT command which works well is

curl -X PUT -d @vcs.disabled --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Bearer xxxxxxxxxxxx" https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features/BUILD_EXT_611

where the file vcs.disabled content is

{"id":"BUILD_EXT_611","type":"VcsLabeling","disabled":true}

But providing these parameters directly 

curl -X PUT -d {"id":"BUILD_EXT_611","type":"VcsLabeling","disabled":true} --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Bearer xxxxxxxxxxxx" https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features/BUILD_EXT_611

fails with error:

Details: javax.servlet.ServletException: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'id': was expecting ('true', 'false' or 'null')

But this is some general curl PUT issue command problem not related with TC directly - I believe.

The real problem in TC, in this case, is id!=type

With file vcs.define:

{"count":1,"feature":[{"id":"VcsLabeling","type":"VcsLabeling","properties":{"count":3,"property":[{"name":"branchFilter","value":"+:<default>"},{"name":"labelingPattern","value":"%vcs.label%"},{"name":"vcsRootId","value":"DevOps_Testing_Tks_CiSshUser"}]}}]}

and command

curl -X PUT -d @vcs.define --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Bearer xxxx" https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features

the feature is inserted but the ID is wrong

curl -X GET --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Bearer xxxxxx"  https://myhost/app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features
{"count":1,"feature":[{"id":"BUILD_EXT_612","type":"VcsLabeling","disabled":true,"properties":{"count":3,"property":[{"name":"branchFilter","value":"+:<default>"},{"name":"labelingPattern","value":"%vcs.label%"},{"name":"vcsRootId","value":"DevOps_Testing_Tks_CiSshUser"}]}}]}

0

As I mentioned we're running on 2020.1.1 but very soon will go to 2020.2.2 and there the VCS labeling has other mechanism/methods in API so let's focus on that version. https://www.jetbrains.com/help/teamcity/rest-api-reference.html
In the reference we have three calls for VCSlabels, first of them is working fine but the second not :

$curl -s -X GET -H 'Content-Type: application/json' -H "Accept: application/json" --header "Authorization: Bearer xxxx" 'https://xxxx/app/rest/builds?locator=1091212&fields=build(id,vcsLabels:$long)'
{"build":[{"id":1091212,"vcsLabels":[{"text":"ci-dev-label","status":"SUCCESSFUL_SET","buildId":1091212}]}]}


$ curl -s -X GET -H 'Content-Type: application/json' -H "Accept: application/json" --header "Authorization: Bearer xxxx" 'https://xxxx/app/rest/builds/1091212/vcsLabels?fields=status,text'
{}

So I tried without fields

$curl -s -X GET -H 'Content-Type: application/json' -H "Accept: application/json" --header "Authorization: Bearer xxxx" 'https://xxxx/app/rest/builds/1091212/vcsLabels'
{"count":1,"vcsLabel":[{"text":"ci-dev-label","status":"SUCCESSFUL_SET","buildId":1091212}]}

So this is an issue of the reference

The third call in API reference (to add vcs label) - please advise how to provide "text" of the label and optionally VCSrootlocator

I'd like to cover scenarios (using VCSlabeling build feature or Label build sources option) :

A. give a user an option to decide during an execution of a build config (regular) to label VCSes (all or single)

B. give a user an option to decide during an execution of a build config (composite) to label VCSes in all dependant builds

 

0
Avatar
Fedor Rumyantsev

Hello Tomasz!

Apologies for the delayed response here; let me address above questions one by one.

> difference in -d @vcs.disabled versus -d {"id"

Could you please let me know if --data-binary and payload enclosed in single quotes works for you?

> id!=type

Yes indeed, for some features ID apparently will be selected as the type of feature, but in general a new feature will have semi-random ID. The best approach might be to GET the feature, set disabled flag to required value and PUT the updated definition back. Please also mind that instead of 

[PUT] /app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features

you may want to use

[PUT] /app/rest/buildTypes/DevOps_Testing_Tks_VcsLabelingCloudBB/features/<ID of feature>


> method with fields parameter

Yes, the method does support the fields parameter; one thing I`d like to note here is that you may want to use ?fields=vcsLabel(status,text), but I have spotted some issues with the logic while testing out locally and am looking into it further now. 

> method for adding VCS label

It`s covered here; text should be passed as body of request, with Content-Type set to text/plain, and the locator parameter expects a VcsRootInstanceLocator in case you need to ensure label is appended for the specific VCS root(s) only. For example, this locator would ensure only VCS root with ID "MyVCSRoot" would be labeled:

vcsRoot:id:MyVCSRoot
0

Hello Fedor,

Now we're running on 2020.2.3

I've resigned from enabling/disabling feature during a build execution as it makes a lot of troubles. Decide to go with adding VCS label via API call but no success. Even collecting existing label is not properly described (or I can't see it) but I figured out how to find it:

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238647/vcsLabels
{"count":1,"vcsLabel":[{"text":"covid","status":"SUCCESSFUL_SET","buildId":1238647}]}

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238647/vcsLabels?fields
{"count":1,"vcsLabel":[{"text":"covid"}]}

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238647/vcsLabels?fields=count
{"count":1}

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238647/vcsLabels?fields=vcsLabel
{"vcsLabel":[{}]}

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238647/vcsLabels?fields=vcsLabel,text
{"vcsLabel":[{"text":"covid"}]}

So the one which works well is ?fields=vcsLabel,text
Having this above experience I tried:

curl --silent --header "Authorization: Bearer xxx" --header "Accept: text/plain" POST https://xxx/app/rest/builds/1238671/vcsLabels?locator=vcsRoot:id:DevOps_Testing_Tks_PbnTest&fields=build,id,vcsLabels

curl --silent --header "Authorization: Bearer xxx " --header "Accept: text/plain" POST https://xxx/app/rest/builds/1238671/vcsLabels?fields=vcsLabels,text:"newlabel"

Nothing works for me :( 

So the only question is: how to add a VCS label for a build that doesn't have vcslabel yet (ie. build 1238671). For simplicity without providing Vcsroot

curl --silent --header "Authorization: Bearer xxx" --header "Accept: application/json" GET https://xxx/app/rest/builds/1238671/vcsLabels
{"count":0}

Could you write down exact API call to POST a lablel "newLabel" to the above build?

0

According to the REST API reference, the locator is optional however if required the above build 1238671 has the following vcsroot:

"changes": {
"href": "/app/rest/changes?locator=build:(id:1238671)",
"count": 0
},
"revisions": {
"count": 1,
"revision": [
{
"version": "30df4b5d1ff951446383d66569c7670430ee7def",
"vcsBranchName": "refs/heads/master",
"vcs-root-instance": {
"id": "10025",
"vcs-root-id": "DevOps_Testing_Tks_PbnTest",
"name": "pbn-test-ssh",
"href": "/app/rest/vcs-root-instances/id:10025"
}
}
]
}

0

OK I figured out it, the proper POST query is:

curl --silent --header "Authorization: Bearer xxx --header "Content-type: text/plain" POST https://xxx/app/rest/builds/1238827/vcsLabels?locator=vcsRoot:id:DevOps_Testing_Tks_PbnTest -d "newLabel"

or without providing vcsRoot (so all attached VCSes will be lableled)

curl --silent --header "Authorization: Bearer xxx --header "Content-type: text/plain" POST https://xxx/app/rest/builds/1238827/vcsLabels -d "newLabel"

 

Heh debugging it I learned a lot about TC api :) 

This Topic can be closed - thanks Fedor for the cooperation. 

0
Avatar
Fedor Rumyantsev

Hello Tomasz,

Sorry for being late to respond - glad to hear the requests are working for you, though! The methods are included in our auto-documentation (GET and POST, respectively) and there are also several usage examples listed here. "Common use cases" section in the REST API documentation contains a number of request examples which should cover most of the basic scenarios, so maybe it would also come handy to you going forward.

0

Please sign in to leave a comment.