TFS Release Deploy

Team Service Erweiterung – Deploy

Mit dem Deploy Tool können Sie auf den Zielsystemen, auf dem die Build Agent installiert sind, MSI Anwendungen Deinstallieren und installieren. Zusätzlich enthält das Skript noch die Ausführung von SQL Skripte für die Aktualisierung der Datenbank. Hier besteht auch die Notwendigkeit, dass der Agent auf dem DB Server installiert ist.

Über den folgenden Link bekommen Sie das komplette Paket als ZIP bereitgestellt. Das Skript ist kostenfrei und kann nach Ihren wünschen angepasst werden. Download Deploy Team Service extensions

d7952ec20e351b038e60d0b5f03b0cfa

Damit eine Ausführung von Invoce-SQLCMD über den lokalen Agent erfolgen kann, ist die Sammlung VstsTaskSdk notwendig. Diese wurde bereits in meinen Paket hinzugefügt. Weitere Infos finden Sie hierzu unter vsts-task-lib.

  • Als Vorraussetzung ist wie beschrieben, dass der Build Agent auf dem Zielsystem installiert ist. Eine Anleitung für die Konfiguration finden Sie hier: Deploy an agent on Windows
  • Entpacken Sie das Zip und Importieren den PowerShell Task. Eine Beschreibung für den Import finden Sie hier:  Eigene TFS Build / Release Aufgaben bereitstellen
  • Erstellen Sie eine neue Release definition. Infos finden Sie hier: Define your CD release process
  • Fügen Sie jetzt Ihre Aufgaben wie SPS Deploy hinzu.
  • Geben Sie nun alle notwendigen Werte ein und führen die Bereitstellung aus.

Folgende Parameter können Sie mitgeben:

  • Application URL / Name: Applikationsname für Protokollierung und SQL DB Name
  • Action: Abhängig von der Tätigkeit haben Sie die Auswahl MSI Uninstall, MSI Install, SQL Run.
  • Folder or productcode: MSI und SQL Ablageverzeichnis oder MSI Produktcode des Zielsystems
  • MSI Name: Name des MSI Setups (setup.msi)
  • MSI Arguments: MSI Parameter, Achten Sie darauf, dass Sie keine Hochkommas verwenden.
    Beispiel:
    ALLUSERS=$(ALLUSERS)
    INSTALLLOCATION=$(WebIISRoot)\$(RELEASE.ENVIRONMENTNAME)
    INSTALLDESKTOPSHORTCUT=0
    DATABASESERVER=$(SQLServer)
    DATABASSERVERPORT=$(RELEASE.ENVIRONMENTNAME)
    DATABASENAME=$(RELEASE.ENVIRONMENTNAME)
    DATABASEUSER=$(RELEASE.ENVIRONMENTNAME)
    DATABASEPASSWORD=$(AppSQLUserPassword)
    DATABSEENCRYPTION=$(SQLDBEncryption)
    LOGDIR=$(WebLogDir)

Wichtig SQL Voraussetzungen: 

Aktuell ist das Skript so konfiguriert, dass die Aktualisierungen der SQL Skripte folgende Vorraussetzungen benötigt:

  • SQL Server horcht lokal auf localhost, Port 1433
  • Wenn mehrere Skripte existieren, so müssen diese von der Benennung der Windows logik folgen. Das können Sie erreichen, wenn Sie z.B. A, B, C… die Dateien benennen. Die Prüfung können Sie im Datei-Explorer vornehmen.
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy MSI Install
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy MSI Uninstall
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy SQL
$AppName = Get-VstsInput -Name "AppName" -Default ""; 
$Action = Get-VstsInput -Name "Action" -Default "";
$DBName = Get-VstsInput -Name "DBName" -Default "";
$MSIName = Get-VstsInput -Name "MSIName" -Default "";
$FolderProductcode = Get-VstsInput -Name "FolderProductcode" -Default "";
$MSIArguments = Get-VstsInput -Name "MSIArguments" -Default " ";
$Timeout = Get-VstsInput -Name "Timeout" -Default 300;

Write-Output "Action selected - $Action"		
Write-Output "Application name - $AppName"	
Write-Output "Database name - $DBName"
Write-Output "MSI name - $MSIName"
Write-Output "Folder or Productcode - $FolderProductcode"
Write-Output "MSI arguments - $MSIArguments"
Write-Output "Timeout in sec - $Timeout"

Write-Output "Start Deploy"
    
$DataStamp = get-date -Format yyyyMMddTHHmmss
$LogPath = $Env:SYSTEM_DEFAULTWORKINGDIRECTORY


$MSIArguments = $MSIArguments -replace "`t|`n|`r"," "

$timeouted = $null 
	
if ($Action -eq "uninstall")
{
	Write-Output "Uninstall App - ($AppName)......."   

	$uninstall = 0

	# Check productcode and MSI exists
	if ($FolderProductcode -like "{*}"){	
		
		Write-Output "Search guid: " + $FolderProductcode 
		$properties = "identifyingnumber","name","vendor","version"
		Get-ChildItem HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\*\Products | ForEach-Object {
			$root  = $_.PsPath
			$_.GetSubKeyNames() | ForEach-Object {
				try {
					$RegKeyPath = (Join-Path -Path (Join-Path -Path $root -ChildPath $_) -ChildPath InstallProperties)
					$obj = Get-ItemProperty -Path $RegKeyPath -ErrorAction Stop
					if ($obj.UninstallString) {
						$guid = ($obj.UninstallString -replace "msiexec\.exe\s/[IX]{1}","")
						if($guid -eq $FolderProductcode){
							Write-Output "Uninstall guid: " + $guid 
							Write-Output "Uninstall version: " + $obj.DisplayVersion 
							Write-Output "Uninstall name: " + $obj.DisplayName 
							Write-Output "Uninstall vendor: " + $obj.Publisher 
							
							$obj = ''
							$uninstall = 1
						}
					}
				} catch {
				}
			}
		}
	}
	else{		
		$FolderProductcode = "$FolderProductcode\$MSIName"
		Write-Output "Check MSI path: " + $FolderProductcode 
		if ($FolderProductcode -like "*\*.msi") {  
			if (Test-Path $FolderProductcode) {
				$uninstall = 1
			}
		}
	}

	# Uninstall
	if($uninstall -eq 1){	    
	
		$logFile = $LogPath+'\'+$AppName+'-'+$AppVersion+'-Uninstall-' + $DataStamp+'.log'
		$arguments = '/q /x ' +$FolderProductcode+ ' /passive ' + $MSIArguments + ' /l*v ' + $logFile

		$output = 'Start-Process "msiexec.exe" -ArgumentList "' + $arguments + '" -PassThru'
		Write-Output "Run: " + $output   

		$Request = Start-Process "msiexec.exe" -ArgumentList "$arguments" -PassThru
						
		$Request | Wait-Process -Timeout $Timeout
		If ($($Request.ExitCode) -eq '0')
		{
			Write-Output "$AppName uninstalled successfully!"
		}
		else{
			Write-Error "$AppName failed to uninstall with exit error: $($Request.ExitCode)"
		}
		Write-Output "Request: $Request"
	}
	else{
		Write-Warning "MSI or productcode not found: $FolderProductcode"
	}
}

if ($Action -eq "install")
{
	Write-Output "Install App - ($AppName)......."  
	
	$FolderProductcode = "$FolderProductcode\$MSIName"
	# Check MSI exists
	Write-Output "Check MSI path: " + $FolderProductcode 
	if (Test-Path $FolderProductcode) {
		$logFile = $LogPath + '\'+$AppName+'-'+$AppVersion+'-Install-' + $DataStamp+'.log'
		$arguments = '/q /i ' + $FolderProductcode + ' ALLUSERS=ALLUSERS /passive ' + $MSIArguments + ' /l*v ' + $logFile

		$output = 'Start-Process "msiexec.exe" -ArgumentList "' + $arguments + '" -PassThru'
		Write-Output "Run: " + $output

		$Request = Start-Process "msiexec.exe" -ArgumentList "$arguments" -PassThru
		
		$Request | Wait-Process -Timeout $Timeout
		If($($Request.ExitCode) -eq '0')
		{
			Write-Output "$AppName installed successfully!"
		}
		else{
			Write-Error "$AppName failed to install with exit error: $($Request.ExitCode)"
		}
	}
	else{
		Write-Error "MSI not found: $FolderProductcode"
	}
}
	
if ($Action -eq "sql")
{
	Write-Output "Run SQL Script - ($AppName)......."  
	
	Write-Output "Provide modul sqlps in powershell"
	import-module "sqlps" -DisableNameChecking

	# Check MSI exists
	if (Test-Path $FolderProductcode) {
		# Check SQL File and run           
		Write-Output "SQL file search: $FolderProductcode\*.slq"
		$files = Get-ChildItem "$FolderProductcode\*.sql" -Recurse | Select-Object Name, Fullname | Sort-Object Name
		foreach  ($file in $files){
			try{
				Write-Output "Script run: invoke-sqlcmd -ServerInstance 'localhost' -Database $DBName -InputFile $file.FullName -QueryTimeout $Timeout -ConnectionTimeout $Timeout  -ErrorAction 'Stop'"
				invoke-sqlcmd -ServerInstance 'localhost' -Database $DBName -InputFile $file.FullName -QueryTimeout $Timeout -ConnectionTimeout $Timeout  -ErrorAction 'Stop'
			}
			catch{
				Write-Error "Error in script: $file.FullName"
				Write-Error $error -foregroundcolor red
			}
		}  
	}
	else{
		Write-Error "SQL path not found: $FolderProductcode"
	} 
}


Weitere Infos:

Release Management

Team Service Erweiterung – Application Pool Start / Stop

Team Service Erweiterung – Download Artifacts

Team Service Erweiterung – Remote Deploy