DEV Community

Anton Kuryan
Anton Kuryan

Posted on • Originally published at dobryak.org on

1 2

Transforming deployed configuration file in Azure web app

While this guide is primarily targeted towards usage with Azure Web apps and Sitecore ASP.NET solution deployed on them, still it is possible to use it on on-premise solution with other types on ASP.NET projects, running on Windows.

Reasoning behind this

Why I actually started building all this thing up, ignoring interesting Helix publishing pipeline or dropping idea of storing source and transformation files in my source control?

In Helix publishing pipeline I do not like the fact that I could not use different transformation based on roles, where I am deploying (if it is there - can you point it to me?).

When storing vanilla config in source control - I do not like the fact that I will need to update it when I am updating Sitecore version (hence, merging and solving possible conflicts).

Solution

So, I decided to build this transformation thing anew, almost from scratch. I used the same idea as used in Helix publishing pipeline: store only transformation files under source control, as, in general, they are generic. Also, I agreed on following naming convention:

  • configFileName.config.xdt - transforms config file with name configFileName.config lying at this path for all environments
  • configFileName.config.xdt.roleName - transforms config file with name configFileName.config lying at this path when deploying this particular role
param(
[string]$folderWithTransforms,
[string]$webRoot,
[string]$roleName,
[string]$transformationAssemblyPath
)
Write-Output "Starting collecting files for transformations"
if ([string]::IsNullOrWhiteSpace($folderWithTransforms)) {
Write-Output "folderWithTransforms is not defined, so we are assuming it is same folder as script"
$folderWithTransforms = $PSScriptRoot
Write-Output "folderWithTransforms is $folderWithTransforms"
}
if ([string]::IsNullOrWhiteSpace($webRoot)) {
Write-Output "Webroot is not defined - so, we'll try to define it by convention"
$webRoot = Join-Path -Path $folderWithTransforms -ChildPath ..\.. -Resolve
Write-Output "webRoot is $webRoot"
}
function TransformFile {
param(
[string]$fileToTransform,
[string]$transformationFile,
[string]$transformationAssemblyPath
)
if ([string]::IsNullOrWhiteSpace($transformationAssemblyPath)) {
Write-Output "Loading Microsoft.Web.XmlTransform.dll from script directory"
Add-Type -Path $PSScriptRoot\Microsoft.Web.XmlTransform.dll
} else {
Write-Output "Loading Microsoft.Web.XmlTransform.dll from $transformationAssemblyPath"
Add-Type -Path $transformationAssemblyPath
}
$target = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
$target.PreserveWhitespace = $true
Write-Output "Loading $fileToTransform"
$target.Load($fileToTransform);
Write-Output "Transforming $fileToTransform with $transformationFile"
$transformation = New-Object Microsoft.Web.XmlTransform.XmlTransformation($transformationFile);
if ($transformation.Apply($target) -eq $false)
{
throw "XDT transformation failed."
}
$target.Save($fileToTransform);
Write-Output "Finished transformation"
}
if ([string]::IsNullOrWhiteSpace($roleName)) {
$filter = ".xdt"
} else {
$filter = ".xdt.$roleName"
}
$extensionFilter = "*$filter"
Write-Output "Filtering for $extensionFilter"
$helixFolders = "Hotfix", "Website", "Project", "Foundation", "Feature"
$transformationFiles = @()
foreach($folder in $helixFolders) {
#to get ordered transformation - I wish to traverse folders based on theirs helix naming convention
$helixTransformPath = Join-Path $folderWithTransforms $folder
$transformationFiles += Get-ChildItem -Path $helixTransformPath -Filter $extensionFilter -r
}
foreach($transformFile in $transformationFiles) {
$configToTransform = $transformFile.FullName.ToLowerInvariant().Replace($folderWithTransforms.ToLowerInvariant(), [string]::Empty)
if ($configToTransform.ToLowerInvariant().Contains("bin") -or $configToTransform.ToLowerInvariant().Contains("obj")) {
continue;
}
$regex = [regex]::new(".+code\\(.+)\$filter")
$configToTransform = Join-Path $webRoot $regex.Replace($configToTransform, '$1')
TransformFile -fileToTransform $configToTransform -transformationFile $transformFile.FullName -transformationAssemblyPath $transformationAssemblyPath
}
view raw transform.ps1 hosted with ❤ by GitHub

That's is a script, which could be uploaded to web app and executed via Kudu. Script wants several parameters:

  • folderWithTransforms - (optional) folder, where all transform files are residing; if not specified - script folder is taken
  • webRoot - (optional) folder, where webRoot could be found; if not specified, folder 2 levels upper is taken
  • roleName - optional, if there is a specific tranformations for this particular role
  • transformationAssemblyPath - if Microsoft.Web.XmlTransform.dll is not at the same path as script

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay