Automate Codeplex Releases in your Powershell build and deployment scripts / by Matt Wrock

codeplexI maintain a few projects on Codeplex.com and one that I have been working on actively lately is Boxstarter. A sort of “Add-On” to Chocolatey that allows you to run complex (or simple) environment scripts completely unattended in a reboot/logon resilient manner.

Whenever I startup any project that I plan to develop beyond a hack or a spike, the very first thing I do is lay down test infrastructure along with build and deployment automation. These are NOT “nice to haves” and especially since I devote my “free” time to these projects, it is important that I make the most of that time and spend as little time as possible chasing regression bugs or mucking with the Release gymnastics of packaging things up and copying/uploading files, etc. It is too easy to get that stuff wrong and takes too long to do and test every detail by hand every time I want to push bits - not to mention that it is just not fun.

When I push a Boxstarter release, my download zip, click-once app  and home page are updated on my Azure web site by doing a GIT Push to Master. My Chocolatey packages are packed and pushed by a deployment script. So the one manual step has been uploading ,my download zip file to Codeplex and creating a Codeplex Release for it. Well it ends up there is a web service that codeplex maintains to facilitate the automation of this step. It is a SOAP service and therefore a bit of a pain to call directly, but Codeplex also has a C# SDK that makes working with this service very easy.

While the SDK is a .Net Assembly that was likely intended for C# based clients, I prefer to write my build and deployment scripts in Powershell. I believe that what happens in a deployment should be easily discoverable and that the script should serve as the “deployment document.” Compiled code does not lend itself well to that kind of transparency. I also don’t like to use XML for control flow and therefore avoid msbuild for all but the basic compile tasks. PSake is a great powershell tool I have been using for years to organize and execute build and deployment scripts. Every build task is encapsulated by a Powershell function called Task. Here is my Push-Codeplex task:

Task Push-Codeplex { Add-Type -Path ` "$basedir\BuildScripts\CodePlexClientAPI\CodePlex.WebServices.Client.dll" $releaseService=New-Object CodePlex.WebServices.Client.ReleaseService $releaseService.Credentials = Get-Credential `   -Message "Codeplex credentials"`   -username "mwrock" $releaseService.CreateARelease(`     "boxstarter",`     "Boxstarter $version",`     "Running the Setup.bat file will install Chocolatey if not present `      and then install the Boxstarter modules.", `     [DateTime]::Now,[CodePlex.WebServices.Client.ReleaseStatus]::Beta,`     $true,`     $true) $releaseFile = New-Object CodePlex.WebServices.Client.releaseFile $releaseFile.Name="Boxstarter $version" $releaseFile.MimeType="application/zip" $releaseFile.FileName="boxstarter.$version.zip" $releaseFile.FileType=`   [CodePlex.WebServices.Client.ReleaseFileType]::RuntimeBinary $releaseFile.FileData=[System.IO.File]::ReadAllBytes(`   "$basedir\BuildArtifacts\Boxstarter.$version.zip") $fileList=new-object `   "System.Collections.Generic.List``1[[CodePlex.WebServices.Client.ReleaseFile]]" $fileList.Add($releaseFile) $releaseService.UploadReleaseFiles("boxstarter", "Boxstarter $version", $fileList)}

This adds the types in the Codeplex.Webservices.Client assembly to the current Powershell session. I have downloaded  the SDK and put it in my source tree. Its too bad this is not packaged in its own Nuget package. Then I could use Package Restore to grab the bits from Nuget.org.

Note that this assembly has a dependency on a couple Build assemblies. You could try to track these down separately but since I have Visual Studio installed, this gives me these dependencies.

The parent object handling all codeplex project commands takes a ICredentials to authenticate the client. I can simply use Get-Credential for this. This does require me to manually enter my password but that is fine for my script.If you had a more enterprise grade deployment that needed to fully script the authentication, that is very possible. After that I am free to create my release, and upload my file. This worked flawlessly for my project and now I can deploy my project with a single command.