Capistrano is commonly used for rails deployments. Automated deployment is a very good thing. A while back I wanted to do something like that on windows for a .net project.
Pstools is a collection of command-line tools for windows from sysinternals . They provide unix-style process control for windows systems. There are a few tools that let you do things remotely on another windows machine (if you have permission).
So, what I wanted to do with a .net project was:
This should all be triggered from the BUILD machine using pstools.
If you keep your build tools in source control and you do this, you find that it won’t work. By default, windows security policy won’t execute .net apps from a shared drive. So running nant from your working folder won’t work. You can, however, manipulate that security policy using the Caspol tool . (You could probably skip this Caspol step if NAnt was installed on the target server as it would have trust to execute from the local drive on that machine.)
This is a proof of concept, showing how to make this work. It hasn’t been used extensively – though might be a good starting point to implement something like this. Details Follow…
The code for this article is here in subversion: https://please.peelmeagrape.net/svn/public/nant/remote/
Going to use nant macrodef library to set this up.
We also need the pstools library (just psexec actually). The EULA on the sysinternals tools seem to indicate that I can’t redistribute them. So I’ve put a little bit of nant in the build file to download them:
<if test="${not file::exists('tools/pstools/psexec.exe')}">
<mkdir dir="tools/pstools"/>
<get src="http://download.sysinternals.com/Files/PsTools.zip" dest="tools/pstools.zip"/>
<unzip zipfile="tools/pstools.zip" todir="tools/pstools"/>
</if>
The first time you use one of the pstools you will have to accept the EULA. (Though you could then check the exe into your source control and it should work from then on).
We will create a remote-nant task that will execute a target within a buildfile on a remote host. This task has some parameters:
You need system-level permissions to execute on the remote server – not sure exactly what is the most restrictive set that will work though. You might want to edit the macrodef and add username and password parameters also.
First, we need to share out the working folder. This needs cmd.exe, and should not fail on error (in case it’s already mapped):
<exec program="cmd.exe" failonerror="false">
<arg value="/c"/>
<arg value="net share remotenant${share_id}=${path::get-full-path(basedir)}"/>
</exec>
Then we alter the security policy on the target host to give ‘FullTrust’ to code originating on the drive we are mapping:
<exec program="psexec.exe" basedir="${basedir}\tools\pstools" failonerror="true">
<arg value="\\${remote_host}"/>
<arg value="-s"/>
<arg value="cmd.exe"/>
<arg value="/c"/>
<arg
value="${dotnetpath}CasPol.exe -machine -f -ag All_Code -url file:///${drive_letter}:/* FullTrust -name remote_nant_${drive_letter}"/>
</exec>
These two steps (sharing out the working folder and granting trust to the mapped drive on the target host) are wrapped up as the setup-remote-deploy task. The remove-remote-deploy tears down the network share, unmounts it on the remote server and removes the trust from the security policy.
Note: Yes, while the remote_nant is running, the security policy of the target server is relaxed.
cmd.exe shell on the remote server. In this shell, we mount the shared drive, switch to that drive and execute nant in that shell.
<remote-nant target="hello_world" remote_host="${remote_host}"/>
The example, at https://please.peelmeagrape.net/svn/public/nant/remote/ in subversion, has a hello world example. If you type go in the remote folder, it will execute the hello_world task. It executes against the localhost by default, use:
go -D:remote_host=server
to specify the host (or edit the build file).
( Writing this up from a Dublin Coding Brunch! )