Monday, February 13, 2012

Continuous Delivery with psake and TeamCity - Config Templates

The series so far:

  1. Creating a Local Build With psake, Part 1: Compiling
  2. Creating a Local Build with psake, Part 2: Testing
  3. Continuous Delivery with psake and TeamCity - Reusing the Local Build to Create a CI Build
  4. Continuous Delivery with psake and TeamCity - Preparing for a pipeline
  5. Continuous Delivery with psake and TeamCity - Creating a pipeline with artifact dependencies
  6. Continuous Delivery with psake and TeamCity - Visualizing a pipeline
  7. Continuous Delivery with psake and TeamCity - Environment Configuration Management
  8. Continuous Delivery with psake and TeamCity - Time for Some Refactoring

When we are deploying we always do some config transforms so that the application is configured for the right environment. In Nant we got xmlpoke, in msbuild 4.0 we got XmlPoke and there's also web.config transforms in .Net 4.0 which has been transformed to a general config transformation tool. In psake there isn’t something like this available, however as James Kovacks himself says, it’s very easy to do with PowerShell. I’ve created a little PowerShell script called Replace-Tokens, which you can find on GitHub, that does the work. Given a file some.template:

hello #{world}

and a file some.data.ps1:

@{
    world = 'world'
}

When we run:

replace_tokens_with_file "some.data.ps1" "some.template" "output.txt"

The output is the file output.txt:

hello world

The main idea here is that we pass in a hash table who's keys will be located in the template file and swapped by the value. We can also pass in a hash table directly instead of a file. So referring to my former post,  if we were to change the app.config of the application when deploying to Test and Acceptance Test  we could use the script and do the transformation. Change the test.ps1 properties file to:

$database_server = "Server 2"

$app_config_data = @{
    "database_connection_string" = "Data Source=$database_server;Initial Catalog=App;Integrated security = true";
}

Then change the deploy task of deploy.ps1 to:

task deploy -depends set_build_number{
    Write-Output "deploying to $env => database is deployed to $database_server"
    $app_path = "$build_artifacts_dir\Debug\ContinuousDelivery.WpfApplication"
    $config_file = "ContinuousDelivery.WpfApplication.exe.config"
    replace_tokens $app_config_data "$configs_dir\$config_file.template" "$app_path\$config_file"
}

Note that we pass in the $app_config_data from the test environment properties file. Now we just need to create a template of the app.config called ContinuousDelivery.WpfApplication.exe.config.template and place in in folder called configs under the build folder:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="database" connectionString="#{database_connection_string}"/>
  </connectionStrings>
</configuration>

This will overwrite the app.config based on the values found in the environment specific properties file when we deploy. Download the code from GitHub.

No comments:

Post a Comment