Octopus.Script exported 2026-03-13 by bcullman belongs to ‘SQL Server’ category.
This step template will deploy SSIS ispac projects to SQL Server Integration Services Catalog. The template uses a referenced package and is Worker compatible.
This template will install the Nuget package provider if it is not present on the machine it is running on.
NOTE: The SqlServer PowerShell module this template utilizes removed the assemblies necessary to interface with SSIS as of version 22.0.59. Version 21.1.18256 has been pinned and will be used if the SqlServer PowerShell module is not installed.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Database server name (\instance)
SSIS.Template.ServerName =
Name of the SQL Server you are deploying to.
SQL Authentication Username
SSIS.Template.sqlAccountUsername =
(Optional) Username of the SQL Authentication account. Use this approach when deploying to Azure Databases with SSIS configured. If SQL Authentication Username and Password are blank, Integrated Authentication is used.
SQL Authentication Password
SSIS.Template.sqlAccountPassword =
(Optional) Password of the SQL Authentication account.
Enable SQL CLR
SSIS.Template.EnableCLR = False
This will reconfigure SQL Server to enable the SQL CLR. It is highly recommended that this be previously authorized by your Database Administrator.
Catalog name
SSIS.Template.CatalogName = SSISDB
Name of the catalog to create in Integration Services Catalogs on SQL Server. When using the GUI, this value gets hardcoded to SSISDB and cannot be changed. It is recommended that you do not change the default value.
Catalog password
SSIS.Template.CatalogPwd =
Password to the Integration Services Catalog.
Folder name
SSIS.Template.FolderName =
Name of the folder to use within the Integration Services Catalog
Use environment
SSIS.Template.UseEnvironment = False
This will make a project reference to the defined environment.
Environment name
SSIS.Template.EnvironmentName =
Name of the environment to reference the project to. If the environment doesn’t exist, it will create it.
Reference project parameters to environment variables
SSIS.Template.ReferenceProjectParametersToEnvironmentVairables = False
Checking this box will make Project Parameters reference Environment Variables. If the Environment Variable doesn’t exist, it will create it. This expects that an Octopus variable of the same name exists.
Reference package parameters to environment variables
SSIS.Template.ReferencePackageParametersToEnvironmentVairables = False
Checking this box will make Package Parameters reference Environment Variables. If the Environment Variable doesn’t exist, it will create it. This expects than an Octopus variable of the same name exists.
Use Fully Qualified Variable Names
SSIS.Template.UseFullyQualifiedVariableNames = False
When true the package variables names must be represented in dtsx_name_without_extension.variable_name
Use Custom Filter for connection manager properties
SSIS.Template.UseCustomFilter = False
Custom filter should contain the regular expression for ignoring properties when setting will occur during the auto-mapping
Custom Filter for connection manager properties
SSIS.Template.CustomFilter =
Regular expression for filtering out the connection manager properties during the auto-mapping process. This string is used when UseCustomFilter is set to true
Clean obsolete variables from environment
SSIS.Template.SyncEnvironment = False
When true synchronizes the environment:
- Removes obsolete variables
- Removes renamed variables
- Replaces values of valid variables (also when
false)
Package Id
SSIS.Template.ssisPackageId =
Id of the package to deploy, used to support deployment with Workers.
Script body
Steps based on this template will execute the following PowerShell script.
function Add-TemporaryPinnedSqlServerModule
{
# Define parameters
param(
$LocalModulesPath
)
$PowerShellModuleName = "SqlServer"
$RequiredVersion = [version]'21.1.18256'
# Check to see if the package provider has been installed
if ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))
{
# Display that we need the nuget package provider
Write-Host "Nuget package provider not found, installing ..."
# Install Nuget package provider
Install-PackageProvider -Name Nuget -Force
}
# Save the module in the temporary location
Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force -RequiredVersion $RequiredVersion -Repository "PSGallery"
# Display
Write-Output "Saved module $PowerShellModuleName v$RequiredVersion to $LocalModulesPath"
# Import the module
Import-Module -Name $PowerShellModuleName
}
Function Remove-TemporaryPinnedSqlServerModule
{
param(
[Parameter(Mandatory = $true)][string]$LocalModulesPath,
[Parameter(Mandatory = $true)][version]$PinnedVersion
)
try { Remove-Module SqlServer -Force -ErrorAction SilentlyContinue } catch {}
$moduleRoot = Join-Path $LocalModulesPath 'SqlServer'
$pinnedPath = Join-Path $moduleRoot $PinnedVersion.ToString()
if (Test-Path $pinnedPath)
{
Write-Host "Removing temporary pinned SqlServer module folder: $pinnedPath"
Remove-Item -Path $pinnedPath -Recurse -Force -ErrorAction SilentlyContinue
}
# Optional: remove parent if empty
if (Test-Path $moduleRoot)
{
$remaining = Get-ChildItem -Path $moduleRoot -Force -ErrorAction SilentlyContinue
if (-not $remaining)
{
Remove-Item -Path $moduleRoot -Force -ErrorAction SilentlyContinue
}
}
}
Function Test-IntegrationServicesTypeAvailable
{
# True if the IntegrationServices type resolves in this PowerShell session, else false
$typeName = 'Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices'
$aqn = "$typeName, Microsoft.SqlServer.Management.IntegrationServices"
try
{
if ([Type]::GetType($aqn, $false)) { return $true }
}
catch {}
# Try to load assembly (strong name), may fail on some boxes
try { [void][Reflection.Assembly]::Load('Microsoft.SqlServer.Management.IntegrationServices') } catch {}
try
{
if ([Type]::GetType($aqn, $false)) { return $true }
}
catch {}
# Fall back to explicit GAC path load (LoadFrom) if present
$gacRoot = Join-Path $env:windir 'Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.Management.IntegrationServices'
if (Test-Path $gacRoot)
{
$gacDll = Get-ChildItem -Path $gacRoot -Recurse -Filter 'Microsoft.SqlServer.Management.IntegrationServices.dll' -File -ErrorAction SilentlyContinue |
Sort-Object FullName -Descending |
Select-Object -First 1
if ($null -eq $gacDll)
{
try
{
$asm = [Reflection.Assembly]::LoadFrom($gacDll.FullName)
if ($asm.GetType('Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices', $false)) { return $true }
}
catch {}
}
}
try
{
if ([Type]::GetType($aqn, $false)) { return $true }
}
catch {}
return $false
}
Function Load-SqlServerAssemblies
{
# Get the folder where the SqlServer module ended up in
$sqlServerModulePath = [System.IO.Path]::GetDirectoryName((Get-Module SqlServer).Path)
# Loop through the assemblies
foreach($assemblyFile in (Get-ChildItem -Path $sqlServerModulePath -Exclude msv*.dll | Where-Object {$_.Extension -eq ".dll"}))
{
try
{
# Only load managed .NET assemblies (native DLLs will throw)
[void][System.Reflection.AssemblyName]::GetAssemblyName($assemblyFile.FullName)
# Load the managed assembly
[Reflection.Assembly]::LoadFrom($assemblyFile.FullName) | Out-Null
}
catch [System.BadImageFormatException]
{
# Native DLL (or wrong format), skip
}
}
}
Function Initialize-SsisDeploymentRuntime
{
param(
[Parameter(Mandatory = $true)][string]$LocalModulesPath,
[Parameter(Mandatory = $true)][version]$PinnedSqlServerVersion
)
# Define PowerShell Modules path
$env:PSModulePath = "$LocalModulesPath;$env:PSModulePath"
$runtime = [pscustomobject]@{
UsedPinnedSqlServerModule = $false
SsisTypeAvailable = $false
}
# First preference: use SSIS assemblies already available on the machine/session
$runtime.SsisTypeAvailable = Test-IntegrationServicesTypeAvailable
if ($runtime.SsisTypeAvailable)
{
Write-Host "SSIS IntegrationServices type is already available."
# Only need a SqlServer module for cmdlets such as Invoke-Sqlcmd
if ($null -ne (Get-Module -ListAvailable -Name "SqlServer"))
{
Import-Module -Name SqlServer -ErrorAction Stop
}
else
{
Write-Output "PowerShell module SqlServer not present, downloading temporary pinned copy for cmdlets ..."
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
Add-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModulesPath
$manifestPath = Join-Path (Join-Path (Join-Path $LocalModulesPath 'SqlServer') $PinnedSqlServerVersion.ToString()) 'SqlServer.psd1'
Write-Host "Importing pinned SqlServer module from: $manifestPath"
Import-Module -Name $manifestPath -Force -DisableNameChecking -ErrorAction Stop
$runtime.UsedPinnedSqlServerModule = $true
}
# SSIS type already resolved, no need to bulk-load module assemblies
return $runtime
}
# Second preference: fall back to pinned SqlServer module that still contains SSIS assemblies
Write-Output "SSIS IntegrationServices type not available via installed components. Downloading pinned SqlServer module $PinnedSqlServerVersion temporarily ..."
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
$manifestPath = Join-Path (Join-Path (Join-Path $LocalModulesPath 'SqlServer') $PinnedSqlServerVersion.ToString()) 'SqlServer.psd1'
if (-not (Test-Path $manifestPath))
{
Add-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModulesPath
}
Write-Host "Importing pinned SqlServer module from: $manifestPath"
Import-Module -Name $manifestPath -Force -DisableNameChecking -ErrorAction Stop
Load-SqlServerAssemblies
$runtime.UsedPinnedSqlServerModule = $true
$runtime.SsisTypeAvailable = Test-IntegrationServicesTypeAvailable
return $runtime
}
Function Get-Catalog
{
# define parameters
Param ($CatalogName)
# NOTE: using $integrationServices variable defined in main
# define working variables
$Catalog = $null
# check to see if there are any catalogs
if($integrationServices.Catalogs.Count -gt 0 -and $integrationServices.Catalogs[$CatalogName])
{
# get reference to catalog
$Catalog = $integrationServices.Catalogs[$CatalogName]
}
else
{
if((Get-CLREnabled) -eq 0)
{
if(-not $EnableCLR)
{
# throw error
throw "SQL CLR is not enabled."
}
else
{
# display sql clr isn't enabled
Write-Warning "SQL CLR is not enabled on $($sqlConnection.DataSource). This feature must be enabled for SSIS catalogs."
# enabling SQLCLR
Write-Host "Enabling SQL CLR ..."
Enable-SQLCLR
Write-Host "SQL CLR enabled"
}
}
# Provision a new SSIS Catalog
Write-Host "Creating SSIS Catalog ..."
$Catalog = New-Object "$ISNamespace.Catalog" ($integrationServices, $CatalogName, $OctopusParameters['SSIS.Template.CatalogPwd'])
$Catalog.Create()
}
# return the catalog
return $Catalog
}
Function Get-CLREnabled
{
# define parameters
# Not using any parameters, but am using $sqlConnection defined in main
# define working variables
$Query = "SELECT * FROM sys.configurations WHERE name = 'clr enabled'"
# execute script
$CLREnabled = Invoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database "master" -Query $Query | Select value
# return value
return $CLREnabled.Value
}
Function Enable-SQLCLR
{
$QueryArray = "sp_configure 'show advanced options', 1", "RECONFIGURE", "sp_configure 'clr enabled', 1", "RECONFIGURE "
# execute script
foreach($Query in $QueryArray)
{
Invoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database "master" -Query $Query
}
# check that it's enabled
if((Get-CLREnabled) -ne 1)
{
# throw error
throw "Failed to enable SQL CLR"
}
}
Function Get-Folder
{
# parameters
Param($FolderName, $Catalog)
$Folder = $null
# try to get reference to folder
if(!($Catalog.Folders -eq $null))
{
$Folder = $Catalog.Folders[$FolderName]
}
# check to see if $Folder has a value
if($Folder -eq $null)
{
# display
Write-Host "Folder $FolderName doesn't exist, creating folder..."
# create the folder
$Folder = New-Object "$ISNamespace.CatalogFolder" ($Catalog, $FolderName, $FolderName)
$Folder.Create()
}
# return the folder reference
return $Folder
}
Function Get-Environment
{
# define parameters
Param($Folder, $EnvironmentName)
$Environment = $null
# get reference to Environment
if(!($Folder.Environments -eq $null) -and $Folder.Environments.Count -gt 0)
{
$Environment = $Folder.Environments[$EnvironmentName]
}
# check to see if it's a null reference
if($Environment -eq $null)
{
# display
Write-Host "Environment $EnvironmentName doesn't exist, creating environment..."
# create environment
$Environment = New-Object "$ISNamespace.EnvironmentInfo" ($Folder, $EnvironmentName, $EnvironmentName)
$Environment.Create()
}
# return the environment
return $Environment
}
Function Set-EnvironmentReference
{
# define parameters
Param($Project, $Environment, $Folder)
# get reference
$Reference = $null
if(!($Project.References -eq $null))
{
$Reference = $Project.References[$Environment.Name, $Folder.Name]
}
# check to see if it's a null reference
if($Reference -eq $null)
{
# display
Write-Host "Project does not reference environment $($Environment.Name), creating reference..."
# create reference
$Project.References.Add($Environment.Name, $Folder.Name)
$Project.Alter()
}
}
Function Set-ProjectParametersToEnvironmentVariablesReference
{
# define parameters
Param($Project, $Environment)
$UpsertedVariables = @()
if($Project.Parameters -eq $null)
{
Write-Host "No project parameters exist"
return
}
# loop through project parameters
foreach($Parameter in $Project.Parameters)
{
# skip if the parameter is included in custom filters
if ($UseCustomFilter)
{
if ($Parameter.Name -match $CustomFilter)
{
Write-Host "- $($Parameter.Name) skipped due to CustomFilters."
continue
}
}
# Add variable to list of variable
$UpsertedVariables += $Parameter.Name
$Variable = $null
if(!($Environment.Variables -eq $null))
{
# get reference to variable
$Variable = $Environment.Variables[$Parameter.Name]
}
# check to see if variable exists
if($Variable -eq $null)
{
# add the environment variable
Add-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $Parameter.Name
# get reference to the newly created variable
$Variable = $Environment.Variables[$Parameter.Name]
}
# set the environment variable value
Set-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $Parameter.Name
}
# alter the environment
$Environment.Alter()
$Project.Alter()
return $UpsertedVariables
}
Function Set-PackageVariablesToEnvironmentVariablesReference
{
# define parameters
Param($Project, $Environment)
$Variables = @()
$UpsertedVariables = @()
# loop through packages in project in order to store a temp collection of variables
foreach($Package in $Project.Packages)
{
# loop through parameters of package
foreach($Parameter in $Package.Parameters)
{
# add to the temporary variable collection
$Variables += $Parameter.Name
}
}
# loop through packages in project
foreach($Package in $Project.Packages)
{
# loop through parameters of package
foreach($Parameter in $Package.Parameters)
{
if ($UseFullyQualifiedVariableNames)
{
# Set fully qualified variable name
$ParameterName = $Parameter.ObjectName.Replace(".dtsx", "")+"."+$Parameter.Name
}
else
{
# check if exists a variable with the same name
$VariableNameOccurrences = $($Variables | Where-Object { $_ -eq $Parameter.Name }).count
$ParameterName = $Parameter.Name
if ($VariableNameOccurrences -gt 1)
{
$ParameterName = $Parameter.ObjectName.Replace(".dtsx", "")+"."+$Parameter.Name
}
}
if ($UseCustomFilter)
{
if ($ParameterName -match $CustomFilter)
{
Write-Host "- $($Parameter.Name) skipped due to CustomFilters."
continue
}
}
# get reference to variable
$Variable = $Environment.Variables[$ParameterName]
# Add variable to list of variable
$UpsertedVariables += $ParameterName
# check to see if the parameter exists
if(!$Variable)
{
# add the environment variable
Add-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $ParameterName
# get reference to the newly created variable
$Variable = $Environment.Variables[$ParameterName]
}
# set the environment variable value
Set-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $ParameterName
}
# alter the package
$Package.Alter()
}
# alter the environment
$Environment.Alter()
return $UpsertedVariables
}
Function Sync-EnvironmentVariables
{
# define parameters
Param($Environment, $VariablesToPreserveInEnvironment)
foreach($VariableToEvaluate in $Environment.Variables)
{
if ($VariablesToPreserveInEnvironment -notcontains $VariableToEvaluate.Name)
{
Write-Host "- Removing environment variable: $($VariableToEvaluate.Name)"
$VariableToRemove = $Environment.Variables[$VariableToEvaluate.Name]
$Environment.Variables.Remove($VariableToRemove) | Out-Null
}
}
# alter the environment
$Environment.Alter()
}
Function Add-EnvironmentVariable
{
# define parameters
Param($Environment, $Parameter, $ParameterName)
# display
Write-Host "- Adding environment variable $($ParameterName)"
# check to see if design default value is empty or null
if([string]::IsNullOrEmpty($Parameter.DesignDefaultValue))
{
# give it something
$DefaultValue = "" # sensitive variables will not return anything so when trying to use the property of $Parameter.DesignDefaultValue, the Alter method will fail.
}
else
{
# take the design
$DefaultValue = $Parameter.DesignDefaultValue
}
# add variable with an initial value
$Environment.Variables.Add($ParameterName, $Parameter.DataType, $DefaultValue, $Parameter.Sensitive, $Parameter.Description)
}
Function Set-EnvironmentVariableValue
{
# define parameters
Param($Variable, $Parameter, $ParameterName)
# check to make sure variable value is available
if (-not $OctopusParameters){
Write-Host "[WARN] - OctopusParameters collection is empty"
}
else
{
if($OctopusParameters.ContainsKey($ParameterName))
{
# display
Write-Host "[ OK ] - $($ParameterName) updated."
# set the variable value
$Variable.Value = $OctopusParameters["$($ParameterName)"]
}
else
{
# warning
Write-Host "[WARN] - $($ParameterName) not in OctopusParameters collection."
}
}
# Set reference
$Parameter.Set([Microsoft.SqlServer.Management.IntegrationServices.ParameterInfo+ParameterValueType]::Referenced, "$($ParameterName)")
}
Function Invoke-SsisProjectDeployment
{
$LocalModules = (New-Item "$PSScriptRoot\Modules" -ItemType Directory -Force).FullName
$pinnedSqlServerVersion = [version]'21.1.18256'
$sqlConnection = $null
$runtime = $null
try
{
$runtime = Initialize-SsisDeploymentRuntime -LocalModulesPath $LocalModules -PinnedSqlServerVersion $pinnedSqlServerVersion
# Store the IntegrationServices Assembly namespace to avoid typing it every time
$ISNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
# ensure all boolean variables are true booleans
$EnableCLR = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.EnableCLR'])")
$UseEnvironment = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.UseEnvironment'])")
$ReferenceProjectParametersToEnvironmentVairables = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.ReferenceProjectParametersToEnvironmentVairables'])")
$ReferencePackageParametersToEnvironmentVairables = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.ReferencePackageParametersToEnvironmentVairables'])")
$UseFullyQualifiedVariableNames = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.UseFullyQualifiedVariableNames'])")
$SyncEnvironment = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.SyncEnvironment'])")
# custom names for filtering out the excluded variables by design
$UseCustomFilter = [System.Convert]::ToBoolean("$($OctopusParameters['SSIS.Template.UseCustomFilter'])")
$CustomFilter = [System.Convert]::ToString("$($OctopusParameters['SSIS.Template.CustomFilter'])")
# list of variables names to keep in target environment
$VariablesToPreserveInEnvironment = @()
$ssisPackageId = $OctopusParameters['SSIS.Template.ssisPackageId']
# Get the extracted path
$DeployedPath = $OctopusParameters["Octopus.Action.Package[$ssisPackageId].ExtractedPath"]
# Get all .ispac files from the deployed path
$IsPacFiles = Get-ChildItem -Recurse -Path $DeployedPath | Where {$_.Extension.ToLower() -eq ".ispac"}
# display number of files
Write-Host "$($IsPacFiles.Count) .ispac file(s) found."
Write-Host "Connecting to server ..."
# Create a connection to the server
$sqlConnectionString = "Data Source=$($OctopusParameters['SSIS.Template.ServerName']);Initial Catalog=SSISDB;"
if (![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountUsername']) -and ![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountPassword']))
{
# Add username and password to connection string
$sqlConnectionString += "User ID=$($OctopusParameters['SSIS.Template.sqlAccountUsername']); Password=$($OctopusParameters['SSIS.Template.sqlAccountPassword']);"
}
else
{
# Use integrated
$sqlConnectionString += "Integrated Security=SSPI;"
}
# Create new connection object with connection string
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString
# create integration services object
$integrationServices = New-Object "$ISNamespace.IntegrationServices" $sqlConnection
# get reference to the catalog
Write-Host "Getting reference to catalog $($OctopusParameters['SSIS.Template.CataLogName'])"
$Catalog = Get-Catalog -CatalogName $OctopusParameters['SSIS.Template.CataLogName']
# get folder reference
$Folder = Get-Folder -FolderName $OctopusParameters['SSIS.Template.FolderName'] -Catalog $Catalog
# loop through ispac files
foreach($IsPacFile in $IsPacFiles)
{
# read project file
$ProjectFile = [System.IO.File]::ReadAllBytes($IsPacFile.FullName)
$ProjectName = $IsPacFile.Name.SubString(0, $IsPacFile.Name.LastIndexOf("."))
# deploy project
Write-Host "Deploying project $($IsPacFile.Name)..."
$Folder.DeployProject($ProjectName, $ProjectFile) | Out-Null
# get reference to deployed project
$Project = $Folder.Projects[$ProjectName]
# check to see if they want to use environments
if($UseEnvironment)
{
# get environment reference
$Environment = Get-Environment -Folder $Folder -EnvironmentName $OctopusParameters['SSIS.Template.EnvironmentName']
# set environment reference
Set-EnvironmentReference -Project $Project -Environment $Environment -Folder $Folder
# check to see if the user wants to convert project parameters to environment variables
if($ReferenceProjectParametersToEnvironmentVairables)
{
# set environment variables
Write-Host "Referencing Project Parameters to Environment Variables..."
$VariablesToPreserveInEnvironment += Set-ProjectParametersToEnvironmentVariablesReference -Project $Project -Environment $Environment
}
# check to see if the user wants to convert the package parameters to environment variables
if($ReferencePackageParametersToEnvironmentVairables)
{
# set package variables
Write-Host "Referencing Package Parameters to Environment Variables..."
$VariablesToPreserveInEnvironment += Set-PackageVariablesToEnvironmentVariablesReference -Project $Project -Environment $Environment
}
# Removes all unused variables from the environment
if ($SyncEnvironment)
{
Write-Host "Sync package environment variables..."
Sync-EnvironmentVariables -Environment $Environment -VariablesToPreserveInEnvironment $VariablesToPreserveInEnvironment
}
}
}
}
finally
{
# check to make sure sqlconnection isn't null
if($sqlConnection)
{
# check state of sqlconnection
if($sqlConnection.State -eq [System.Data.ConnectionState]::Open)
{
# close the connection
$sqlConnection.Close()
}
# cleanup
$sqlConnection.Dispose()
}
# cleanup temporary pinned SqlServer module only when it was actually used
if ($runtime -and $runtime.UsedPinnedSqlServerModule)
{
Remove-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModules -PinnedVersion $pinnedSqlServerVersion
}
}
}
Invoke-SsisProjectDeployment
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "27567d46-b935-4ee6-8b2d-8c165edada4e",
"Name": "Deploy ispac SSIS project from a Package parameter",
"Description": "This step template will deploy SSIS ispac projects to SQL Server Integration Services Catalog. The template uses a referenced package and is Worker compatible.\n\nThis template will install the Nuget package provider if it is not present on the machine it is running on.\n\nNOTE: The SqlServer PowerShell module this template utilizes removed the assemblies necessary to interface with SSIS as of version 22.0.59. Version 21.1.18256 has been pinned and will be used if the SqlServer PowerShell module is not installed.",
"Version": 7,
"ExportedAt": "2026-03-13T09:17:00.0000000",
"ActionType": "Octopus.Script",
"Author": "bcullman",
"Packages": [
{
"Id": "5ce9da08-a4ed-4b69-92d1-ab88c705cf08",
"Name": "SSIS.Template.ssisPackageId",
"PackageId": null,
"FeedId": null,
"AcquisitionLocation": "Server",
"Properties": {
"Extract": "True",
"SelectionMode": "deferred",
"PackageParameterName": "SSIS.Template.ssisPackageId"
}
}
],
"Parameters": [
{
"Id": "53aa9e3e-1292-4e75-8095-3666ebd5886b",
"Name": "SSIS.Template.ServerName",
"Label": "Database server name (\\instance)",
"HelpText": "Name of the SQL Server you are deploying to.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "c0605196-f184-44f6-9b3d-c043323e017c",
"Name": "SSIS.Template.sqlAccountUsername",
"Label": "SQL Authentication Username",
"HelpText": "(Optional) Username of the SQL Authentication account. Use this approach when deploying to Azure Databases with SSIS configured. If SQL Authentication Username and Password are blank, Integrated Authentication is used.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "224b913f-657c-4d1c-a3d8-0f286203c1ec",
"Name": "SSIS.Template.sqlAccountPassword",
"Label": "SQL Authentication Password",
"HelpText": "(Optional) Password of the SQL Authentication account.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "0abbb06c-5f98-44d8-b20d-b811b6bf18da",
"Name": "SSIS.Template.EnableCLR",
"Label": "Enable SQL CLR",
"HelpText": "This will reconfigure SQL Server to enable the SQL CLR. It is highly recommended that this be previously authorized by your Database Administrator.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "ebe9ab8b-3433-4aeb-bafb-642033a9b0a0",
"Name": "SSIS.Template.CatalogName",
"Label": "Catalog name",
"HelpText": "Name of the catalog to create in Integration Services Catalogs on SQL Server. When using the GUI, this value gets hardcoded to SSISDB and cannot be changed. It is recommended that you do not change the default value.",
"DefaultValue": "SSISDB",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "d111401b-504f-41f4-96de-b7667fcbf990",
"Name": "SSIS.Template.CatalogPwd",
"Label": "Catalog password",
"HelpText": "Password to the Integration Services Catalog.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "d2fefbf6-c68f-4a66-a5d1-3beb9e51a331",
"Name": "SSIS.Template.FolderName",
"Label": "Folder name",
"HelpText": "Name of the folder to use within the Integration Services Catalog",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "ec3589c1-360b-44fc-a19c-f2de0f57a323",
"Name": "SSIS.Template.UseEnvironment",
"Label": "Use environment",
"HelpText": "This will make a project reference to the defined environment.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "718f2836-1c49-4119-a294-9b5488ead33b",
"Name": "SSIS.Template.EnvironmentName",
"Label": "Environment name",
"HelpText": "Name of the environment to reference the project to. If the environment doesn't exist, it will create it.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "303dd486-a389-48c2-a653-fe881c3b7d9a",
"Name": "SSIS.Template.ReferenceProjectParametersToEnvironmentVairables",
"Label": "Reference project parameters to environment variables",
"HelpText": "Checking this box will make Project Parameters reference Environment Variables. If the Environment Variable doesn't exist, it will create it. This expects that an Octopus variable of the same name exists.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "06079e96-3c10-4137-9c99-83da2051f8be",
"Name": "SSIS.Template.ReferencePackageParametersToEnvironmentVairables",
"Label": "Reference package parameters to environment variables",
"HelpText": "Checking this box will make Package Parameters reference Environment Variables. If the Environment Variable doesn't exist, it will create it. This expects than an Octopus variable of the same name exists.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "8c219bf1-0715-4c21-a131-f7bfb44690cd",
"Name": "SSIS.Template.UseFullyQualifiedVariableNames",
"Label": "Use Fully Qualified Variable Names",
"HelpText": "When true the package variables names must be represented in `dtsx_name_without_extension.variable_name`",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "6b29c969-3928-4faf-af17-0911d777d5b1",
"Name": "SSIS.Template.UseCustomFilter",
"Label": "Use Custom Filter for connection manager properties",
"HelpText": "Custom filter should contain the regular expression for ignoring properties when setting will occur during the auto-mapping",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "b33575e2-7246-4c04-b4fa-cd58e2b5e516",
"Name": "SSIS.Template.CustomFilter",
"Label": "Custom Filter for connection manager properties",
"HelpText": "Regular expression for filtering out the connection manager properties during the auto-mapping process. This string is used when `UseCustomFilter` is set to true",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "92b546d9-abf3-45e4-a61b-0315c21455df",
"Name": "SSIS.Template.SyncEnvironment",
"Label": "Clean obsolete variables from environment",
"HelpText": "When `true` synchronizes the environment:\n- Removes obsolete variables\n- Removes renamed variables\n- Replaces values of valid variables (also when `false`)",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "6a1fa441-9e14-4c13-b7f3-9c932d9b4e8e",
"Name": "SSIS.Template.ssisPackageId",
"Label": "Package Id",
"HelpText": "Id of the package to deploy, used to support deployment with Workers.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Package"
}
}
],
"Properties": {
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "function Add-TemporaryPinnedSqlServerModule\n{\n # Define parameters\n param(\n $LocalModulesPath\n )\n\n $PowerShellModuleName = \"SqlServer\"\n $RequiredVersion = [version]'21.1.18256'\n\n # Check to see if the package provider has been installed\n if ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))\n {\n # Display that we need the nuget package provider\n Write-Host \"Nuget package provider not found, installing ...\"\n\n # Install Nuget package provider\n Install-PackageProvider -Name Nuget -Force\n }\n\n # Save the module in the temporary location\n Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force -RequiredVersion $RequiredVersion -Repository \"PSGallery\"\n\n # Display\n Write-Output \"Saved module $PowerShellModuleName v$RequiredVersion to $LocalModulesPath\"\n\n # Import the module\n Import-Module -Name $PowerShellModuleName\n}\n\nFunction Remove-TemporaryPinnedSqlServerModule\n{\n param(\n [Parameter(Mandatory = $true)][string]$LocalModulesPath,\n [Parameter(Mandatory = $true)][version]$PinnedVersion\n )\n\n try { Remove-Module SqlServer -Force -ErrorAction SilentlyContinue } catch {}\n\n $moduleRoot = Join-Path $LocalModulesPath 'SqlServer'\n $pinnedPath = Join-Path $moduleRoot $PinnedVersion.ToString()\n\n if (Test-Path $pinnedPath)\n {\n Write-Host \"Removing temporary pinned SqlServer module folder: $pinnedPath\"\n Remove-Item -Path $pinnedPath -Recurse -Force -ErrorAction SilentlyContinue\n }\n\n # Optional: remove parent if empty\n if (Test-Path $moduleRoot)\n {\n $remaining = Get-ChildItem -Path $moduleRoot -Force -ErrorAction SilentlyContinue\n if (-not $remaining)\n {\n Remove-Item -Path $moduleRoot -Force -ErrorAction SilentlyContinue\n }\n }\n}\n\nFunction Test-IntegrationServicesTypeAvailable\n{\n # True if the IntegrationServices type resolves in this PowerShell session, else false\n $typeName = 'Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices'\n $aqn = \"$typeName, Microsoft.SqlServer.Management.IntegrationServices\"\n\n try\n {\n if ([Type]::GetType($aqn, $false)) { return $true }\n }\n catch {}\n\n # Try to load assembly (strong name), may fail on some boxes\n try { [void][Reflection.Assembly]::Load('Microsoft.SqlServer.Management.IntegrationServices') } catch {}\n\n try\n {\n if ([Type]::GetType($aqn, $false)) { return $true }\n }\n catch {}\n\n # Fall back to explicit GAC path load (LoadFrom) if present\n $gacRoot = Join-Path $env:windir 'Microsoft.NET\\assembly\\GAC_MSIL\\Microsoft.SqlServer.Management.IntegrationServices'\n if (Test-Path $gacRoot)\n {\n $gacDll = Get-ChildItem -Path $gacRoot -Recurse -Filter 'Microsoft.SqlServer.Management.IntegrationServices.dll' -File -ErrorAction SilentlyContinue |\n Sort-Object FullName -Descending |\n Select-Object -First 1\n\n if ($null -eq $gacDll)\n {\n try\n {\n $asm = [Reflection.Assembly]::LoadFrom($gacDll.FullName)\n if ($asm.GetType('Microsoft.SqlServer.Management.IntegrationServices.IntegrationServices', $false)) { return $true }\n }\n catch {}\n }\n }\n\n try\n {\n if ([Type]::GetType($aqn, $false)) { return $true }\n }\n catch {}\n\n return $false\n}\n\nFunction Load-SqlServerAssemblies\n{\n # Get the folder where the SqlServer module ended up in\n $sqlServerModulePath = [System.IO.Path]::GetDirectoryName((Get-Module SqlServer).Path)\n\n # Loop through the assemblies\n foreach($assemblyFile in (Get-ChildItem -Path $sqlServerModulePath -Exclude msv*.dll | Where-Object {$_.Extension -eq \".dll\"}))\n {\n try\n {\n # Only load managed .NET assemblies (native DLLs will throw)\n [void][System.Reflection.AssemblyName]::GetAssemblyName($assemblyFile.FullName)\n\n # Load the managed assembly\n [Reflection.Assembly]::LoadFrom($assemblyFile.FullName) | Out-Null\n }\n catch [System.BadImageFormatException]\n {\n # Native DLL (or wrong format), skip\n }\n }\n}\n\nFunction Initialize-SsisDeploymentRuntime\n{\n param(\n [Parameter(Mandatory = $true)][string]$LocalModulesPath,\n [Parameter(Mandatory = $true)][version]$PinnedSqlServerVersion\n )\n\n # Define PowerShell Modules path\n $env:PSModulePath = \"$LocalModulesPath;$env:PSModulePath\"\n\n $runtime = [pscustomobject]@{\n UsedPinnedSqlServerModule = $false\n SsisTypeAvailable = $false\n }\n\n # First preference: use SSIS assemblies already available on the machine/session\n $runtime.SsisTypeAvailable = Test-IntegrationServicesTypeAvailable\n\n if ($runtime.SsisTypeAvailable)\n {\n Write-Host \"SSIS IntegrationServices type is already available.\"\n\n # Only need a SqlServer module for cmdlets such as Invoke-Sqlcmd\n if ($null -ne (Get-Module -ListAvailable -Name \"SqlServer\"))\n {\n Import-Module -Name SqlServer -ErrorAction Stop\n }\n else\n {\n Write-Output \"PowerShell module SqlServer not present, downloading temporary pinned copy for cmdlets ...\"\n [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12\n\n Add-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModulesPath\n\n $manifestPath = Join-Path (Join-Path (Join-Path $LocalModulesPath 'SqlServer') $PinnedSqlServerVersion.ToString()) 'SqlServer.psd1'\n Write-Host \"Importing pinned SqlServer module from: $manifestPath\"\n Import-Module -Name $manifestPath -Force -DisableNameChecking -ErrorAction Stop\n\n $runtime.UsedPinnedSqlServerModule = $true\n }\n\n # SSIS type already resolved, no need to bulk-load module assemblies\n return $runtime\n }\n\n # Second preference: fall back to pinned SqlServer module that still contains SSIS assemblies\n Write-Output \"SSIS IntegrationServices type not available via installed components. Downloading pinned SqlServer module $PinnedSqlServerVersion temporarily ...\"\n [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12\n\n $manifestPath = Join-Path (Join-Path (Join-Path $LocalModulesPath 'SqlServer') $PinnedSqlServerVersion.ToString()) 'SqlServer.psd1'\n if (-not (Test-Path $manifestPath))\n {\n Add-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModulesPath\n }\n\n Write-Host \"Importing pinned SqlServer module from: $manifestPath\"\n Import-Module -Name $manifestPath -Force -DisableNameChecking -ErrorAction Stop\n Load-SqlServerAssemblies\n\n $runtime.UsedPinnedSqlServerModule = $true\n $runtime.SsisTypeAvailable = Test-IntegrationServicesTypeAvailable\n\n return $runtime\n}\n\nFunction Get-Catalog\n{\n # define parameters\n Param ($CatalogName)\n # NOTE: using $integrationServices variable defined in main\n\n # define working variables\n $Catalog = $null\n # check to see if there are any catalogs\n if($integrationServices.Catalogs.Count -gt 0 -and $integrationServices.Catalogs[$CatalogName])\n {\n # get reference to catalog\n $Catalog = $integrationServices.Catalogs[$CatalogName]\n }\n else\n {\n if((Get-CLREnabled) -eq 0)\n {\n if(-not $EnableCLR)\n {\n # throw error\n throw \"SQL CLR is not enabled.\"\n }\n else\n {\n # display sql clr isn't enabled\n Write-Warning \"SQL CLR is not enabled on $($sqlConnection.DataSource). This feature must be enabled for SSIS catalogs.\"\n\n # enabling SQLCLR\n Write-Host \"Enabling SQL CLR ...\"\n Enable-SQLCLR\n Write-Host \"SQL CLR enabled\"\n }\n }\n\n # Provision a new SSIS Catalog\n Write-Host \"Creating SSIS Catalog ...\"\n\n $Catalog = New-Object \"$ISNamespace.Catalog\" ($integrationServices, $CatalogName, $OctopusParameters['SSIS.Template.CatalogPwd'])\n $Catalog.Create()\n }\n\n # return the catalog\n return $Catalog\n}\n\nFunction Get-CLREnabled\n{\n # define parameters\n # Not using any parameters, but am using $sqlConnection defined in main\n\n # define working variables\n $Query = \"SELECT * FROM sys.configurations WHERE name = 'clr enabled'\"\n\n # execute script\n $CLREnabled = Invoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database \"master\" -Query $Query | Select value\n\n # return value\n return $CLREnabled.Value\n}\n\nFunction Enable-SQLCLR\n{\n $QueryArray = \"sp_configure 'show advanced options', 1\", \"RECONFIGURE\", \"sp_configure 'clr enabled', 1\", \"RECONFIGURE \"\n # execute script\n\n foreach($Query in $QueryArray)\n {\n Invoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database \"master\" -Query $Query\n }\n\n # check that it's enabled\n if((Get-CLREnabled) -ne 1)\n {\n # throw error\n throw \"Failed to enable SQL CLR\"\n }\n}\n\nFunction Get-Folder\n{\n # parameters\n Param($FolderName, $Catalog)\n\n $Folder = $null\n # try to get reference to folder\n\n if(!($Catalog.Folders -eq $null))\n {\n $Folder = $Catalog.Folders[$FolderName]\n }\n\n # check to see if $Folder has a value\n if($Folder -eq $null)\n {\n # display\n Write-Host \"Folder $FolderName doesn't exist, creating folder...\"\n\n # create the folder\n $Folder = New-Object \"$ISNamespace.CatalogFolder\" ($Catalog, $FolderName, $FolderName)\n $Folder.Create()\n }\n\n # return the folder reference\n return $Folder\n}\n\nFunction Get-Environment\n{\n # define parameters\n Param($Folder, $EnvironmentName)\n\n $Environment = $null\n # get reference to Environment\n if(!($Folder.Environments -eq $null) -and $Folder.Environments.Count -gt 0)\n {\n $Environment = $Folder.Environments[$EnvironmentName]\n }\n\n # check to see if it's a null reference\n if($Environment -eq $null)\n {\n # display\n Write-Host \"Environment $EnvironmentName doesn't exist, creating environment...\"\n\n # create environment\n $Environment = New-Object \"$ISNamespace.EnvironmentInfo\" ($Folder, $EnvironmentName, $EnvironmentName)\n $Environment.Create()\n }\n\n # return the environment\n return $Environment\n}\n\nFunction Set-EnvironmentReference\n{\n # define parameters\n Param($Project, $Environment, $Folder)\n\n # get reference\n $Reference = $null\n\n if(!($Project.References -eq $null))\n {\n $Reference = $Project.References[$Environment.Name, $Folder.Name]\n }\n\n # check to see if it's a null reference\n if($Reference -eq $null)\n {\n # display\n Write-Host \"Project does not reference environment $($Environment.Name), creating reference...\"\n\n # create reference\n $Project.References.Add($Environment.Name, $Folder.Name)\n $Project.Alter()\n }\n}\n\nFunction Set-ProjectParametersToEnvironmentVariablesReference\n{\n # define parameters\n Param($Project, $Environment)\n\n $UpsertedVariables = @()\n\n if($Project.Parameters -eq $null)\n {\n Write-Host \"No project parameters exist\"\n return\n }\n\n # loop through project parameters\n foreach($Parameter in $Project.Parameters)\n {\n # skip if the parameter is included in custom filters\n if ($UseCustomFilter)\n {\n if ($Parameter.Name -match $CustomFilter)\n {\n Write-Host \"- $($Parameter.Name) skipped due to CustomFilters.\"\n continue\n }\n }\n\n # Add variable to list of variable\n $UpsertedVariables += $Parameter.Name\n\n $Variable = $null\n if(!($Environment.Variables -eq $null))\n {\n # get reference to variable\n $Variable = $Environment.Variables[$Parameter.Name]\n }\n\n # check to see if variable exists\n if($Variable -eq $null)\n {\n # add the environment variable\n Add-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $Parameter.Name\n\n # get reference to the newly created variable\n $Variable = $Environment.Variables[$Parameter.Name]\n }\n\n # set the environment variable value\n Set-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $Parameter.Name\n }\n\n # alter the environment\n $Environment.Alter()\n $Project.Alter()\n\n return $UpsertedVariables\n}\n\nFunction Set-PackageVariablesToEnvironmentVariablesReference\n{\n # define parameters\n Param($Project, $Environment)\n\n $Variables = @()\n $UpsertedVariables = @()\n\n # loop through packages in project in order to store a temp collection of variables\n foreach($Package in $Project.Packages)\n {\n # loop through parameters of package\n foreach($Parameter in $Package.Parameters)\n {\n # add to the temporary variable collection\n $Variables += $Parameter.Name\n }\n }\n\n # loop through packages in project\n foreach($Package in $Project.Packages)\n {\n # loop through parameters of package\n foreach($Parameter in $Package.Parameters)\n {\n if ($UseFullyQualifiedVariableNames)\n {\n # Set fully qualified variable name\n $ParameterName = $Parameter.ObjectName.Replace(\".dtsx\", \"\")+\".\"+$Parameter.Name\n }\n else\n {\n # check if exists a variable with the same name\n $VariableNameOccurrences = $($Variables | Where-Object { $_ -eq $Parameter.Name }).count\n $ParameterName = $Parameter.Name\n\n if ($VariableNameOccurrences -gt 1)\n {\n $ParameterName = $Parameter.ObjectName.Replace(\".dtsx\", \"\")+\".\"+$Parameter.Name\n }\n }\n\n if ($UseCustomFilter)\n {\n if ($ParameterName -match $CustomFilter)\n {\n Write-Host \"- $($Parameter.Name) skipped due to CustomFilters.\"\n continue\n }\n }\n\n # get reference to variable\n $Variable = $Environment.Variables[$ParameterName]\n\n # Add variable to list of variable\n $UpsertedVariables += $ParameterName\n\n # check to see if the parameter exists\n if(!$Variable)\n {\n # add the environment variable\n Add-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $ParameterName\n\n # get reference to the newly created variable\n $Variable = $Environment.Variables[$ParameterName]\n }\n\n # set the environment variable value\n Set-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $ParameterName\n }\n\n # alter the package\n $Package.Alter()\n }\n\n # alter the environment\n $Environment.Alter()\n\n return $UpsertedVariables\n}\n\nFunction Sync-EnvironmentVariables\n{\n # define parameters\n Param($Environment, $VariablesToPreserveInEnvironment)\n\n foreach($VariableToEvaluate in $Environment.Variables)\n {\n if ($VariablesToPreserveInEnvironment -notcontains $VariableToEvaluate.Name)\n {\n Write-Host \"- Removing environment variable: $($VariableToEvaluate.Name)\"\n $VariableToRemove = $Environment.Variables[$VariableToEvaluate.Name]\n $Environment.Variables.Remove($VariableToRemove) | Out-Null\n }\n }\n\n # alter the environment\n $Environment.Alter()\n}\n\nFunction Add-EnvironmentVariable\n{\n # define parameters\n Param($Environment, $Parameter, $ParameterName)\n\n # display\n Write-Host \"- Adding environment variable $($ParameterName)\"\n\n # check to see if design default value is empty or null\n if([string]::IsNullOrEmpty($Parameter.DesignDefaultValue))\n {\n # give it something\n $DefaultValue = \"\" # sensitive variables will not return anything so when trying to use the property of $Parameter.DesignDefaultValue, the Alter method will fail.\n }\n else\n {\n # take the design\n $DefaultValue = $Parameter.DesignDefaultValue\n }\n\n # add variable with an initial value\n $Environment.Variables.Add($ParameterName, $Parameter.DataType, $DefaultValue, $Parameter.Sensitive, $Parameter.Description)\n}\n\nFunction Set-EnvironmentVariableValue\n{\n # define parameters\n Param($Variable, $Parameter, $ParameterName)\n\n # check to make sure variable value is available\n if (-not $OctopusParameters){\n Write-Host \"[WARN] - OctopusParameters collection is empty\"\n }\n else\n {\n if($OctopusParameters.ContainsKey($ParameterName))\n {\n # display\n Write-Host \"[ OK ] - $($ParameterName) updated.\"\n\n # set the variable value\n $Variable.Value = $OctopusParameters[\"$($ParameterName)\"]\n }\n else\n {\n # warning\n Write-Host \"[WARN] - $($ParameterName) not in OctopusParameters collection.\"\n }\n }\n\n # Set reference\n $Parameter.Set([Microsoft.SqlServer.Management.IntegrationServices.ParameterInfo+ParameterValueType]::Referenced, \"$($ParameterName)\")\n}\n\nFunction Invoke-SsisProjectDeployment\n{\n $LocalModules = (New-Item \"$PSScriptRoot\\Modules\" -ItemType Directory -Force).FullName\n $pinnedSqlServerVersion = [version]'21.1.18256'\n $sqlConnection = $null\n $runtime = $null\n\n try\n {\n $runtime = Initialize-SsisDeploymentRuntime -LocalModulesPath $LocalModules -PinnedSqlServerVersion $pinnedSqlServerVersion\n\n # Store the IntegrationServices Assembly namespace to avoid typing it every time\n $ISNamespace = \"Microsoft.SqlServer.Management.IntegrationServices\"\n\n # ensure all boolean variables are true booleans\n $EnableCLR = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.EnableCLR'])\")\n $UseEnvironment = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseEnvironment'])\")\n $ReferenceProjectParametersToEnvironmentVairables = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.ReferenceProjectParametersToEnvironmentVairables'])\")\n\n $ReferencePackageParametersToEnvironmentVairables = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.ReferencePackageParametersToEnvironmentVairables'])\")\n $UseFullyQualifiedVariableNames = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseFullyQualifiedVariableNames'])\")\n $SyncEnvironment = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.SyncEnvironment'])\")\n # custom names for filtering out the excluded variables by design\n $UseCustomFilter = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseCustomFilter'])\")\n $CustomFilter = [System.Convert]::ToString(\"$($OctopusParameters['SSIS.Template.CustomFilter'])\")\n # list of variables names to keep in target environment\n $VariablesToPreserveInEnvironment = @()\n $ssisPackageId = $OctopusParameters['SSIS.Template.ssisPackageId']\n\n # Get the extracted path\n $DeployedPath = $OctopusParameters[\"Octopus.Action.Package[$ssisPackageId].ExtractedPath\"]\n\n # Get all .ispac files from the deployed path\n $IsPacFiles = Get-ChildItem -Recurse -Path $DeployedPath | Where {$_.Extension.ToLower() -eq \".ispac\"}\n\n # display number of files\n Write-Host \"$($IsPacFiles.Count) .ispac file(s) found.\"\n\n Write-Host \"Connecting to server ...\"\n\n # Create a connection to the server\n $sqlConnectionString = \"Data Source=$($OctopusParameters['SSIS.Template.ServerName']);Initial Catalog=SSISDB;\"\n\n if (![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountUsername']) -and ![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountPassword']))\n {\n # Add username and password to connection string\n $sqlConnectionString += \"User ID=$($OctopusParameters['SSIS.Template.sqlAccountUsername']); Password=$($OctopusParameters['SSIS.Template.sqlAccountPassword']);\"\n }\n else\n {\n # Use integrated\n $sqlConnectionString += \"Integrated Security=SSPI;\"\n }\n\n # Create new connection object with connection string\n $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString\n\n # create integration services object\n $integrationServices = New-Object \"$ISNamespace.IntegrationServices\" $sqlConnection\n\n # get reference to the catalog\n Write-Host \"Getting reference to catalog $($OctopusParameters['SSIS.Template.CataLogName'])\"\n $Catalog = Get-Catalog -CatalogName $OctopusParameters['SSIS.Template.CataLogName']\n\n # get folder reference\n $Folder = Get-Folder -FolderName $OctopusParameters['SSIS.Template.FolderName'] -Catalog $Catalog\n\n # loop through ispac files\n foreach($IsPacFile in $IsPacFiles)\n {\n # read project file\n $ProjectFile = [System.IO.File]::ReadAllBytes($IsPacFile.FullName)\n $ProjectName = $IsPacFile.Name.SubString(0, $IsPacFile.Name.LastIndexOf(\".\"))\n\n # deploy project\n Write-Host \"Deploying project $($IsPacFile.Name)...\"\n $Folder.DeployProject($ProjectName, $ProjectFile) | Out-Null\n\n # get reference to deployed project\n $Project = $Folder.Projects[$ProjectName]\n\n # check to see if they want to use environments\n if($UseEnvironment)\n {\n # get environment reference\n $Environment = Get-Environment -Folder $Folder -EnvironmentName $OctopusParameters['SSIS.Template.EnvironmentName']\n\n # set environment reference\n Set-EnvironmentReference -Project $Project -Environment $Environment -Folder $Folder\n\n # check to see if the user wants to convert project parameters to environment variables\n if($ReferenceProjectParametersToEnvironmentVairables)\n {\n # set environment variables\n Write-Host \"Referencing Project Parameters to Environment Variables...\"\n $VariablesToPreserveInEnvironment += Set-ProjectParametersToEnvironmentVariablesReference -Project $Project -Environment $Environment\n }\n\n # check to see if the user wants to convert the package parameters to environment variables\n if($ReferencePackageParametersToEnvironmentVairables)\n {\n # set package variables\n Write-Host \"Referencing Package Parameters to Environment Variables...\"\n $VariablesToPreserveInEnvironment += Set-PackageVariablesToEnvironmentVariablesReference -Project $Project -Environment $Environment\n }\n\n # Removes all unused variables from the environment\n if ($SyncEnvironment)\n {\n Write-Host \"Sync package environment variables...\"\n Sync-EnvironmentVariables -Environment $Environment -VariablesToPreserveInEnvironment $VariablesToPreserveInEnvironment\n }\n }\n }\n }\n\n finally\n {\n # check to make sure sqlconnection isn't null\n if($sqlConnection)\n {\n # check state of sqlconnection\n if($sqlConnection.State -eq [System.Data.ConnectionState]::Open)\n {\n # close the connection\n $sqlConnection.Close()\n }\n\n # cleanup\n $sqlConnection.Dispose()\n }\n\n # cleanup temporary pinned SqlServer module only when it was actually used\n if ($runtime -and $runtime.UsedPinnedSqlServerModule)\n {\n Remove-TemporaryPinnedSqlServerModule -LocalModulesPath $LocalModules -PinnedVersion $pinnedSqlServerVersion\n }\n }\n}\n\nInvoke-SsisProjectDeployment",
"Octopus.Action.Script.ScriptSource": "Inline"
},
"Category": "SQL Server",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/ssis-deploy-ispac-from-package-parameter.json",
"Website": "/step-templates/27567d46-b935-4ee6-8b2d-8c165edada4e",
"Logo": "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",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Friday, March 13, 2026