BTDF / DeploymentFramework

The Deployment Framework for BizTalk is the most powerful and customizable, yet easy-to-use toolkit for deploying and configuring your BizTalk solutions.
MIT License
53 stars 24 forks source link

Add SkipExportSettings property to support pre-prepared settings files. #454

Closed eloekset closed 5 years ago

eloekset commented 5 years ago

Fixes #453

Makes it possible to use Octopus to prepare values for the environment and then call MSBuild for the Deploy target, passing /p:SkipExportSettings="true" to avoid overwriting the prepared <env>_settings.xml file for the environment.

eloekset commented 5 years ago

Have you considered this yet, @tfabraham? It is a non-breaking change. I hope to get it merged and released asap to be able to continue using the official release of BTDF.

eloekset commented 5 years ago

To clarify a bit more why I wan't this change, I'll post the Octopus process that I use here: image

The origin is this TechNet Wiki page: https://social.technet.microsoft.com/wiki/contents/articles/33474.biztalk-server-continuous-deployment-of-applications-built-using-btdf-and-octopus-deploy.aspx

I've continued developing the source to work for BizTalk 2016 and extended it with a bit more functionality.

Each step in the process contains small PowerShell scripts that depend on a PowerShell module globally available for all Octopus projects. The module is in the develop branch here: https://github.com/eloekset/publish-btdfBiztalkApplication

A copy of all code snippets in each step is in the following block:

1. Unpublish existing application
    ##Octopus environment variables required for this deployment, 
    ##For non-clustered BizTalk server environments set this to true always
    $IsFirstBiztalkServer = $OctopusParameters['Octopus.Machine.Roles'] -contains "biztalk-primary"
    $IsFirstBiztalkServer = $True #for some reason the test above doesn't work
    $appPoolIdentity = $OctopusParameters['AppPoolIdentity'] 
    $appPoolPassword = $OctopusParameters['AppPoolPassword']
    $undeployDependentApps = $OctopusParameters['Octopus.Environment.Name'].StartsWith("DEV")

    ##initialise variables
    $backupDir = Join-Path "C:\BizTalkApps" "Backup"
    $biztalkAppName = $OctopusParameters["BizTalkApplicationName"]
    $btdfProductName = $biztalkAppName

    ##If you have more options in your BTDF installwizard.xml, just add them  as name value pairs as shown here.
    ##PS. The /p: is mandatory : 
    ##Make sure the names or values with spaces are enclosed within double quotes.
    ##Double quotes in PowerShell strings can be escaped using "" or `"
    ##In this example, see the value of /p:ENV_Settings is escaped with ""
    Write-Verbose "App pool identity: $appPoolIdentity"
    $deployOptions = @{"/p:VDIR_USERNAME"="$($appPoolIdentity)";
       "/p:VDIR_USERPASS"="$($appPoolPassword)";
       "/p:BTSACCOUNT"="biztalk";
    }

    New-Item $backupDir -ItemType Container -Force

    #unpublish using the powershell module. 
    unpublish-btdfbiztalkapplication -verbose -btdfProductName $btdfProductName -biztalkApplicationName  $biztalkAppName -importIntoBiztalkMgmtDb $IsFirstBiztalkServer -backupdir $backupDir -undeployOptions $undeployOptions -undeployDependentApps $undeployDependentApps

    ##To see more options available to customise you deployment including custom undeploy options, set msbuild or BTS task paths use get-help
    #Get-Help Unpublish-BTDFBiztalkApplication -Detailed 
    ##To troubleshoot and increase log level use the -Verbose switch
    #Unpublish-BTDFBiztalkApplication -verbose

2. Install MSI
    ##Get MSI from nuget package.
    $installDir = $OctopusParameters['Octopus.Action[Deploy package].Output.Package.InstallationDirectoryPath']
    Set-OctopusVariable -name "InstallDir" -value $installDir

    ##This assumes you have created a nuget package with the msi and the msi is under content dir when the nuget package is unpacked
    $Msi = Get-Item "$(Join-Path $installDir $OctopusParameters["BizTalkApplicationName"])*.msi"

    ##initialise variables
    $installOptions = $NULL
    install-btdfBiztalkApp -Verbose $Msi -installDir $installdir -installOptions $installOptions

3. Export environment settings
    ##Get MSI from nuget package.
    $installDir = $OctopusParameters['Octopus.Action[Install MSI].Output.InstallDir']
    Write-Verbose "installDir = $installDir"

    #Run EnvironmentSetttingsExporter.exe to genereate xml file for environment 
    #to replace its values with matching Octopus variables
    $settingsFolder = Export-EnvironmentSettings $installDir
    Set-OctopusVariable -name "SettingsFolder" -value $settingsFolder

4. Custom substitute values in settings file
    # Call Substitute-XmlSettingsFileValues in script module
    $settingsFolder = $OctopusParameters["Octopus.Action[Export environment settings].Output.SettingsFolder"]
    $settingsFilePath = Join-Path $settingsFolder "Octopus_settings.xml"
    Substitute-XmlSettingsFileValues $settingsFilePath $OctopusParameters

5. Deploy application
    ##Octopus environment variables required for this deployment, 
    ##For non-clustered BizTalk server environments set this to true always
    #$IsFirstBiztalkServer = $true
    $MachineRoles = $OctopusParameters['Octopus.Machine.Roles']
    foreach($r in $MachineRoles)
    {
        Write-Host "Role: $r"
    }
    $IsFirstBiztalkServer = $OctopusParameters['Octopus.Machine.Roles'] -contains "biztalk-primary"
    $IsFirstBiztalkServer = $True #for some reason the test above doesn't work
    Write-Verbose "IsFirstBiztalkServer = $IsFirstBiztalkServer"
    $appPoolIdentity = $OctopusParameters['AppPoolIdentity'] 
    $appPoolPassword = $OctopusParameters['AppPoolPassword']

    ##initialise variables
    $btdfProductName = $OctopusParameters["BizTalkApplicationName"]

    ##If you have more options in your BTDF installwizard.xml, just add them  as name value pairs as shown here.
    ##PS. The /p: is mandatory : 
    ##Make sure the names or values with spaces are enclosed within double quotes.
    ##Double quotes in PowerShell strings can be escaped using "" or `"
    ##In this example, see the value of /p:ENV_Settings is escaped with ""
    $octpousEnvironmentSettingsFile = "Octopus_settings.xml"
    $envSettingsPath = $OctopusParameters["Octopus.Action[Export environment settings].Output.SettingsFolder"]
    $octpousEnvironmentSettingsPath = (Join-Path $envSettingsPath $octpousEnvironmentSettingsFile)
    Write-Verbose "Settings path: $octpousEnvironmentSettingsPath"
    Write-Verbose "App pool identity: $appPoolIdentity"
    $deployOptions = @{"/p:VDIR_USERNAME"="$($appPoolIdentity)";
       "/p:VDIR_USERPASS"="$($appPoolPassword)";
       "/p:BTSACCOUNT"="biztalk";
       "/p:SettingsFilePath"="""$($octpousEnvironmentSettingsPath)""";
       "/p:SkipExportSettings"="true";
    }

    ##Deploy using the powershell module. 
    Deploy-BTDFBiztalkApp -verbose -btdfProductName $btdfProductName -importIntoBiztalkMgmtDb $IsFirstBiztalkServer -deployOptions $deployOptions
    ##To see more options available to customise you deployment including custom undeploy options, set msbuild or BTS task paths use get-help
    #Get-Help Deploy-BTDFBiztalkApp -Detailed 
    ##To troubleshoot and increase log level use the -Verbose switch
    #Deploy-BTDFBiztalkApp -verbose

Step 5 contains the SkipExportSettings parameter that I need.

tfabraham commented 5 years ago

A simple way to achieve the same result is to delete or rename SettingsFileGenerator.xml immediately after the export. The export will be skipped with a simple message "Skipping settings file export because file at SettingsSpreadsheetPath does not exist: [path]". And no changes required to the Framework.

eloekset commented 5 years ago

Thanks for you answer, @tfabraham! This was a nice workaround. 😊

I can confirm that it works like you said: image

For completeness, I'll post the updated script snippets for steps 3 and 5:

Step 3:

##Get MSI from nuget package.
$installDir = $OctopusParameters['Octopus.Action[Install MSI].Output.InstallDir']
Write-Verbose "installDir = $installDir"

#Run EnvironmentSetttingsExporter.exe to genereate xml file for environment 
#to replace its values with matching Octopus variables
$settingsFolder = Export-EnvironmentSettings $installDir
Set-OctopusVariable -name "SettingsFolder" -value $settingsFolder

#Delte SettingsFileGenerator.xml so BTDF doesn't overwrite our exported settings on deploy
$sourceSettingsFile = Join-Path $settingsFolder "SettingsFileGenerator.xml"
Remove-Item -Path $sourceSettingsFile

Step 5:

##Octopus environment variables required for this deployment, 
##For non-clustered BizTalk server environments set this to true always
#$IsFirstBiztalkServer = $true
$MachineRoles = $OctopusParameters['Octopus.Machine.Roles']
foreach($r in $MachineRoles)
{
    Write-Host "Role: $r"
}
$IsFirstBiztalkServer = $OctopusParameters['Octopus.Machine.Roles'] -contains "biztalk-primary"
$IsFirstBiztalkServer = $True #for some reason the test above doesn't work
Write-Verbose "IsFirstBiztalkServer = $IsFirstBiztalkServer"
$appPoolIdentity = $OctopusParameters['AppPoolIdentity'] 
$appPoolPassword = $OctopusParameters['AppPoolPassword']

##initialise variables
$btdfProductName = $OctopusParameters["BizTalkApplicationName"]

##If you have more options in your BTDF installwizard.xml, just add them  as name value pairs as shown here.
##PS. The /p: is mandatory : 
##Make sure the names or values with spaces are enclosed within double quotes.
##Double quotes in PowerShell strings can be escaped using "" or `"
##In this example, see the value of /p:ENV_Settings is escaped with ""
$octpousEnvironmentSettingsFile = "Octopus_settings.xml"
$envSettingsPath = $OctopusParameters["Octopus.Action[Export environment settings].Output.SettingsFolder"]
$octpousEnvironmentSettingsPath = (Join-Path $envSettingsPath $octpousEnvironmentSettingsFile)
Write-Verbose "Settings path: $octpousEnvironmentSettingsPath"
Write-Verbose "App pool identity: $appPoolIdentity"
$deployOptions = @{"/p:VDIR_USERNAME"="$($appPoolIdentity)";
   "/p:VDIR_USERPASS"="$($appPoolPassword)";
   "/p:BTSACCOUNT"="biztalk";
   "/p:SettingsFilePath"="""$($octpousEnvironmentSettingsPath)""";
}

##Deploy using the powershell module. 
Deploy-BTDFBiztalkApp -verbose -btdfProductName $btdfProductName -importIntoBiztalkMgmtDb $IsFirstBiztalkServer -deployOptions $deployOptions
##To see more options available to customise you deployment including custom undeploy options, set msbuild or BTS task paths use get-help
#Get-Help Deploy-BTDFBiztalkApp -Detailed 
##To troubleshoot and increase log level use the -Verbose switch
#Deploy-BTDFBiztalkApp -verbose

As long as the framework doesn't fail on missing SettingsFileGenerator.xml, the change of this PR won't be needed, so I'll close it and update and close the related issue that I created.

eloekset commented 5 years ago

For anyone interested, I've now created a wiki page on how to setup an Octopus Deploy process. The wiki page will be updated, while the code posted in the previous comment above won't. https://github.com/eloekset/publish-btdfBiztalkApplication/wiki/Octopus-Deploy