Archive

Posts Tagged ‘psake’

sharepoint-deployment-scripting-with-powershell

November 26th, 2010 No comments

PowerShell scripting approach for SharePoint (via psake)

This is a simple plea to SharePointers. Can we please have a decent build runner around PowerShell scripts in the deployment environment. Most developers in other frameworks do. So I thought that I would outline some basic techniques. psake is as good as any other options (except rake which I still think is vastly superior but I don’t want the operational hassle of needing it in other environments). Here’s what I’m doing:

  • powershell wrapped in psake
  • modularised scripts
  • psake helpers scripts for the real world (and documented in other places)
  • helper scripts for each of access to command line powershell

One caveat, psake has a couple of limitations that make it otherwise a good rake port:

  • it doesn’t namespace (AFAIK) tasks and that means it effectively works in the global namespace – this means we get conflicts and have to resort to poor naming practices
  • it doesn’t create good documentation for nested scripts – that seriously sucks – I want to be able to do -docs and read what I can do
  • it really doesn’t do logging well when moving across scripts (Start-Transcript seems to suck – but that might be my knowledge)

If you don’t go down this road what you end up with is a load of powershell scripts that we double click on. That’s not my idea of well structured or maintainable. Skip straight down to deploy.ps1 if want to see what the scripts look like rather than all the plumbing. And, yes, there is way too much plumbing! Here is the script where I actually do the packaging up of these files.

File layout

default.ps1
here.cmd
deploy.cmd
scripts/
    psake.psm1
    psake1.ps1
    deploy.ps1
    install.ps1
wsp/
    MySolution.wsp

Quick explanation:

  • psake1.ps1, psake.psm1 – both come with psake. psm is a module and the make DSL engine – go there to understand what to do. psake1 is a help wrapper.
  • default.ps1 is a manifest that links all your psake tasks – psake looks for default.ps1 by, well, default.
  • deploy.cmd is a GUI-based wrapper that invoke a specific tasks (deploy in this case)
  • here.cmd brings up a command line interface so that I can use all the psake tasks (eg Invoke-psake Deploy)
  • deploy.ps1, install.ps1 are my two specific sets of tasks – deploy has SharePoint cmdlets linked in here (install is a further wrapper that does logging and in my own case also invokes other scripts I haven’t included like migrations)

How to use

Option One:

  1. Click deploy.cmd

Option Two:

  1. Click here.cmd – this will list out the available commands
  2. Be able to type in powershell commands
Invoke-psake Deploy

Files

deploy.cmd

powershell -ExecutionPolicy Unrestricted -NoExit -Command "&{import-module .\scripts\psake.psm1; Invoke-Psake Install}"

default.ps1

Include .\scripts\deploy.ps1; 
Include .\scripts\install.ps1

here.cmd

powershell -ExecutionPolicy Unrestricted -NoExit -Command " &{import-module .\scripts\psake.psm1; Invoke-Psake -docs}"

psake.ps1

import-module .\scripts\psake.psm1

Start-Transcript -Path .\install.log
invoke-psake @args
Stop-Transcript

remove-module psake

deploy.ps1

$framework = '3.5x64'
Properties {
  $base_dir = resolve-path .
    $solution = "MySolution.wsp"
    $application = $null
    $path = "$base_dir\wsp\$solution"
    $SolutionFileName = ""
}

Task Deploy -Depends Solution-Setup, Solution-UnInstall, Solution-Remove, Solution-Add, Solution-Install, Solution-TearDown

Task Solution-Remove -Depends Solution-Wait{
  Write-Host 'Remove solution'
  Remove-SPSolution ñidentity $solution -confirm:$false
}

Task Solution-Add {
  Write-Host 'Add solution'
  Add-SPSolution -LiteralPath $path
}

Task Solution-Install {
  Write-Host 'install solution'
  if($application -eq $null)
  {
      Install-SPSolution -identity $solution -GACDeployment -force
  }
  else
  {
      Install-SPSolution -identity $solution -application $application -GACDeployment -force
  }
}

Task Solution-UnInstall {
  Write-Host 'uninstall solution'
  if($application -eq $null)
  {
     Uninstall-SPSolution -identity $solution -confirm:$false
  }
  else
  {
     Uninstall-SPSolution -identity $solution -application $application -confirm:$false
  }  
}

Task Solution-Setup {
  Add-PsSnapin Microsoft.SharePoint.PowerShell
}

Task Solution-TearDown -Depends Solution-Wait {
  Remove-PsSnapin Microsoft.SharePoint.PowerShell
}

Task Solution-Wait {
  $JobName = "*solution-deployment*$SolutionFileName*"
    $job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
    if ($job -eq $null) 
    {
        Write-Host 'Timer job not found'
    }
    else
    {
        $JobFullName = $job.Name
        Write-Host -NoNewLine "Waiting to finish job $JobFullName"

        while ((Get-SPTimerJob $JobFullName) -ne $null) 
        {
            Write-Host -NoNewLine .
            Start-Sleep -Seconds 2
        }
        Write-Host  "Finished waiting for job.."
    }
}

install.ps1

Task Install -Depends Logging-Start, Deploy, Logging-Stop

Task Logging-Start {
  Start-Transcript -Path .\install.log
}

Task Logging-Stop {
  Stop-Transcript
}
Categories: Uncategorized Tags: , , ,