Unable to set up build chain for projects built from same VCS root
I have 4 projects that are all in a single .Net solution but they are built and Nuget packaged separately. I would ideally only like them to rebuild if code within the specific project folder(s) has changed. I would like this to happen automatically but I think the checkout rules are causing problems because they combine both rules for rebuilding and also which files are checked out to disk!
I have added automatic triggers (with filters) so that each project can trigger directly from VCS but since there might be changes in more than one project, I have used the snapshot dependencies to build a chain. However, if only the "top" project is triggered, it is building all of its dependencies first even though they have existing builds that are available.
I think the issue is that the dependencies are saying, "the VCS has changed since I last built so I will rebuild". The problem is that checkout rules could prevent this but they don't work in our case because I DO need all of the files on the local disk to build the solution.
Am I correct? Is there any plan to separate "what files to checkout" and "what files to watch for rebuilding"? Otherwise, I can't see how this works and I don't think I am doing anything strange because other people have asked similar questions. Do I have to heavily refactor the code to provide complete separation?
Thanks
Please sign in to leave a comment.
Hi Luke,
VCS Checkout rules define what will be checked out and where. VCS Trigger filters decide on what of what has been checked out a build should be triggered. Snapshot dependencies will only reuse builds when they are set to do so and the snapshot dependency determines that the builds are suitable: https://www.jetbrains.com/help/teamcity/snapshot-dependencies.html
Snapshot dependencies are meant to be used for controlling order of operations, and of course, defining what needs to be built before the current build configuration can be started. I'm not exactly sure what you have set up with them or why you felt like snapshot dependencies are what help in your scenario. If we can go a bit more in depth as to what your scenario is we might be able to suggest to keep it or maybe perform some modifications.
This said, your explanation looks pretty much accurate, but without exact examples (screenshots, or a specific example of what has happened and what you expected to happen) it's hard to point out whether something has been misconfigured.
Hi Denis,
Thanks for the reply. I think the issue is that because all of the projects are in the same solution, I cannot use VCS rules - all projects need all the code. But the problem is the combination of a VCS trigger and snapshot dependency. What I would like to happen is imagine the build order is Project A then B then C, if the code has changed only in Project B then only project B and C should rebuild. The issue is if I trigger B manually or with a trigger rule, it will always trigger Project A because project A as a snapshot dependency will "see" a new commit to its code (which remember is all of the code) and think it has changes to build.
I've managed to get around it by not having any automatic triggers and a snapshot dependency that allows the latest build instead of build from the same chain. Then I have to manually trigger the chain in the place that I know has changed and it correctly builds only B and C.
I think there is one combination of settings that is missing that would require the same chain builds but only if code in their folders was changed, otherwise just use the latest build. At least I can work around it though.
Luke
Hi Luke,
thanks for following up. In roughly every scenario of this we have seen so far, there is usually some common library with APIs, etc but then each other project works independently, or if they require order, they don't each depend on each other. The core issue here is that if everything is needed to build everything, then a change in any code should affect the results of each of the builds, otherwise why can't those folders be excluded?
Respecting your scenario, and assuming that you do have a way to figure out which projects to build based on the folders of the changes, then you can set up a separate set of builds, copies of B and C on their own chain, which are triggered filtering out changes on A, and an extra copy of C which can be triggered excluding changes on B and A.
Hi Denis,
Sorry for resurrecting an old thread but I am back again trying to make our CI slightly less painful. I think I understand the issue here and it relates to suitable builds meaning "A build with the same commit or at a specified date/time (if different repo)", which is causing the problem.
Imagine I have A and B and B depends on A in general. Forget triggers. I manually trigger B because I know my change was only made in B and it *should* be able to use the current build of A. However, since I need to use a snapshot dependency to get the correct version of A and ensure that if A has changed, B should wait for it to build, what Team City would do is look at the repo for A and see there is a new commit (the change I made for B) so it will always build A.
If I remove the snapshot dependency and only use an artifact dependency to get the versioned csproj file from the latest build of A, then if both A and B have changes, I would have to manually trigger them in the correct order since adding an automatic trigger without a snapshot dependency might mean it builds B and then A instead of the other way round.
I appreciate that I might be missing something and I am prepared to re-factor what we have to make it work in the best way but I want to avoid 4 + projects building every time a single change is made to any of them but since they get converted from project to nuget package dependencies by msbuild, I need the built projects to depend on the correct versions (something I am using the artifact dependency for).
Can you point me in the right direction? Perhaps there is a best-practice guide for avoiding complex build-chains or something?
Thanks
This might also be easier answer in another way: If I do NOT use snapshot dependencies (which forces something to build even if no important changes are made), is there another way I can guarantee that if changes are made in 2 projects, that it will build project A before project B and then simply use an artifact dependency instead?
This is what I would like:
Example 1: Changes made in project A and B => Build A and then B
Example 2: Changes made in project B only => Project B builds with latest artifacts from project A
Exampel 3: Changes made in project A only => Either A builds (and user has to trigger B if they need to) or A builds, which triggers B, I don't mind.