This is part of a series of walk throughs exploring CI in TFS, starting from the ground up. The entire series and source code are maintained at this BitBucket repository.
Where I'm Headed
For the next walkthroughs, I'm starting with new team projects and sample applications, building a suite of solutions with shared dependencies. My goal is to uncover the various problems that come from:
- DLL dependencies
- Project references
- Web.config and app.config settings
- Unit tests
- Integration tests
- BONUS: Migrating to Git
Along the way, I'm going to completely abuse the TFS team project structure and show how to clean up and organize a repository.
Relationship of Team Projects, Solutions and Build Definitions
Team Projects are intended to manage a software project.
But that doesn't mean there's just one Visual Studio solution for a project. There might be several. For example, our CI Sample projects might end up looking like this:
$/CI Sample (team project) |_CIConsoleSample |_CIRestSample |_CIDocumentation $/CI Shared (team project) |_CINuGetSample
What does this mean for automated builds?
- Maybe the Console now has a dependency on the REST solution, and we need Console to build any time REST changes.
- Maybe we need the NuGet solution to deploy to a staging location on a successful build, then build dependent solutions pulling this NuGet dll from the staging source.
- And maybe we don't want the Documentation to build at all.
Important If you're using a Continuous Integration trigger, and any trigger fires, all the solutions in the definition will be rebuilt. For example, let's say the definition builds all solutions in the CI Sample team project above (the default behavior). You have a trigger that says "only build when CIConsole changes." It would still build all three solutions.
This feature of a build definition means that much of the time we'll configure a definition to build just one solution. However, as pointed out above, for a solution that builds an assembly used by multiple projects, you might want to rebuild all the solutions that depend on it, to catch bugs.
As this diagram shows, a team project can include multiple solutions. A build definition can build multiple solutions. A build definition belongs to a single team project, but, it can (with effort) build solutions in other team projects.
The Projects - A Turing Oracle
My sample suite of applications is a pseudo Turing Test, and is made up of desktop and web apps. The user can ask questions, and get answers that seem to be from a human. I'll start simple, imitating a real-world project progression. In the end, this will be my structure in the TFS repository.
_$Shared |_$/Magic8Engine $/TuringDesktop |_TuringDesktop.sln |_TuringConsole.csproj (Dependencies: Magic8Engine, TextColor) |_TextColor.csproj $/TuringWeb |_TuringWeb.sln |_TuringWeb.csproj (Dependencies: TuringSoap) |_TuringSoap.sln |_TuringSoap.csproj (Dependencies: Magic8Engine)
Magic8Engine The Magic8Engine produces the answers, using the eerily accurate Magic 8-Ball Algorithm. It's a shared dll, and lives in a separate folder. It's published as a NuGet package.
TuringDesktop TuringDesktop is a console application for asking questions. The team project has one solution, which itself has two projects.
TuringConsole, the UI, has two dependencies. One is the Magic8Engine dll, the other is on TextColor, which is configured as a project reference.
TextColor is for changing the color of the text. It is only used by TuringConsole.
TuringWeb This is our web interface. The team project has two solutions.
TuringWeb Solution This solution has one project, TuringWeb, which is dependent on the TuringSoap web service.
TuringSoap Solution Our old-fashioned SOAP web service is dependent on the Magic8Engine dll. In the future, the web service could become shared by other applications.
In the next part, I'll build my desktop application as if I didn't know anything about the future web application.