If you are developing with Sitecore you are probably using TDS. If you are not then you are clearly missing out. You may as well stop reading this post and go check it out first.
File Replacement Residue
We have posted previously on how to set up your Sitecore solution with TDS and how to do proper build configuration with support for multiple environments. It all works extremely well. There has only been one wrinkle that you wouldn’t come across too often but when you do it may cost you a few minutes (or more) to figure out and may leave that slight taste of bitterness or even make you flinch.
while you did delete it from the project, TDS build didn’t delete it from your deployment target
Say you need to add a few new event handlers or pipeline processors and you start off with a new .config
include file for your local development sandbox environment. Code is written, tested, events are firing off and handlers do their job just fine. You take the declarations from that events.new.config
file and merge it into an events.global.config
that you share for all environments (please read more on how we recommend to structure your App_ConfigInclude
artifacts to account for environment differences here). You test it some more, probably do a few more tweaks, and of course you end up deleting that original events.new.config
from your sandbox configuration. The only thing is, while you did delete it from the project, TDS build didn’t delete it from your deployment target (be that a package or your website). The App_ConfigInclude
will have both events.new.config
and events.global.config
. You may not even notice until the files drift enough apart to cause you grief. Happened to me the other day as I refactored include artifacts in one of our solutions.
Automate It
all the ingredients for the solution are in the TDS MSBuild targets
Deleting these orphaned artifacts would be, of course, an option if it was a one-off. Cleaning the entire target folder is not an option either as there are Sitecore installation artifacts that you want preserved. Here’s what you can do to help TDS do a better job. We apprently have all the ingredients for the solution in the TDS MSBuild targets that you will find under $(MSBuildExtensionsPath)HedgehogDevelopment
. Take a closer look at what TDS does in the CopySourceProjectToOutputDir
target using its custom built RemoveObsoleteFiles
directive. Reflector will show you that it’s a very simple and a very clever way to only remove the files the script knew it copied last time but now can tell are gone from the project. The build script keeps track of it in the BuiltFiles_$(Configuration).txt
. We can do exactly the same trick with the File Replacement artifacts.
Here’s the extra build directives that you would add into your TDS.Master (following our convention) *.scproj
file:
<Target Name="AfterFileReplacements"> <Message Importance="high" Text="Preparing to run File Replacement cleanup"/> <WriteLinesToFile File="NewCopiedFiles_$(Configuration).txt" Lines="%(_CopiedFiles.Identity)" Overwrite="false" Condition="'$(BuildingInsideVisualStudio)' == 'true'"/> <RemoveObsoleteFiles PreviousBuildFiles="CopiedFiles_$(Configuration).txt" CurrentBuildFiles="NewCopiedFiles_$(Configuration).txt"/> <Delete Files="CopiedFiles_$(Configuration).txt" Condition="Exists('CopiedFiles_$(Configuration).txt')"/> <Copy SourceFiles="NewCopiedFiles_$(Configuration).txt" DestinationFiles="CopiedFiles_$(Configuration).txt" Condition="Exists('NewCopiedFiles_$(Configuration).txt')"/> <Delete Files="NewCopiedFiles_$(Configuration).txt" Condition="Exists('NewCopiedFiles_$(Configuration).txt')"/> <Message Importance="high" Text="File Replacement cleanup complete"/> </Target> <Target Name="AfterSitecoreBuild"> <Message Importance="high" Text="Preparing to run Sitecore Web Project Deploy Cleanup"/> <WriteLinesToFile File="NewDeployedFiles_$(Configuration).txt" Lines="@(DeployFiles->'$(SitecoreDeployFolder)%(RecursiveDir)%(FileName)%(Extension)')" Overwrite="false" Condition="'$(SitecoreDeployFolder)' != ''"/> <RemoveObsoleteFiles PreviousBuildFiles="DeployedFiles_$(Configuration).txt" CurrentBuildFiles="NewDeployedFiles_$(Configuration).txt"/> <Delete Files="DeployedFiles_$(Configuration).txt" Condition="Exists('DeployedFiles_$(Configuration).txt')"/> <Copy SourceFiles="NewDeployedFiles_$(Configuration).txt" DestinationFiles="DeployedFiles_$(Configuration).txt" Condition="Exists('NewDeployedFiles_$(Configuration).txt')"/> <Delete Files="NewDeployedFiles_$(Configuration).txt" Condition="Exists('NewDeployedFiles_$(Configuration).txt')"/> <Message Importance="high" Text="Sitecore Web Project Deploy Cleanup complete"/> </Target>
This is it. Clean the target once and now every time you run the TDS build it will keep track of what it copies. Once you delete something and re-build a now-smarter TDS will notice and will take care of it in the deployment target for you. Oh, and please add the new CopiedFiles_*.txt
and DeployedFiles_*.txt
into your .gitignore
.