Lets assume you have run the PowerUp Quickstart. Hopefully you are wondering – what actually happened during all that?
Have a look at the contents of build_package_nant_deploy_local.bat. You should see just a few DOS commands:
_powerup\nant\bin\nant cd _package call deploy local cd .. pause
Broadly, two things happen here. First, the solution is built into a package (the call to nant). Then that package is deployed to the local machine (deploy local). I will go over these two steps below.
Building the package (with Nant)
_powerup\nant\bin\nant
This step is a completely normal, run of the mill, nothing-special-at-all nant build. (Note – don’t like Nant? Don’t worry, you can use MSBuild as well – have a look at build_package_msbuild_deploy_local.bat for the exact equivalent of this in MSBuild)
Solution Nant File
For this solution (SampleWebsite), the nant build file (main.build) looks like this:
<project default="build-package-common">
<include buildfile="_powerup\common.build" />
<property name="solution.name" value="SampleSolution" />
<target name="package-project">
<copy todir="${package.dir}\SimpleWebsite" overwrite="true" flatten="false" includeemptydirs="true">
<fileset basedir="${solution.dir}\SimpleWebsite">
<include name="**.aspx"/>
<include name="**.css"/>
<include name="**.js"/>
<include name="**.master"/>
<include name="bin/**"/>
</fileset>
</copy>
</target>
</project>
This nant file does 3 things:
- Includes a reference to the PowerUp common nant file (common.build)
- Creates a property to set the name of the Solution file (in this case SampleSolution)
- States what within the website folder is required to be in the package (in this case all the aspx, css, js, master files and bin folder)
Common PowerUp Nant File
<target name="build-package-common" depends="clean compile-solution package-project copy-build-files zip-package" />
That is, it firstly cleans (both the package folder and the solution bin folders), compiles the solution, calls package-project to get the solution specific files (look back at main.build to find this target), copies the powerup folder (and some other required files) into the package and then zips the whole lot up.
Package Contents
The result of all this is output to the folder _package, found under the root of your solution root folder. The contents look like this:
I won’t explain in detail all the items here just yet. But generally the contents of this are:
- Any folder created by the package-project target in main.build. In this case, it is SampleSolution, but this may be up to many dozens of folders for an extremely large solution.
- The _powerup folder, which contains all the PowerUp scripts and dlls required during deployment.
- The _templates folder, which contains templates config files for substitution during deployment (to be explained further later)
- The solution specific files settings.txt, servers.txt and deploy.ps1. These are the settings and deployment scripts that guide the specifics of each deployment (again, this will be explained in full later)
- The package identification file package.id, used to efficiently distribute this packages across multiple servers.
Deploying the Package
call deploy local
The above package is designed to be environment neutral. That is, it is designed to be NOT built with a particular deployment environment in mind (local, test, staging, live etc).
What this means is that during deployment, you must specify which environment you are deploying to in this particular instance. Technically, PowerUp refers to this as the deployment profile.
So by calling “deploy local” we are instructing PowerUp to deploy this package according to the deployment profile “local”. What does this actually do then?
Deploy.ps1 (the deployment file)
This is the (psake) file where, for each solution, you detail what should happen during a deployment. In the case of SimpleWebsite, the deployment file looks like this:
include .\_powerup\commontasks.ps1
task deploy {
run web-deploy ${web.servers}
}
task web-deploy {
import-module powerupfilesystem
import-module powerupweb
$packageFolder = get-location
copy-mirroreddirectory $packageFolder\simplewebsite ${deployment.root}\${website.name}
set-webapppool ${website.name} "Integrated" "v4.0"
set-website ${website.name} ${website.name} ${deployment.root}\${website.name} "" "http" "*" ${http.port}
}
We’ll start with the web-deploy task. In here we:
- Instruct the deployment to copy the contents of the “SimpleWebsite” to the required folder of the destination server.
- Create an an apppool.
- State we want a website of a certain name with this apppool, bound to http, all IP addresses and a given port
All quite simple then. But there are probably already some questions in your head. Firstly – where do the properties (${website.name}, ${http.port} etc) come from? Secondly, where do the cmdlets (copy-mirroreddirectory etc) come from? Thirdly, what is the line “run web-deploy ${web.servers}” for?
I will take these all in turn.
Settings.txt (the configuration settings)
This file holds all the information about the differences between each environment you wish to deploy to. Lets have a look:
default
website.name SimpleWebsite
deployment.root ${root.drive}\sites
http.port 80
https.port 443
local
web.servers localhost
root.drive c:
http.port 9000
https.port 9001
example.setting local
staging
web.servers stagingweb
root.drive e:
example.setting staging
live
web.servers liveweb1;liveweb2
root.drive g:
example.setting live
See the setting names? That is what we are referring to within the script. By having the setting values separate out like this, this allows a single deploy.ps1 file work just fine for many different environments. There are some subtleties here which I won’t explain fully (such as how the default profile works, referencing other setting from settings etc), but hopefully the basics are clear.
Built in PowerUp Cmdlets
During the script we refer to a number of PowerUp cmdlets, such as copy-mirroreddirectory. These cmdlets live in the _powerup\modules folder, as so:
To use each of these, the script simple calls import-module for the modules required. By default, PowerUp has placed this entire directory in the Powershell modules path. Of course, you can include any other non-Powerup modules just like you would in any Powershell script.
Remote Tasks/servers.txt
Turn your attention now to following lines in deploy.ps1:
task deploy {
run web-deploy ${web.servers}
}
As you might expect, this line states “run the task web-deploy on the machine web.servers”. Why would we want this?
You may not immediately notice why we would need to do this. Here are a few reasons why you might want to execute tasks on machines other than the one you start the script on:
- You are executing the script on a CI server, and want bits of the deployment to run on your test server. That is, you want the website created on your test server, not the CI server itself!
- You have 3 web servers on Live, and you want to deploy to all of them without running the script 3 times
- You need to install something on the database server
default
temp.root.drive c
remote.temp.working.folder \\${server.name}\${temp.root.drive}$\packages
local.temp.working.folder ${temp.root.drive}:\packages
localhost
server.name localhost
stagingweb
server.name staging.exampledomain
liveweb1
server.name live1.exampledomain
liveweb2
server.name live2.exampledomain
- What the network name of the server is
- Which folder PowerUp can copy the package to and run scripts from (both the external and local path).
File (usually config Subsitutions)
In .Net at least, config files need to be different in some way on each environment. Maybe the db connection string has to be different, or the url of an external web server.
PowerUp deals with this through file templating, combined with the settings system already described above.
Have a look at _templates\SimpleWebsite\web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="EnvironmentName" value="${example.setting}"/>
</appSettings>
</configuration>
See the placeholder ${example.setting}? That will be substituted (during deployment) for the specific value for the deployment profile from settings.txt. In the case of local, this is simply “local”. You can see the effect of this at http://localhost:9000, in the sentence “This is the website for the environment “local”.
The rules for this substitution scheme is simple: any files you place in _templates will be processed such that any occurances of a setting will be replaced, and the resulting file copied over the top of the package before it deploys.
Summary
So there are the basics of how PowerUp builds packages and then deploys them. Hopefully that is enough to understand the Quickstart deployment, and even getting started on your own.
Extensibility note: What I have described here is the default behaviour of PowerUp. None of this is mandatory. It is possible you might want to store your settings a different way (maybe in a database), execute remote tasks a different way, or deal with web.config files in a different way. All of this is supported, and will be detailed in later blog posts.
Other Posts
Next (How To Know If PowerUp is Right For You)


[...] Next (PowerUp Quickstart – An Rundown) [...]
[...] Previous (PowerUp Quickstart – A Rundown) [...]
[...] A Rundown of what the PowerUp Quickstart Does [...]