Musings on code and life

PowerShell deployment

I've been playing around with using PowerShell to do some automated deployment. I'm posting the script if it might help anyone else, though I have to admit I'm new at powershell.


$env = $args[0]
$deploydir = "C:\Temp\Deployments\"
$repo = "https://bitbucket.org/"
$sln = ".\src\Project.sln"
$webproj = ".\src\Project.Website\Project.Website.csproj"
$jobproj = ".\src\Project.Service\Project.Service.csproj"
$jobpath = "_PublishedWebsites\Project.Website\App_Data\jobs\continuous\Service"
$config = "Debug"
$branch = "dev"
$publishSite = ""
$publishUser = ""
$publishPass = ""

if ($env -eq "prod") {
    $publishSite = ""
    $branch = "master"
    $config = "Release"
}

function Main() {
    $sw = [Diagnostics.Stopwatch]::StartNew()
    Clear-Host
    CreateTempFolder
    CheckoutCode
    BuildCode
    DeployToAzure
    DeleteTempFolder
    $sw.Stop()
    Write-Host "Success in" $sw.Elapsed
}

function CreateTempFolder() {
    Write-Host
    Write-Host "==================== CREATE TEMP ===================="

    $tempdir = [System.Guid]::NewGuid().ToString()
    #$tempdir = "Test"
    $path = Join-Path $deploydir $tempdir
    if ($tempdir -ne "Test") {
        New-Item $path -Type directory | Out-Null
    }
    
    Write-Host "Location: $path"
    Set-Location $path
}

function CheckoutCode() {
    Write-Host
    Write-Host "==================== GIT CHECKOUT ===================="
    
    #Git branch
    $path = (Get-Location).Path
    $prms = "clone " + $repo + " . --single-branch -b " + $branch + " -q -v"
    Run $path "git" $prms

    #Verify
    if ($LASTEXITCODE -ne 0) {
        throw "Web Build failed"
    }
    $gitFolder = Join-Path $path ".git"
    if ((Test-Path $gitFolder -Type container) -ne $true) {
        throw "Git folder not found"
    }

    #Delete git folder
    Delete $gitFolder
}

function BuildCode() {
    Write-Host
    Write-Host "==================== NUGET ===================="

    #Nuget restore
    Invoke-Expression (".\deploy\nuget.exe restore " + $sln + " -PackagesDirectory .\packages")

    #check Output folder
    $output = Join-Path (Get-Location).Path "output"
    if ((Test-Path $output -Type container) -eq $true) {
        Delete $output
    }
    New-Item $output -Type directory | Out-Null

    Write-Host
    Write-Host "==================== BUILD WEB ===================="
    $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
    $msbuild += " " + $webproj + " /T:_WPPCopyWebApplication /p:OutDir=" + $output + " /clp:ErrorsOnly /p:Configuration=" + $config #/verbosity:minimal
    Invoke-Expression $msbuild
    if ($LASTEXITCODE -ne 0) {
        throw "Web Build failed"
    }

    Write-Host
    Write-Host "==================== BUILD JOB ===================="
    $output = Join-Path $output $jobpath
    $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
    $msbuild += " " + $jobproj + " /p:OutputPath=" + $output + " /clp:ErrorsOnly /p:Configuration=" + $config #/verbosity:minimal
    Invoke-Expression $msbuild
    if ($LASTEXITCODE -ne 0) {
        throw "Job Build failed"
    }

    #Clear junk
    $output = Join-Path $output "_PublishedWebsites"
    Delete $output
}

#REF: http://blog.davidebbo.com/2014/03/WAWSDeploy.html
function DeployToAzure() {
    Write-Host
    Write-Host "==================== DEPLOY ===================="
    $output = Join-Path (Get-Location).Path "\output\_PublishedWebsites\Project.Website\"

    Delete $output "\App_Data\jobs\continuous\Service\*.xml"
    Delete $output "\bin\*.xml"
    Delete $output "\Notes.txt"

    $msdeploy = "'C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe'"
    #$msdeploy = """C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\Pscx\Apps\echoargs.exe"""
    $msdeploy += " -verb:sync ""-source:contentPath="+$output+""" ""-dest:contentPath="+$publishSite+",ComputerName=https://serverurl.com:443/msdeploy.axd?site="+$publishSite+",UserName="+$publishUser+",Password="+$publishPass+",AuthType=Basic"""
    $msdeploy += " -allowUntrusted -useCheckSum -enableRule:DoNotDeleteRule" # -verbose 
    $msdeploy += " ""-skip:objectName=filePath,absolutePath=App_Data\\jobs\\continuous\\Service\\Project.Service.exe.config"""
    #$msdeploy += " -whatif"

    Invoke-Expression ("& " + $msdeploy)
    if ($LASTEXITCODE -ne 0) {
        throw "Deploy failed"
    }
}

function DeleteTempFolder() {
    Write-Host
    Write-Host "==================== DELETE TEMP ===================="

    $tempdir = (Get-Location).Path
    Set-Location $deploydir
    #Start-Sleep -s 1 #wait 1 sec for delete
    
    Delete $tempdir
}

function Delete([String]$path, [string]$item = $null) {
    if ($item -ne $null) {
        $path = Join-Path $path $item
    }

    if ((Test-Path $path -Type container) -eq $true) {
        Remove-Item $path -recurse -force #folder
    }
    elseif (Test-Path $path) {
   Remove-Item $path #file
    }
}

function Run([String]$path, [String]$exe, [String]$prms) {
    #ProcessStartInfo
    $psi = New-object System.Diagnostics.ProcessStartInfo 
    $psi.CreateNoWindow = $true 
    $psi.UseShellExecute = $false
    $psi.RedirectStandardOutput = $true 
    $psi.RedirectStandardError = $true 
    $psi.FileName = $exe 
    $psi.Arguments = $prms
    $psi.WorkingDirectory = $path
    
    #Process
    $process = New-Object System.Diagnostics.Process 
    $process.StartInfo = $psi 
    [void]$process.Start()
    $stdout = $process.StandardOutput.ReadToEnd() 
    $stderr = $process.StandardError.ReadToEnd()
    $process.WaitForExit()
    
    #Output
    Write-Host "stdout: $stdout"
    Write-Host "stderr: $stderr"
    Write-Host "exit:" $process.ExitCode
}

Main