Unfold is a capistrano-like deployment solution for .net applications. I created it because it didn’t find any solution that gave me enough flexibility and at the same time provided enough functionality out-of-the-box to deploy standard applications. In Unix environments, when it comes to deploying web applications, there’s nothing that rivals Capistrano. So what I wanted was pretty simple: a capistrano for .net/windows. This led me to the following design decisions:
we use only Powershell. In terms of automating things, there’s nothing more powerful than Powershell in the Windows world. You can execute any application, there’s a wealth of Modules that allow you to automate anything from installing a Windows Service, configuring IIS or creating folders
for access to remote machines, we depend on Powershell Remoting. It makes it very easy to execute scripts or ScriptBlocks on remote machines. For an easy explanation of Powershell Remoting, check here. The unfold wiki contains an article on how to setup Powershell remoting for your own target server.
Good defaults with good extensibilty:
Unfold had to contain a default deployment flow that is good enough for simple applications, if you need customization, then you should be able to built upon that flow.
The source code is on GitHub.
To install unfold, open a Powershell command-prompt and issue:
cd ~\Documents\WindowsPowerShell\Modules git clone https://github.com/thomasvm/unfold.git
To check whether the installation was successful, import the module.
Add unfold to your project
Now navigate towards a project folder where you want to specify your deployment recipe. For example, if your source code
sits inside a
src folder, then the parent folder is ideal. Once you’re there do:
This will create a folder called
deployment, containing two files
this file is the most important file, as it contains all your configuration and deployment steps. It’s the file that you customize to define your deployment.
this file is for loading the Unfold module and passing the command-line parameters in to it. More on that later
Let’s have a look at a slightly modified
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
Yep, that’s all there is to it, this is a full deployment script for a standard asp.net application. To test whether this works, open a PowerShell inside the folder and issue:
.\unfold.ps1 deploy -to dev
In other words: call the launcher script
unfold.ps1 and let it invoke the
deploy task (that is imported
Import-DefaultTasks) and deploy towards the
Of course, most of the time you’ll want to extend this. That’s for a later post, for now, we’ll have a look at what’s inside this file.
2.a The configuration part
deploy.ps1 file starts off with a set of calls to a function called
Set-Config. These calls populate a
$config variable that
is available throughout your deployment. Most of the variables in the example above are used by the standard Unfold deployment
tasks, but you can add your own if you need to. There are no restrictions. You’ve probably also noticed that some calls are wrapped within a
Set-Environment function call. These configuration settings are considered to be environment-specific. In the above example,
if you deploy using
.\unfold.ps1 deploy -to dev
$config.machine will be localhost, and the
$config.basePath will point to c:\inetpub\wwwroot\dev\YourProject. On
the other hand, if the -to parameter is set to “staging”
.\unfold.ps1 deploy -to staging
Then this will assign the values will be your.machine.name and d:\sites\YourProjectName\staging.
2.b The tasks part
Now that the configuration part is done, we’re ready to define some tasks. If your application doesn’t require too much special, it’s usually enough to just import the default Unfold tasks. That’s exactly what this line of code does
It imports a set of Psake tasks that together compose the deployment flow. A future blog post will explain which tasks there are and what their purpose is.
Next, we define a custom task, this can be used from anything like restarting windows services, clearing a cache folder, or checking whether a process is running. The little task that we define here is to check whether we can connect to our deployment machine.
1 2 3 4 5 6 7 8
This task writes out the computername, the current folder, and the basePath property of the
$config global variable we composed
Set-Config calls. What is important however, is that we do this inside a powershell scriptblock that we pass to a
Invoke-Script is a very, very important part of Unfold because it allows you to write deployment operations that work on
both your local machine as on a remote machine.
Invoke-Script function has 1 important parameter, namely the scriptblock that you pass into it. With that scriptblock,
Invoke-Script performs the following operation.
- It checks the
$config.machineparameter, and based on its value it decides where to execute the scriptblock.
- If the value equals “localhost”, then
Invoke-Scriptsimply changes the current directory to
$config.basePathand executes the provided scriptblock.
- If however, the value of
$config.machineis something else, like an IP address, a computername or a remote hostname, then it creates a new PS-Session through the New-PSSession function and uses that session to execute the scriptblock on the remote machine.
Invoke-Script allows you to write very transparent deployment code, but where to execute it, is completely dependant on
what the current configuration is.
In the above example, if the deployment is issues like this:
.\unfold.ps1 ping -to dev
Then the ping task will be executed and will write out the computername of the local machine. However, if we ask Unfold to execute the ping task on staging, it will print out the computername of your.machine.name.
.\unfold.ps1 ping -to staging
You may ask the question: “where do you get the credentials from when opening a session on a remote machine?”. The answer is very simple: from the Windows Credential Manager. Just open the Windows Credential Manager from your start menu and add a generic principal to it. This means we don’t have to store credentials in our deployment scripts. The name for the principal must reflect the name you’ve configured using:
The result of all this is that
Invoke-Script allows you to write deployment code that is easily portable between environments and it makes setting up
a new environment for your deployments just a matter of adding an extra
Set-Environment call to your deployment script.
You’ve now seen how you can easily create an Unfold deployment for your project, how the configuration system works and how to define customs deployment tasks.
In future posts, we’ll explain what the default deployment tasks are defined by Unfold and how to extend them with your own tasks. By doing so, you’ll be able to complete customize your deployment and make it completely automated and runnable from the command-line.