Getting Started

You want developers to build, test, and deploy a product on their own computers. As often as possible, you want staff with appropriate permissions to deploy it to other environments and eventually on to production without manual changes. You are deploying to Windows and you want to use PowerShell code you’ve written already, or other modules you’ve found on the web.

If this sounds like you, powerdelivery is what you need. Every good automated release is custom so changes to it need to be fast. Powerdelivery is designed specifically to allow PowerShell developers to use a standard directory structure, some cmdlets that generate files, and a mechanism for securely sharing secrets to put code they already know to use without learning new APIs.

This page provides a walkthrough of getting setup and building a simple automated build to demonstrate some of the core features of powerdelivery. We’ll just scratch the surface - to automate the release of your product, you’ll want to read the rest of the topics when you’re done here.

Requirements

Powerdelivery can be run directly from a developer’s computer, or you can set it up to run automatically when developers check code into their source control repository. Either way, the computer that will run powerdelivery needs the following components:

  • Windows 7, 8.1, or 10; or Windows Server 2008 R2 or 2012
  • PowerShell 3.0 or greater
  • Whatever you need for compiling assets into deliverables (Visual Studio, Java, Grunt, etc.)
  • Open ports in the firewall from your computer to any nodes you will deploy to

Install powerdelivery

Before you can use powerdelivery you’ll need to install it onto your developer’s computer, and your build server (if using one).


Method A: Installing with chocolatey

The easiest way to install powerdelivery is with the chocolatey package manager. To use this method you must permit PowerShell scripts downloaded from the internet to run on the computer.


To do this, open a PowerShell Administrator console and enter the command below:

Administrator: Windows PowerShell
PS> Set-ExecutionPolicy Unrestricted


After allowing scipts to run from the Internet and installing chocolatey, open a PowerShell Administrator console and enter the following command:

Administrator: Windows PowerShell
PS> choco install PowerDelivery3


After this completes, close and re-open an Administrator PowerShell console.


Method B: Installing from source

If you are not permitted to run scripts from the Internet due to IT policies, you must install from source and digitally sign the module with your company’s certificate. The source is available from github.


Use your favorite git tool and clone the following repo:

https://github.com/eavonius/powerdelivery.git


Once you have the code in a local directory, modify the PSMODULEPATH environment variable by appending the Modules subdirectory of powerdelivery. You can do this with the Windows System control panel application.


For example, if the powerdelivery source is at C:\Powerdelivery append this to the end of PSMODULEPATH:

;C:\Powerdelivery\Modules


Once you’ve set this variable, close any open consoles and re-open an Administrator PowerShell console.


Create a project

Powerdelivery includes the New-DeliveryProject cmdlet that can be run from your console to generate an intial project. You’ll want to store the files generated by this cmdlet in source control. If you want to store your powerdelivery project along with the product’s source code, first pull your source into a local directory.

Imagine our product’s source code has been pulled into the directory C:\MyApp and the name of the product is “MyApp”. We decide to allow developers to deploy on their local computers; have another environment for user acceptance testing, and one for production.


Below is an example of creating this project:

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


After this cmdlet completes you’ll be left with the following directory structure:

C:\MyApp\MyAppDelivery\
  |-- Configuration\
      |-- _Shared.ps1
      |-- Local.ps1
      |-- Test.ps1
      |-- Production.ps1
  |-- Environments\
      |-- Local.ps1
      |-- Test.ps1
      |-- Production.ps1
  |-- Roles\
  |-- Secrets
  |-- Targets\
      |-- Release.ps1


Because we specified three environment names as the second parameter to the cmdlet, powerdelivery generated files specific to each environment as appropriate. You could name these whatever makes sense for your particular method of release. We’ll disect each of the above directories and generated files in the sections that follow.


Configure environments

Next you need to tell powerdelivery what nodes will host the product in each environment. This will be totally dependent on your application.

Imagine our test environment will have two web server nodes and one database server node. In production, there will be four web servers and two database servers that have been setup for fault tolerance by being part of a Windows cluster.


With these decisions made, we fill out environment scripts:

param($target, $config)
@{
  Build = @{
    Hosts = "localhost"
  };
  Database = @{
    Hosts = "localhost"
  };
  Website = @{
    Hosts = "localhost"
  }
}
MyAppDelivery\Environments\Local.ps1
param($target, $config)
@{
  Build = @{
    Hosts = "localhost"
  };
  Database = @{
    Hosts = "x.x.x.1"
  };
  Website = @{
    Hosts = "x.x.x.2", "x.x.x.3"
  }
}
MyAppDelivery\Environments\Test.ps1
param($target, $config)
@{
  Build = @{
    Hosts = "localhost"
  };
  Database = @{
    Hosts = "x.x.x.4", "x.x.x.5"
  };
  Website = @{
    Hosts = "x.x.x.6", "x.x.x.7", "x.x.x.8", "x.x.x.9"
  }
}
MyAppDelivery\Environments\Production.ps1


Note how each script file is named after the environment. Each set of nodes has a name (Build, Database, and Website in this case) and a set of host names separated by commas. The IP addresses can instead be computer names if resolvable through DNS or NetBIOS. You can also use connection URIs here, see the full environments topic for details.

We’ve set the Build group of nodes to always specify localhost. This ensures that any actions performed on this set of nodes are run on the developer’s computer (or the build server) and not a test or production node.

This example assumes the nodes are already running. If you need to provision nodes on the fly (for A/B deployments) see provisioning nodes at deploy time. This is what the $target and $config parameters are for - you can ignore them for now.


Create a role

In powerdelivery, a role is a script intended to apply a set of changes to a node to enable it to serve a particular function in your overall product’s architecture. This is where the heavy lifting of your deployment is done. Whatever nodes are configured to run this role will actually execute the script directly on that computer. Roles might deploy a website, run scripts against a database, or install dependencies using oneget or chocolatey. Powerdelivery doesn’t create roles for you so let’s dig into creating one.


First generate a role with the New-DeliveryRole cmdlet:

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


After this cmdlet completes it will have added the following to your directory structure:

C:\MyApp\MyAppDelivery\
  |-- Roles\
      |-- Compile\
          |-- Always.ps1
          |-- Migrations\


The default script is called Always.ps1 because it runs every time. Migrations are discussed in the full roles topic, we’ll skip those for now. The most common thing needed before any deployment of a release can occur on most Windows projects is compiling of code. To do this, we’ll use powerdelivery’s included Invoke-MSBuild cmdlet to compile a Visual Studio solution.


Here’s an example of scripting our role to compile a Visual Studio solution:

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

  Invoke-MSBuild -ProjectFile MyApp.sln
}
MyAppDelivery\Roles\Compile\Always.ps1


The Delivery:Role statement contains all code that will execute when this role is applied to a node. The second line declares the three special parameters that are passed to every role. We’re not using them here so you can ignore them for now.


Create a target

In powerdelivery, every sequential deployment process you want to complete during one run is represented by a target script.


Let’s use the default Release.ps1 script generated by the New-DeliveryProject cmdlet:

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


The ordered keyword tells powerdelivery to run these steps in sequence. The key of each step will be displayed as a status message. Roles is an list of any roles that should be applied when this step is reached. In this case we will apply the Compile role we implemented in the role script earlier. Lastly, Nodes is a list of sets of nodes from the environment script that specifies which sets will have the roles applied to them.

Whew! That’s a mouthful. In layman’s terms, this code says “When building the product, apply the compile role to the build nodes in the environment”.


Run a target

To run a target, use the Start-Delivery cmdlet. You should always run this from the directory above your powerdelivery project. This cmdlet takes the name of the project as the first parameter, the target to run as the second, and the environment to apply the target to as the third.


The console session below demonstrates a run of the Release target in the Local environment:

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

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

[----- Building the product
[---------- Compile -> (localhost)

Target "Release" succeeded in 1 sec 857 ms.


Upon running the command you will see a build log in PowerShell similar to above that shows who ran the build, which targets and environment were selected, and the progress of the roles being applied to each node. If any errors occur you will need to resolve them and try your target again.

Now that you’ve had an overview of powerdelivery, follow the directions on this page to install it and create your own project, and continue by reading about environments in more detail.