views:

226

answers:

5

I've set up our SVN repository like the Subversion book suggests, and this is also how my previous companies have done it. It looks something like this:

/trunk
/branches
/tags
/extlibs
/docs

where the first three are pretty obvious, and extlibs is for 3rd party assemblies that we wouldn't typically recompile ourselves.

All of this works great for the daily development stuff.

Now I've installed TeamCity and have builds, unit tests, code coverage, and code analysis running. Everything is great, except for the fact that this code structure results in too much code getting downloaded.

So here's the catch 22, in my opinion: it's silly to download all of aforementioned folders from the SVN repo when I only need /trunk and /extlibs. But I can only specify one repo folder to download in the TeamCity VCS settings. So then the other possibility is to put the /extlibs folder into /trunk, but in order to compile branches, /extlibs would have to go into all of those as well (since I usually branch the trunk, and not individual subfolders... and this would seem infinitely more evil since /extlibs could actually be larger than /trunk and /branches, with all of the binaries stored there...

Do you guys have any suggestions for me? Thanks!

+4  A: 

Set TeamCity to download only /trunk. Make /trunk/extlibs an external that points to /extlibs. Do the same for all /branches. This would allow you to share /extlibs between /trunk and all /branches, while still having single root folder for each of them.

Update: When I said to make /extlibs an external in /trunk/extlibs, I was referring to the SVN externals property. Assuming your SVN server is svn://yoursvnserver/svn, you can do this with the following svn command:

svn.exe propset svn:externals svn://yoursvnserver/svn/trunk -F externals_defs.txt

You can refer to svn.exe help propset for more details on the format of the file, but in the simplest form, it'll have one line like this:

extlibs svn://yoursvnserver/svn/extlibs

Once you set the SVN externals property on the trunk, you'll commit it. From there on, everybody that checks out /trunk (including TeamCity) will get in /trunk/extlibs a copy of /extlibs. Of course, you will have to change your references a bit so that they point to /trunk/extlibs now, so that your build is self-contained in the /trunk tree.

Franci Penov
+1 That's the same notion I had!
Achilles
Ah, so that's what the "external" setting is for. sheesh. :) Thanks, I'll give that a go. I wonder how much havoc this is going to wreak on my builds. Better snapshot the server now, I think. Thank you for the suggestion!
Dave
Hmm.. I misread your answer, sorry. I thought you were talking about the "externals" setting in the VCS settings in TeamCity, but I just looked at it and saw that it only has the options "full support", "checkout", and "ignore". So I guess you're not referring to that. How do I make /trunk/extlibs point to /extlibs? Are you talking about hard-link trickery?
Dave
I don't know much about TeamCity actually, but I would assume that the "externals" property in its settings is quite similar to the SVN "externals" property. So you might be actually able to do this through TeamCity as well; however, I don't know what directory structure this will create on the build machine drive and whether you'll have to tweak your build to account for potential changes in `/extlibs` location relative to the `/trunk` location.
Franci Penov
Ok, reading up on it now! http://svnbook.red-bean.com/en/1.0/ch07s03.html
Dave
Both this, and the original have a problem though: If you update extlibs, then all of your branches and tags won't be compiled as they were when they were tagged (for instance, if you tag a previous release). Having extlibs in the trunk does.
SnOrfus
@SnOrfus - that is correct. The only way to ensure everything builds as the label/branch build as at the time of branching requires separate copy of `extlibs` in each label/branch tree.
Franci Penov
Also ensure you set a revision property on that external, to ensure that tags and branches brings in the correct version of the external libraries. This way you can update the files in /extlibs with new content, and still build an older version of trunk, or a tag, since it refers to a specific revision of /extlib that was current at that time. To do this, check the red-bean svnbook page linked about and find the `-r21` part of the example there, this hard-links the external reference to revision 21, not just "whatever is most up-to-date when we update."
Lasse V. Karlsen
Ha, I didn't know the trick @Lasse mentioned. Nice!
Franci Penov
+1 Lasse; I didn't know that either.
SnOrfus
@Lasse approach is correct - no need to do magic with svn:externals
KIR
A: 

One approach is to store the extlibs in their own "project" structure. Treat them like a seperate project that your main project references instead of a part of the main project. Then set TeamCity to "build" these binaries(which is simply to pull them down) when they are modified. Since your main project is dependent on these binaries, when they are "built" it should trigger a build of the projects that depend on them. That way you aren't pulling down the binaries each time you get ready to build your main project but only as they are recompiled and committed into SVN.

Achilles
I'm having a little trouble picturing how this will work. I'm going to sleep on this issue tonight and will post up more silly questions in the morning. :)
Dave
+2  A: 

I'd say that putting extlibs in the trunk is actually a good idea, that not only solves your problem but another as well.

What happens when you need to release a previous tagged build but you've updated some of the libraries in extlibs since then? You have to fish through the history to find a version of extlibs that was current when that build was tagged.

SnOrfus
that's a good point! I guess it might not happen *a lot*, but in those cases where we do an extlibs update, it would be a problem to have it in a separate folder. I'll have to think about this issue a little more, but you definitely have a point. Branching for dev. purposes might get to be a little slow because I'd have to get multiple copies of extlibs, but that might be a necessary evil in this case.
Dave
@Dave: It gets worse if you have a team working on a feature branch of some kind and you update any extlibs libraries... without them being in the trunk of their branch, you could potentially break their build.
SnOrfus
yep... very true.
Dave
+1  A: 

It looks like you have two different issues you need to address:

  1. How to set up your VCS for your build configuration
  2. How to handle your external libraries

For your VCS, leave your setup as you have it - at the root of your repository. In each build configuration, you can add checkout rules to prune your checkout to the right folders.

For instance, you can use the following to make the trunk folder the root folder of the checkout:

+:trunk=>.

Or for a branch, you can do something like:

+:branches/featureset=>.

You can add multiple checkout rules if desired, including adding any files/folders from your extlib folder:

+:extlibs/dependency-2.5.3=>.libs/dependency1

You can even remove files/folders using checkout rules:

-:trunk/files-not-needed 

For your external libs, as stated in other answers, you can include external folders using SVN. However, I would not get heavy handed with the inclusion of the entire extlibs folder. Only include the specific library revisions that you need to build the project. Also, make sure your extlibs folders are well-protected from change. By being fine-grained about your externals, you can avoid the issue of trying to build an old version because your project will be linked to the correct version. If you have triggered builds enabled, you will also avoid a library change triggering a build. For example, you could configure your snv:external libs like so:

libs/dependency1 svn://yoursvnserver/svn/extlibs/dependency-2.5.3
libs/dependency2 svn://yoursvnserver/svn/extlibs/dependency-rc-2.4
Richard Cirerol
I do like the idea of keeping extlibs where it is. At my previous job, we didn't keep them well-protected from change, but it was just known that things there shouldn't be modified often, and when they are, the entire team needs to be notified. Thanks for the info. I haven't been able to focus on this issue recently, but I will review your suggestions soon!
Dave
I didn't mean to give the impression that you needed to move the libs, but instead use the svn:external commands to import the specific dependencies you needed. I do hope the information is useful.
Richard Cirerol
Also, you can use the checkout rules to only pull the extlibs folders you need. (It sounds like you are linking to that folder structure in development.) You could add each as needed, but may be a maintenance problem when you start needing additional libraries.
Richard Cirerol
+3  A: 

I'd like to chip in a smallish answer as well. All the answers here about how to instruct Subversion to keep a "current" copy of the external libraries as part of trunk is basically the right way to go forward in this particular case.

However, if for some reason you want to pull down parts of a repository in TeamCity, like you asked, you can do that as well.

When you edit the build configuration, on the second tab, the one for version control settings, you have a setting for each attached VCS root, for checkout rules.

Click on the "edit checkout rules" link to the right in the VCS root grid for that build configuration and enter the following (as per your example):

-:.
+:trunk
+:extlibs

This will first flag everything as "do not pull down", both files and subfolders of the root, and then flag both trunk and extlibs as "do pull these down".

You can read more about the checkout rules here.

Lasse V. Karlsen
thanks! I will read up on it.
Dave
I should say this is how it supposed to work in TeamCity by its design. I'd write the same answer unless it is already here :)
KIR