What was there at the beginning
Large enterprise-system, which is the main platform of the company. The structure includes the core of the system and a set of plug-ins for different tasks. Plug-ins develop independently of each other, they require changes and extensions to common libraries.
During the development and branching of the system, finding all the plug-ins in a common project complicated the code support. Constantly there were several branches in the repository, which led to great difficulties in preparing releases and merging changes.
Therefore, a volition was made to create the infrastructure and set up scripts to automate the project assembly for different plug-ins.
')
The following tools were used to solve the problem: NuGet, TeamCity, NAnt, Visual Studio 2010, SlowCheetah.
Why do you need it
Use
Joel's Test to evaluate your work. The actions described in my post, cover points 2 and 3.
The solution of the problem
Gradually, the project evolved to separate all plug-ins into separate projects, creating their own repository for each project in VCS (Version Control System). Projects received hard versions installed on the build server (TeamCity). The build file version was composed of 4 numbers: the major and minor versions of the functional, the revision number in the VCS and the number of the attempt to launch the build configuration.
[assembly: AssemblyVersion("1.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
The main modules were combined for functional purposes in several packages using NuGet. The composition of the packages was described by nuspec-files, and the packages were reassembled with the new version after each commit to the branch for release (a trigger was triggered in TeamCity). NuGet-packages were stored on the build server and were available on the local network through a shared directory.
Sample nuspec file
<?xml version="1.0"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>Core</id> <version>1.0.0.0</version> <authors>DefaultCompanyName</authors> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description> </description> <frameworkAssemblies> <frameworkAssembly assemblyName="System.Configuration" targetFramework="net35" /> <frameworkAssembly assemblyName="System.Core" targetFramework="net35"/> <frameworkAssembly assemblyName="System.Drawing" targetFramework="net35"/> <frameworkAssembly assemblyName="System.Runtime.Serialization" targetFramework="net35"/> <frameworkAssembly assemblyName="System.ServiceModel" targetFramework="net35"/> <frameworkAssembly assemblyName="System.Windows.Forms" targetFramework="net35"/> <frameworkAssembly assemblyName="System.Xml" targetFramework="net35"/> </frameworkAssemblies> </metadata> <files> <file src="core\bin\Release\*.dll" target="lib" /> </files> </package>
NAnt and MSBuild were chosen as the main build tool. Csproj projects have been extended with additional instructions for configuring configs and downloading dependent libraries.
At assembly of projects there was a definition of dependences. The NuGet's Enable-PackageRestore function (included in Visual Studio extension from version 1.6) allows you to automatically find and download nuget packages of the required versions during the compilation process. There is no need to store binary files of used libraries in VCS. When building a project on a build server, a similar script was executed. It is enough to store the NuGet utility itself with the target set for MSBuild in the project repository.
Changes in the project file
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> ... <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <RestorePackages>true</RestorePackages> ... <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">..\.slowCheetah\SlowCheetah.Transforms.targets</SlowCheetahTargets> ... <Import Project="$(SolutionDir)\.nuget\NuGet.targets" /> <Import Project="$(SlowCheetahTargets)" Condition="Exists('$(SlowCheetahTargets)')" /> </Project>
Each plugin was required to modify the system configuration by adding or changing elements to the config file. I used the SlowCheetah project, which transforms xml files. Config files were included in nuget packages with target = "content" and added as a project file. Transformation added two files. For example, the Client.Debug.config and Client.Release.config files are created for the Client.config file. Depending on the current configuration used when building the project, one or another transformation will be applied.
You can configure the artifacts so that the assembled projects are available for downloading from TeamCity via the web interface as a zip file.
Conclusion
As a result, we get a streamlined mechanism that automates the assembly of applications. The main advantages are the speed of assembly and minimizing the number of
stupid mistakes.
Links
NugetTeamcyNAntSlowCheetah