4

I have TFS On-Premises 2015 and I would like to transform app_config/include files with SlowCheetah on build using TFS, but I am running into some issues.

Existing Solution

First, we already have a solution in place where we created an Environment_Config\$(Environment) folder which overwrites the appropriate app_config/include files on deploy to specific environments.But this results in config duplication and it would be much cleaner to perform transforms like we do with Web.config

Issue(s)

We are using SlowCheetah 3.0.6 and there are a couple of issues.

1) The final app_config/include directory also has the environment config files in there which results in Sitecore picking them up and applying those settings when looking at /Sitecore/Admin/ShowConfig.aspx. How can I get rid of the environment specific transform files so they are not included in the final build artifact?

2) On build, when I look at the original config file, the transforms haven't been applied at all. When I publish using Visual Studio, it works fine but on build the transform doesn't happen. I've looked at another StackOverflow question that suggested removing the condition in C:\Users\Users\AppData\Local\Microsoft\MSBuild\SlowCheetah\v2.5.11\SlowCheetah.Transforms.targets:

<BuildDependsOn Condition=" '$(IsWap)'!='true' "> $(BuildDependsOn); TransformAllFiles; ScReplaceAppConfigItem; </BuildDependsOn>

but instead I set IsWap = "False" as my build MSBuild argument. But the transform still doesn't occur. Apparently, this variable is used to determine when to perform the transform in SlowCheetah but I'm not sure this is applicable since it seems to be for SlowCheetah v2. How can I get SlowCheetah to transform on build using TFS? What else can I try?

  • 2
    You have tagged the questions with TDS. Are you using TDS classic? – Vicent Galiana Aug 7 '17 at 8:00
  • Yes, we are using TDS Classic – uioporqwerty Aug 7 '17 at 8:04
2

If you have TDS, it can do the configuration transformation for you, as you do for web.config files. It is there since version 4 as you can see here. NO need for extra configuration or software. It does the clean-up in the results folder, meaning you don't need to worry about anything . Depending on how you later publish your files, it can be a bit tricky to find and move them to the target server. In my case, I build the TDS project related to master, and then I do MSdeploy of the results to the server.

It means a build per environment, who some consider wrong by definition, but at the same time, it means you can add as new settings depending on the environment, without having to modify the deployment process, just your solution.

| improve this answer | |
  • Interesting, I had come across this article while Googling but this also carries with it the one build configuration per environment issue with it that Richard Seal above mentioned correct? I suppose this is one of those areas where there are multiple ways to do the same thing but you just have to figure out what works best for your company? If so, I'll bring it up with the team to see which they prefer before I dive too deep. – uioporqwerty Aug 7 '17 at 13:29
  • 1
    I think so, I like the idea of one build for every server, but at the same time I like the idea of set and forget the build definition. For me the key thing is simplicity. If TDS can do many things without further complexities, reducing the amount of tools and settings, I go for it. – Vicent Galiana Aug 7 '17 at 13:36
1

Update

So as a direct answer to your question - a PowerShell script can help with this as you have found. But this is not a good way of controlling environment config transforms. Doing it this way requires you to create a unique build for each environment. That is inherently a flawed way of deploying. It means that the code you test in DEV or UAT etc... is not the same as the code that you deploy to Production.

For environment config transforms you should be doing this in Release Manager, not as part of your build. Set up tokens that Release Manager (or whatever your release management tool is, e.g Octopus Deploy) can replace on deployment.

This is much better than having everything in build transforms, as you then only need to build once. You shouldn't have to build for each environment.

| improve this answer | |
  • Hmm, but SlowCheetah does come as a NuGet package for the build server to restore. The plugin is only necessary to preview and create the initial transform files, but not for the actual transform afaik. I'll look into the Release Manager route, but I'll leave the question open as I think there might be a way to use SlowCheetah and remove the environment configs after transform. – uioporqwerty Aug 6 '17 at 14:25
  • 1
    You could also use a PowerShell script to do that – Richard Seal Aug 6 '17 at 14:26
  • Yeah, I was wondering if there is a minimatch pattern that could look for something like Ends With $(BuildConfiguration).config in a directory? And that could run after the transform has taken place. – uioporqwerty Aug 6 '17 at 14:28
  • Ok, thank you for the update. I'll look into TFS release management some more to see how this would be possible. But the question I have is, why would TFS allow you to build for multiple configurations in one check-in? What use-case scenario does that serve if not one build per environment? – uioporqwerty Aug 7 '17 at 2:09
  • 1
    For that - you would use SlowCheetah and have a .debug transform that would transform the settings for local development. – Richard Seal Aug 7 '17 at 15:21
0

So, as it turns out SlowCheetah does perform the transforms on build, but after looking at the diagnostic build logs the transformed config files are stored in the bin/$(Environment)/App_Config/Include directory. So it should be easy enough to create a Powershell script(s) that do the following:

Grab all config files in bin/$(BuildPlatform)/App_Config/*, overwrite the ones in the Source/App_Config/* directory, and then remove all config files that EndsWith $(BuildPlatform).config.

Here is a small PS script I wrote that does this, could be better but it gets the job done, I think:

<# 
    Apply configuration transforms from the bin/App_Config directory after successful build and remove environment specific config files.
#>
param([string]$BuildConfiguration)

$ENVIRONMENTS = @("Dev", "Local", "QA", "Release", "Stage")

<# 
    Remove environment config files.
#>
function RemoveEnvironmentConfigs() {
    For ($i = 0; $i -lt $ENVIRONMENTS.Length; $i++) {
        $Environment = $ENVIRONMENTS[$i]
        Get-ChildItem ..\Project\App_Config\ -Include "*$Environment.config" -Recurse | ForEach-Object ($_) { 
            Remove-Item $_.FullName -Force
        }
    }
}

<#
    Copy transformed config files from bin/$(BuildConfiguration)
#>
function CopyTransformedConfigs() {
    If ($ENVIRONMENTS -notcontains $BuildConfiguration) {
        Throw "Error finding $BuildConfiguration"
    }

    Copy-Item -Path ..\Project\bin\$BuildConfiguration\App_Config -Filter *.config -Destination ..\Project\ -Force -Recurse
}

RemoveEnvironmentConfigs
CopyTransformedConfigs
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.