Headless build can make you scratch your head (Part 1)
One big advantage over recent database projects is the ability to do headless build on a build controller.
There is no straight forward definition of a headless build. In summary you can describe it that only the needed prerequisites are installed for compiling and translating the bits. While for some compilations specific applications will have to be installed or even cannot be build without the IDE, headless builds use the builds machine build processor (for MSFT mostly msbuild.exe) and pulls only the needed .targets / satellite assemblies.
Doing headless builds need a specific set of assemblies installed and registered assemblies on the build controller. As there can be some problems associated preparing the prerequisites, this (and former) blog posts will emphasize some of them or at least those were you won´t be able to find an easy solution by yourself.
A good starting point for installing the prereqs is the following blog post. It provides you with the needed Basic for the best walkthrough.
DACFX Sept 2012 Updates Break Headless Build
Though, there can be some culprits and error messages you can run into, which do not seem to be obvious in the error messages at all. The following series will contain some of the problem you might encounter and will not be able to find simple solutions on the internet for.
Referencing dacpacs
You encounter the following error:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets (465): File "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\Extensions\SqlServer\110\SqlSchemas\master.dacpac" does not exist.
This works on your Visual Studio machine as you have full blown set of files installed on the machine. On build controllers / the Team Foundation Server you normally don´t find them if you don´t have Visual Studio (and I don´t mean the Shell) installed. The source of the mentioned directory is constructed from your .sqlproj file containing the references:
<ItemGroup>
<ArtifactReference Include="$(DacPacRootPath)\Extensions\Microsoft\SQLDB\Extensions\SqlServer\110\SqlSchemas\master.dacpac">
<HintPath>$(DacPacRootPath)\Extensions\Microsoft\SQLDB\Extensions\SqlServer\110\SqlSchemas\master.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
<DatabaseVariableLiteralValue>master</DatabaseVariableLiteralValue>
</ArtifactReference>
<ArtifactReference Include="$(DacPacRootPath)\Extensions\Microsoft\SQLDB\Extensions\SqlServer\110\SqlSchemas\msdb.dacpac">
<HintPath>$(DacPacRootPath)\Extensions\Microsoft\SQLDB\Extensions\SqlServer\110\SqlSchemas\msdb.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
<DatabaseVariableLiteralValue>msdb</DatabaseVariableLiteralValue>
</ArtifactReference>
</ItemGroup>
You see that a variable called $(DacPacRootPath) is used within the reference. This will be resolved by the above mentioned .targets file (C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets) by the following conditions:
<!--Calculation of the system dac install path-->
< PropertyGroup>
<DacPacRootPath>$(VsIdePath)</DacPacRootPath>
< /PropertyGroup>
which translates to the V(isual)S(tudio)IDEPath (VSIdePath)
<!--Calculation of the VS install path-->
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'">
<VsIdePath>$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0@InstallDir)</VsIdePath>
<VsIdePath Condition=" $(VsIdePath) == ''" >$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\10.0@InstallDir)</VsIdePath>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'">
<VsIdePath>$(Registry:HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\11.0@InstallDir)</VsIdePath>
<VsIdePath Condition=" $(VsIdePath) == ''" >$(Registry:HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\11.0@InstallDir)</VsIdePath>
</PropertyGroup>
The target is first searching for the existence of the regkey in the x64 path, id empty in the x86 path (WowNode) (at least for VS2012 = 11.0)
If you don´t have the regkey set, you can set it to the appropriate one like on your dev machine, pointing to e.g. “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE”. Under this directory you can create the file path as in the error message or simply copy the appropriate Folder to your build machine containing the needed .dacpacs.
After copying, MSBuild will be able to find the references and at least for this path would be able to resolve correctly.
Another option would be to always copy your referenced system dacpacs to the local folder.
-Jens