Functions/Test-ShouldDeployDacpac.ps1
|
<#
.SYNOPSIS Determines whether a DACPAC should be deployed to a database. .DESCRIPTION The Test-ShouldDeployDacpac function analyzes various conditions to determine if a DACPAC file should be deployed to a target database. It checks for database existence, compares deployment settings, examines file dates, and optionally compares hashes to make the deployment decision. .PARAMETER settings Specifies the settings object containing connection and deployment configuration information. This can include properties like serverName, TargetDatabaseName, sqlAdminLogin, etc. .PARAMETER SettingsToCheck Optional. Specifies the specific settings to monitor for changes. If not provided, default settings will be retrieved based on the DACPAC file and connection settings. .PARAMETER dacpacfile Specifies the path to the DACPAC file to evaluate for deployment. .PARAMETER publishFile Specifies the path to the publish profile file. Currently not used for change detection but included for potential future use. .PARAMETER DBDeploySettingsFile Optional. Specifies the path to a file-based deployment settings file. If provided, the function will use file-based comparison instead of database-based comparison. .PARAMETER IgnoreDate Optional switch. When specified, ignores the DACPAC file date when determining if deployment is needed. Only settings changes will trigger deployment. .PARAMETER CompareHash Optional switch. When specified, compares the DACPAC hash with the previously stored hash to determine if the DACPAC content has changed. .OUTPUTS Boolean Returns $true if the DACPAC should be deployed, $false otherwise. .EXAMPLE $settings = @{ serverName = "localhost" TargetDatabaseName = "MyDB" sqlAdminLogin = "sa" sqlAdminPassword = "password" } Test-ShouldDeployDacpac -settings $settings -dacpacfile "C:\MyApp.dacpac" Determines if MyApp.dacpac should be deployed to MyDB on localhost. .EXAMPLE Test-ShouldDeployDacpac -settings $settings -dacpacfile "MyApp.dacpac" -CompareHash Uses hash comparison to determine if the DACPAC content has changed since last deployment. .EXAMPLE Test-ShouldDeployDacpac -settings $settings -dacpacfile "MyApp.dacpac" -IgnoreDate Determines deployment need based only on settings changes, ignoring file modification dates. .NOTES The function checks multiple conditions for deployment: - Database doesn't exist - No previous deployment settings found - Deployment settings have changed - DACPAC file is newer than last deployment (unless IgnoreDate is used) - DACPAC hash has changed (if CompareHash is used) If any error occurs during evaluation, the function defaults to returning $true (deploy). #> Function Test-ShouldDeployDacpac { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification = "Need to cater for users that want to pass strings ")] [CmdletBinding()] param ( [Parameter(Mandatory = $true, HelpMessage = "Settings object containing deployment configuration")] $settings, [Parameter(HelpMessage = "Specific settings to monitor for changes")] $SettingsToCheck, [Parameter(Mandatory = $true, HelpMessage = "Path to the DACPAC file")] [string]$dacpacfile, [Parameter(HelpMessage = "Path to the publish profile file")] [string]$publishFile, [Parameter(HelpMessage = "Path to file-based deployment settings")] [string]$DBDeploySettingsFile, [Parameter(HelpMessage = "Ignore DACPAC file date when determining deployment")] [Switch]$IgnoreDate, [Parameter(HelpMessage = "Compare DACPAC hash to determine if content changed")] [switch]$CompareHash ) $shouldDeploy = $false $TargetUser = "" $TargetServer = "" $TargetPasswordSecure = $null if ($settings.sqlAdminLogin) { $TargetUser = $settings.sqlAdminLogin $TargetPasswordSecure = $settings.sqlAdminPassword | ConvertTo-SecureString -AsPlainText -Force } if ($settings.TargetUser) { $TargetUser = $settings.TargetUser $TargetPasswordSecure = $settings.TargetPasswordSecure } if ($settings.TargetDatabaseName) { $TargetDatabaseName = $settings.TargetDatabaseName } if ($settings.serverName) { $TargetServer = $settings.serverName } if ($settings.TargetServerName) { $TargetServer = $settings.TargetServerName } if ($null -eq $settings.publishFile){ $settings.publishFile = $publishFile } if ($null -ne $Settings.publishFile) { Write-Host "Publish File is not currently used to check if settings have changed. Consider adding publish file as a value in the settings parameter" } #Check date of dacpac against last deployment time $dacpacDate = (Get-Item $dacpacfile).LastWriteTimeUtc if ($null -eq $SettingsToCheck){ $SettingsToCheck = Get-DefaultSettingsToCheck -dacpacfile $dacpacfile @settings } try { Write-Host "Checking if we should deploy database" $databaseExists = Test-DatabaseExists ` -TargetServer $TargetServer ` -TargetUser $TargetUser ` -TargetPasswordSecure $TargetPasswordSecure ` -TargetDatabaseName $TargetDatabaseName Write-Verbose "Database exists query result ($databaseExists)" if (-not $databaseExists) { Write-Host "Should deploy because database doesn't exist" $shouldDeploy = $true } else { #Get latest deploy for the required dacpac if ([string]::IsNullOrWhiteSpace($DBDeploySettingsFile)) { $dacpacname = (Get-Item $dacpacfile).basename $SettingsFromDB = Get-DeploySettingsFromDB -DacpacName $dacpacName -Server $TargetServer -User $TargetUser -PasswordSecure $TargetPasswordSecure -Database $TargetDatabaseName if ($null -eq $SettingsFromDB) { Write-Host "no settings in DB need to deploy" $shouldDeploy = $true } elseif (Test-HaveDeploySettingsChangedSinceLastDeploy -OldSettings $SettingsFromDB.SettingsToCheck -Settings $SettingsToCheck) { Write-Host "ShouldDeploy? Yes - settings have changed" $shouldDeploy = $true } elseif (-not $IgnoreDate -and $SettingsFromDB.LastDeployDate -lt $dacpacDate) { Write-Host "last deploy date < dacpac date so we do need to deploy the database" $shouldDeploy = $true } elseif($CompareHash){ $Hash = Get-DacpacHash $dacpacfile $shouldDeploy = ($SettingsFromDB.Hash -ne $Hash) } } else { #previous behaviour using a DBDeploySettingsFile if (Test-IsPreviousDeploySettingsFileMissing -DBDeploySettingsFile $DBDeploySettingsFile) { Write-Host "ShouldDeploy? Yes - no settings file" $shouldDeploy = $true } elseif (Test-HaveDeploySettingsChangedSinceLastDeploy -OldSettings (Get-DeploySettingsFromFile -DBDeploySettingsFile $DBDeploySettingsFile ) -Settings $SettingsToCheck) { Write-Host "ShouldDeploy? Yes - settings have changed" $shouldDeploy = $true } else { $dacpacname = (Get-Item $dacpacfile).basename $SettingsFromDB = Get-DeploySettingsFromDB -DacpacName $dacpacName -Server $TargetServer -User $TargetUser -PasswordSecure $TargetPasswordSecure -Database $TargetDatabaseName if ($null -eq $SettingsFromDB ) { Write-Host "no settings found in Db for $dacpacname" $shouldDeploy = $true } elseif (-not $IgnoreDate -and $SettingsFromDB.LastDeployDate -lt $dacpacDate) { Write-Host "last deploy date < dacpac date so we do need to deploy the database" $shouldDeploy = $true } } } } } catch { Write-Host "Error Occurred -verbose logging for more detail if required" Write-Verbose ($_ | Format-Table | Out-String) $shouldDeploy = $true } Write-Verbose "Returning from Test-ShouldDeployDacpac with ,$shouldDeploy = $shouldDeploy" return $shouldDeploy } |