Devops-friendly
Windows releases
on-premise or
in the cloud.

Goodbye, manual releases.

Inspired by ansible and rails, powerdelivery organizes everything Windows PowerShell can do within a secure, convention-based framework so you can stop being jealous of your linux friends when you release to Windows.

pure powershell | rollback-capable | encrypts secrets | open source

To discuss powerdelivery Gitter anyone can join!

A birds-eye view

Before you read the docs, see some code.

Create a project

Administrator: Windows PowerShell
PS C:\MyApp> New-DeliveryProject MyApp "Local", "Production"
Project successfully created at ".\MyAppDelivery"

Set variables

param($target, $shared)
@{
  SiteURL = "http://myapp.cloudapp.net";
  ReleasesPath = ".\Releases"
}
MyAppDelivery\Configuration\Local.ps1
param($target, $shared)
@{
  SiteURL = "http://www.myapp.com";
  ReleasesPath = "\\MyShare\MyProduct\Releases"
}
MyAppDelivery\Configuration\Production.ps1

Configure environments

param($target, $config)
@{
  Build = @{
    Hosts = "localhost"
  };
  Web = @{
    Hosts = "localhost"
  }
}
MyAppDelivery\Environments\Local.ps1
param($target, $config)
@{
  Build = @{
    Hosts = "localhost"
  };
  Web = @{
    Hosts = "x.x.x.3", "x.x.x.4";
    Credential = "MYDOMAIN\ops"
  }
}
MyAppDelivery\Environments\Production.ps1

Create roles

Administrator: Windows PowerShell
PS C:\MyApp\MyAppDelivery> New-DeliveryRole "Compile", "Webapp"
Role created at ".\Roles\Compile"
Role created at ".\Roles\Webapp"

Script roles

Delivery:Role {
  param($target, $config, $node)

  # Publish website into a directory
  Invoke-MSBuild MyApp.sln -properties @{DeployOnBuild = "true"; PublishProfile = "MyApp"}

  # \\SHARE\<ProjectName>\<StartedAt>
  $remotePath = "$($config.ReleasesPath)\$($target.ProjectName)\$($target.StartedAt)"

  # Copy website to a network drive, S3 bucket, 
  # or wherever the remote nodes can access
  Copy-Item "MyApp\bin\publish" $remotePath -Recurse
}
MyAppDelivery\Roles\Compile\Always.ps1
Delivery:Role -Up { 
  param($target, $config, $node)

  Import-Module PowerDeliveryNode
  Add-PSSnapin WebAdministration

  # \\SHARE\<ProjectName>\<StartedAt>
  $remotePath = "$($config.ReleasesPath)\$($target.ProjectName)\$($target.StartedAt)"

  # AppData\Roaming\MyApp\Current
  # (symlinked to AppData\Roaming\MyApp\yyyyMMdd_HHmmss)
  $appDataDir = [Environment]::GetFolderPath("ApplicationData")
  $releasePath = New-DeliveryReleasePath $target $appDataDir
  
  # Copy web content from the network drive to the current release
  Copy-Item $remotePath $releasePath -Filter *.* -Recurse

  # Create the web application
  New-WebApplication $config.SiteURL MyApp $releasePath -Force

} -Down { 
  param($target, $config, $node)
  
  Import-Module PowerDeliveryNode

  # Rollback AppData\Roaming\MyApp\Current to previous release
  $appDataDir = [Environment]::GetFolderPath("ApplicationData")
  Undo-DeliveryReleasePath $target $appDataDir
}
MyAppDelivery\Roles\Webapp\Always.ps1

Configure a target

[ordered]@{
  "Building the product" = @{
    Roles = "Compile";
    Nodes = "Build"
  };
  "Deploying the website" = @{
    Roles = "Webapp";
    Nodes = "Web"
  }
}
MyAppDelivery\Targets\Release.ps1

Release locally

Administrator: Windows PowerShell
PS C:\MyApp> Start-Delivery MyApp Release Local

PowerDelivery v3.0.1
Target "Release" started by MYDOMAIN\dev
Delivering "MyApp" to "Local" environment...

[----- Building the product
[--------- Compile -> (localhost)
[----- Deploying the website
[--------- Webapp -> (localhost)

Target "Release" succeeded in 10 sec 453 ms.

Release to production

Administrator: Windows PowerShell
PS C:\MyApp> Start-Delivery MyApp Release Production

PowerDelivery v3.0.1
Target "Release" started by MYDOMAIN\ops
Delivering "MyApp" to "Production" environment...

[----- Building the product
[--------- Compile -> (localhost)
[----- Deploying the website
[--------- Webapp -> (x.x.x.3)
[--------- Webapp -> (x.x.x.4)

Target "Release" succeeded in 1m 13 sec 56 ms.


Now get started automating your own releases!