How do I delete unused VCS roots with REST API?

Answered

Hi,

We have a couple hundred unused VCS roots and would like to remove them, in the name of reducing clutter.  I would do it manually, except that clicking "delete" takes about 10 seconds per VCS root.

I see that the REST api has a "delete" operation.  I was able to query the VCS root details via REST and Ruby with JSON (see below), but the count of roots with "NOT_MONITORED" status doesn't match up to the count of unused roots in the UI (I count about 20 extra NOT_MONITORED entries compared to the UI's count of unused).

Is there a way to clearly identify unused roots from the REST api, so that they may then be deleted (also via the api)?

Thanks,
-chris

require 'json'

# /tmp/tmp/txt was created like this:
#  $ curl --netrc --header 'Accept: application/json' http://builds/httpAuth/app/rest/vcs-roots`
j = JSON.parse File.read('/tmp/tmp.txt')

details = []
not_monitored = 0
j["vcs-root"].each do |v|
  d = JSON.parse(`curl --netrc --header 'Accept: application/json' http://builds/httpAuth/app/rest/vcs-roots/#{v['id']}`)
  puts d['name']
  details << d
  not_monitored+=1 if d['status']=='NOT_MONITORED'
end

File.open("vcs-details.json","w") do |f|
  f.write(JSON.pretty_generate(details))
end

puts "Count of not-monitored roots: #{not_monitored}"
11 comments
Comment actions Permalink

Hi,

 

Did you find a way to achieve this. I am also interested in similar solution,

 

Rajender

 

0
Comment actions Permalink

No, I gave up :-)  Although I do notice that manual deletions are now much faster--less than a second each.  I haven't revisited the REST api to see if it's been updated w.r.t. this capability.

-chris

0
Comment actions Permalink

Thanks you very much for letting me know. Somehow, for me it still takes more than 10 secs on 10.0.4, may be it’s a ui problem.

 

Best,

Rajender

0
Comment actions Permalink

Hello,

At the moment there is no direct support for this in REST API, but you can find VCS roots without instances (which means there are no usages), this can be done via going GET like


TEAMCITY_SERVER_URL/app/rest/vcs-roots?fields=$long,vcs-root(id,href,vcsRootInstances(count))

and then searching for the VCS root nodes with "count="0"".

I created a feature request, please vote for it.

4
Comment actions Permalink

This query gives me many more entries than show in the UI when I select all "unused" from the root. Until I figure out exactly why this number is larger than what shows in the UI as unused, I'm nervous about auto-deleting them all!

0
Comment actions Permalink

Hi John,

 

that query will return every single VCS Root instance in teamcity. A VCS Root instance is not a 1-1 relation to a VCS Root you have defined, but for every parameter combination that is available, it will generate a separate VCS Root instance. This works this way to ensure that TeamCity can keep track of all the multiple possible configurations of a vcs root based on your own settings, but will only create the required ones, while otherwise you might have multiple copies of the same VCS Root which would be duplicating the amount of resources used.

In the mentioned query, you need to check in the response for every element with count = 0 to locate the instances that are not being used. It would also be helpful if you explained what exactly you mean with the "UI shows as unused". If you mean the list of VCS Roots in the root project, you need to take into account that VCS Roots can be defined elsewhere and will not be presented in the VCS Roots tab of the root project.

0
Comment actions Permalink

Hi Denis,

 

I was unclear in what I wrote so I apologize for the confusion. What I mean is that if I go into the UI->admin and select the root project, then click on both Show VCS roots from subprojects" and "Show unused VCS roots only", there are fewer entries there than when I run the query and count the number of query results with count of vcsRootInstances = 0.

For example, I went through and manually deleted several hundred unused vcs roots from the UI. Currently when I look at the UI, I see only 1 unused vcs root that is undeletable. I think this is because it is referenced in an unused template. However, when I run the query, there are 52 vcs roots that have vcsRootInstances count = 0. This is the discrepancy I am referring to.

Also, btw, I thought when I wrote the last comment that I would be able to automate the deletion but it seems the HTTP DELETE verb is not actually supported on vcs root. I was getting a 405 every time I tried to delete an unused vcs root via the REST API even though the documentation specifies that operation (TeamCity Enterprise 2018.1.4 (build 58724))

0
Comment actions Permalink

Hi John,

 

thanks for clarifying. First of all, vcs-root-instances does not accept delete requests. You need to send the request into vcs-roots/<locator>, which should work. As mentioned before, vcs root instances can be multiple out of a single vcs root definition.

 

I'm not exactly sure what is going on and we would probably need to go into details of each of the VCS Roots, although I think this could still be what I mentioned. A single VCS Root parametrized, some subproject reusing it with different parameters but having it unused in it. This VCS Root would still be "in use", but there would be unused instances. You could probably check some of the instances which exist in the REST API but do not appear, then investigate where it's coming from.

If you can still locate instances available in the REST API and not present in the UI, I'd recommend opening an issue in our tracker providing the exact information, where it's defined, where it's being marked as used in the UI, and the report from the REST API: https://youtrack.jetbrains.com/issues/TW

0
Comment actions Permalink

From this page: https://confluence.jetbrains.com/display/TCD18/REST+API#RESTAPI-VCSRoots
```
Get details of a VCS root/delete a VCS root: GET/DELETE http://teamcity:8111/app/rest/vcs-roots/<vcsRootLocator> , where "<vcsRootLocator>" can be "id:<internal VCS root id>" or other VCS root locator
```

# do a GET
```bash
$ curl --user MYUSER -X GET https://teamcity.mycompany.com/app/rest/vcs-roots?locator=id:CommonServices_Cara_CSL_CaraCslIisServiceSource41111111111
Enter host password for user 'MYUSER':
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><vcs-roots count="1" href="/app/rest/vcs-roots?locator=id:CommonServices_Cara_CSL_CaraCslIisServiceSource41111111111"><vcs-root id="CommonServices_Cara_CSL_CaraCslIisServiceSource41111111111" name="CARA_CSL_IIS_Service_Source (4) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1)" href="/app/rest/vcs-roots/id:CommonServices_Cara_CSL_CaraCslIisServiceSource41111111111"/></vcs-roots>

$

```

#do a DELETE

```bash
$ curl --user MYUSER -X DELETE https://teamcity.mycompany.com/app/rest/vcs-roots?locator=id:CommonServices_Cara_CSL_CaraCslIisServiceSource41111111111
Enter host password for user 'MYUSER':

responding with error, status code: 405.
Details: javax.ws.rs.WebApplicationException
Not supported request. Check that URL, HTTP method and transferred data are correct. Metadata: Allow:[HEAD,POST,GET,OPTIONS]

```

0
Comment actions Permalink

Hi John,

 

I see the issue now. The problem is that vcs-roots/<locator> is not internally handled exactly like vcs-roots?locator=<locator>. They are different endpoints and thus behave differently. I see how this can be counterintuitive and will mention it internally, but sending the /<locator> does work.

 

Could you try that?

0
Comment actions Permalink

Ahhh that's it! Thank you for looking into it. I saw the examples in the documentation for passing locators as query parameters and kept doing that. I never noticed that the locator was being passed as a resource in this case.

 

Yes it's confusing that the same style of locator ([name]:[value]) works with GET both as a query parameter and as a resource, but DELETE only works with the one. Looking at it now though, I see that the behavior is different since the query param only returns hrefs and not the details. The use of the same locator syntax is what is confusing. I understand that you could potentially return more than one result using "?locator=..." and "/vcs-roots/[id]" should refer to a single resource. In the second case, just passing the id alone rather than using the generic locator syntax would differentiate it better, IMO.

 

Thanks again.

0

Please sign in to leave a comment.