-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
88233cd
commit 6f00726
Showing
6 changed files
with
412 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,338 @@ | ||
<# | ||
.SYNOPSIS | ||
This powershell script deploys a WDP generated by Sitecore TDS to a Sitecore instance using WebDeploy. Sitecore Azure PaaS has Web Deploy installed by default. | ||
.DESCRIPTION | ||
This powershell script deploys a WDP generated by Sitecore TDS to a Sitecore Azure instance. The script is designed to work in a default Sitecore installation. | ||
If your installation is heavilly customized, this script should server as a starting point for your deployment process. | ||
The script will push all Sitecore items and files in the WDP to the Sitecore App Service specified by the publish settings file. After the code is deployed, the Sitecore instance is contacted using | ||
a web service and all post-deployment steps are executed. | ||
The script will monitor post step execution and optinally display status messages. the script will wait until all post steps are complete or there is a failure in the post step process. | ||
.PARAMETER <PackagePath> | ||
Path to the Sitecore TDS generated WDP. Leave this blank if the web deploy package was deployed using something other than this script. If blank, the script will only monitor the installation status on the server referenced in the publish settings. | ||
.PARAMETER <PublishSettingsPath> | ||
Path to the publish settings file created by Azure in the App Service management screen. This contains the url and credentials needed to access the MSDeploy server in the App Service. | ||
.PARAMETER <MSDeployAllowUntrusted> | ||
Adds the parameter "-AllowUntrusted" to the MSDeploy command. This allows MSDeploy to publish to sites using a self signed certificate. | ||
.PARAMETER <Username> | ||
Adds a Username parameter to the MSDeploy -dest argument. Use this if you are not specifying a publishsettings file. | ||
.PARAMETER <Password> | ||
Adds a Password parameter to the MSDeploy -dest argument. Use this if the publishsettings do not contain a password. | ||
.PARAMETER <ComputerName> | ||
Adds a ComputerName parameter to the MSDeploy -dest argument. Use this if you are not specifying a publishsettings file. | ||
.PARAMETER <SiteName> | ||
The name of the IIS site MSDeploy is installing the package on. Use this if you are not specifying a publishsettings file. | ||
.PARAMETER <AuthType> | ||
Adds a AuthType parameter to the MSDeploy -dest argument. Use this if you are not specifying a publishsettings file. The supported types are 'Basic' and 'NTLM' | ||
.PARAMETER <UseHttp> | ||
When this switch is specified, the script uses an Http:// connection (not recommended) instead of the default Https:// | ||
.PARAMETER <ViewLogs> | ||
When this switch is specified, the script Routes all log messages generated by user PostSteps on the server to the output stream. | ||
.PARAMETER <Remove> | ||
When this switch is specified, the script removes the post deploy processor from the server. This will cause the server to recycle. | ||
.PARAMETER <CodeOnly> | ||
When this switch is specified, the script only runs the WebDeploy portion of the deployment and doesn't look for any item deployment status. | ||
.EXAMPLE | ||
.\PublishWebDeploy.ps1 -PackagePath .\MySite.wdp.zip -PublishSettingsPath .\MyServer.PublishSettings -ViewLogs | ||
Installs a package where Direct Database Deploy was not specified as part of the build: | ||
.EXAMPLE | ||
.\PublishWebDeploy.ps1 -PackagePath .\MySite.wdp.zip -PublishSettingsPath .\MyServer.PublishSettings -ViewLogs -Remove | ||
Installs a package and removes the Web Deploy post processor: | ||
.EXAMPLE | ||
.\PublishWebDeploy.ps1 -PackagePath ".\MySite.wdp.zip" -MSDeployAllowUntrusted -Password ?????? -ComputerName sc.local -SiteName sc.local -Username SCDeploy -AuthType Basic | ||
Installs a package using parameters to specify the computer name instead of a .PublishSettings file. | ||
#> | ||
|
||
[cmdletbinding()] | ||
param( | ||
[string]$PackagePath, | ||
[string]$PublishSettingsPath, | ||
[string]$ComputerName, | ||
[string]$SiteName, | ||
[string]$Username, | ||
[string]$Password, | ||
[string]$AuthType, | ||
[switch]$UseHttp, | ||
[switch]$ViewLogs, | ||
[switch]$Remove, | ||
[switch]$MSDeployAllowUntrusted, | ||
[switch]$CodeOnly | ||
) | ||
|
||
#Parses the publish settings file | ||
function ParsePublishSettings($PublishSettingsPath) { | ||
#Load the XML file | ||
[xml]$parsedPublishSettings = Get-Content -Path $PublishSettingsPath | ||
|
||
#Find the MSDeploy publishProfile node | ||
$webDeployPublishProfile = $parsedPublishSettings.publishData.publishProfile | ? {$_.publishMethod -eq "MSDeploy" } | ||
|
||
if ($null -eq $webDeployPublishProfile) | ||
{ | ||
Throw "Can't find MSDeploy publish profile in publish settings" | ||
} | ||
|
||
#extract parameters into a profile object | ||
@{ | ||
PublishUrl = $webDeployPublishProfile.publishUrl | ||
Username = $webDeployPublishProfile.userName | ||
Password = $webDeployPublishProfile.userPWD | ||
MSDeploySite = $webDeployPublishProfile.msdeploySite | ||
DestinationAppUrl = $webDeployPublishProfile.destinationAppUrl | ||
} | ||
} | ||
|
||
function Get-MSWebDeployInstallPath(){ | ||
return (get-childitem "HKLM:\SOFTWARE\Microsoft\IIS Extensions\MSDeploy" | Select -last 1).GetValue("InstallPath") | ||
} | ||
|
||
#Calls MSDeploy to publish the web deploy package to the Azure instance | ||
function PublishPackage($packagePath, $publishSettings, $publishSettingsPath) { | ||
Write-Output ("Publishing WebDeploy package to " + $publishSettings.MSDeploySite + " on " + $publishSettings.PublishUrl) | ||
|
||
$MSDeployInstallPath = Get-MSWebDeployInstallPath | ||
$MSDeployExecuteCommand = $MSDeployInstallPath + "MSDeploy.exe" | ||
|
||
Write-Verbose "Running MSDepoy from $MSDeployExecuteCommand" | ||
|
||
$destArgment = "-dest:auto,IncludeAcls='False'" | ||
|
||
if ($publishSettingsPath){ | ||
$destArgment += ",publishSettings='$publishSettingsPath'" | ||
} | ||
|
||
if ($Password) { | ||
$destArgment += ",password='$Password'" | ||
} | ||
|
||
if ($ComputerName) { | ||
$destArgment += (",computerName='" + $publishSettings.PublishUrl + "'") | ||
} | ||
|
||
if ($Username) { | ||
$destArgment += ",userName='$Username'" | ||
} | ||
|
||
if ($AuthType) { | ||
$destArgment += ",AuthType='$AuthType'" | ||
} | ||
|
||
Write-Host $destArgment | ||
|
||
$MSDeployCommandArguments = "-verb:sync", ` | ||
"-source:package='$packagePath'", ` | ||
$destArgment, ` | ||
"-setParam:Name=""IIS Web Application Name"",Value=$($publishSettings.MSDeploySite)", ` | ||
"-enableRule:DoNotDeleteRule", ` | ||
"-disableLink:AppPoolExtension", ` | ||
"-disableLink:ContentExtension", ` | ||
"-disableLink:CertificateExtension" | ||
|
||
if ($MSDeployAllowUntrusted) { | ||
$MSDeployCommandArguments += "-AllowUntrusted" | ||
} | ||
|
||
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew(); | ||
|
||
$MSDeployCommandArgumentsString = "$MSDeployCommandArguments" | ||
Write-Verbose "MSDeploy command arguments: $MSDeployCommandArgumentsString" | ||
|
||
$cmd = """$MSDeployExecuteCommand"" $MSDeployCommandArgumentsString" | ||
cmd /c $cmd | ||
|
||
if ($VerbosePreference -eq "continue") | ||
{ | ||
cmd /c $cmd | ||
} | ||
else { | ||
cmd /c $cmd | Out-Null | ||
} | ||
|
||
if ($LASTEXITCODE -ne 0) | ||
{ | ||
throw "MSDeploy failed" | ||
} | ||
|
||
$stopwatch.Stop(); | ||
|
||
Write-Output "Package publish complete in $($stopwatch.Elapsed)" | ||
} | ||
|
||
#Invokes the deployment and waits for completion | ||
function InvokeDeployment($publishSettings, $useHttp, $viewLogs, $remove) { | ||
Write-Output "Beginning package deployment" | ||
|
||
#Force TLS1.2 | ||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | ||
|
||
if ($publishSettings.DestinationAppUrl.EndsWith("/")){ | ||
$baseAPIUrl = "$($publishSettings.DestinationAppUrl)api/TDS/WebDeploy/" | ||
} | ||
else { | ||
$baseAPIUrl = "$($publishSettings.DestinationAppUrl)/api/TDS/WebDeploy/" | ||
} | ||
|
||
#Switch URL to HTTPS | ||
if (!$useHttp) | ||
{ | ||
$baseAPIUrl = $baseAPIUrl.Replace("http://","https://") | ||
} | ||
|
||
#Create the request urls | ||
$statusRequest = "$($baseAPIUrl)Status" | ||
$invokeRequest = "$($baseAPIUrl)Invoke" | ||
$removeRequest = "$($baseAPIUrl)Remove" | ||
$logRequest = "$($baseAPIUrl)Messages?flush=true" | ||
$clearLogMessageRequest ="$($baseAPIUrl)ClearLogs" | ||
|
||
#Get the current status | ||
$retryCount = 20 | ||
$requestComplete = $false; | ||
while($retryCount -ge 0) | ||
{ | ||
try | ||
{ | ||
$statusResponse = Invoke-RestMethod -Uri $statusRequest -TimeoutSec 60 | ||
|
||
$requestComplete = $true | ||
break | ||
} | ||
catch | ||
{ | ||
Write-Warning "Retrying connection to $statusRequest" | ||
$retryCount-- | ||
} | ||
} | ||
|
||
if (!$requestComplete) | ||
{ | ||
Write-Error "Could not contact server at $statusRequest" | ||
|
||
exit | ||
} | ||
|
||
#See if a deployment is taking place | ||
if ($statusResponse.DeploymentStatus -eq "Complete" -or $statusResponse.DeploymentStatus -eq "Idle" -or $statusResponse.DeploymentStatus -eq "Failed") { | ||
#Call the Invoke method to start the deployment. This may not be needed if the server is restarting, but if no Assemblies or configs change | ||
#it will be needed | ||
$invokeResponse = Invoke-RestMethod -Uri $invokeRequest -TimeoutSec 60 | ||
|
||
if ($invokeResponse -ne "Ok") | ||
{ | ||
throw "Request to start deployment failed" | ||
} | ||
|
||
Write-Output "Starting Deployment" | ||
} | ||
|
||
#Wait a bit to allow a deployment to start | ||
Start-Sleep -Seconds 2 | ||
|
||
#Get the current status to see which deploy folder is being deployed | ||
$statusResponse = Invoke-RestMethod -Uri $statusRequest -TimeoutSec 60 | ||
$currentDeploymentFolder = $statusResponse.CurrentDeploymentFolder | ||
|
||
while ($true) { | ||
#Get the current status | ||
$statusResponse = Invoke-RestMethod -Uri $statusRequest -TimeoutSec 60 | ||
Write-Verbose "Server Deploy State: $($statusResponse.DeploymentStatus)" | ||
|
||
#If the deployment folder has changed, complete the progress | ||
if ($statusResponse.CurrentDeploymentFolder -ne $currentDeploymentFolder) | ||
{ | ||
Write-Progress -Completed -Activity "Deploying Web Deploy Package from $currentDeploymentFolder" | ||
} | ||
|
||
#Update the progress bar | ||
Write-Progress -PercentComplete $statusResponse.ProgressPercent -Activity "Deploying Web Deploy Package from $($statusResponse.CurrentDeploymentFolder)" | ||
|
||
#If the user wants deployment logs, write the logs | ||
if ($viewLogs) { | ||
$logResponse = Invoke-RestMethod -Uri $logRequest -TimeoutSec 60 | ||
|
||
Write-Output $logResponse | ||
} | ||
|
||
#Stop if all deployment folders have been deployed | ||
if ($statusResponse.DeploymentStatus -eq "Complete" -or $statusResponse.DeploymentStatus -eq "Idle") { | ||
break | ||
} | ||
|
||
if ($statusResponse.DeploymentStatus -eq "Failed") { | ||
Write-Error "Errors detected during deployment. Please see logs for more details" | ||
|
||
exit 1 #set exit code to failure if there is a problem with the deployment | ||
} | ||
|
||
Start-Sleep -Seconds 5 | ||
} | ||
|
||
if ($remove) { | ||
Write-Output "Removing installer service from webserver" | ||
|
||
Invoke-RestMethod -Uri $removeRequest -TimeoutSec 600 | ||
} | ||
|
||
Write-Progress -Completed -Activity "Deploying Web Deploy Package from $($statusResponse.CurrentDeploymentFolder)" | ||
} | ||
|
||
if (-not($PublishSettingsPath)) { | ||
if (-not($ComputerName)) { | ||
Throw "Please specify a value for -PublishSettingsPath or -ComputerName" | ||
} | ||
|
||
if (-not($SiteName) -or -not($Username) -or -not($Password)){ | ||
Throw "If publish settins are not specified, please specify -SiteName, -Username and -Password" | ||
} | ||
|
||
$publishSettings = @{ | ||
PublishUrl = ("https://" + $ComputerName + ":8172/msdeploy.axd") | ||
Username = $Username | ||
MSDeploySite = $SiteName | ||
DestinationAppUrl = ("http://" + $ComputerName + ":80") | ||
} | ||
} | ||
else { | ||
$publishSettings = ParsePublishSettings $PublishSettingsPath | ||
} | ||
|
||
$currentDirectory = Split-Path $MyInvocation.MyCommand.Path | ||
|
||
if ($PackagePath) | ||
{ | ||
if (-not ([System.IO.Path]::IsPathRooted($PackagePath))) { | ||
$PackagePath = (Get-Item -Path ($currentDirectory + "\" + $PackagePath)).FullName | ||
} | ||
|
||
PublishPackage $PackagePath $publishSettings $PublishSettingsPath | ||
|
||
#Wait until server has recognized that files may have changed and begins its restart | ||
Start-Sleep -s 5 | ||
} | ||
|
||
if (-not($CodeOnly)) | ||
{ | ||
InvokeDeployment $publishSettings $UseHttp $ViewLogs $Remove | ||
} | ||
|
||
Write-Output "Package deployment complete" |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.