A warning

This post in its entirety isn’t readable by humans. I’m sorry. I started by picking out a few psake scripts here and there, figuring hey. I’ll pick one or two examples and talk about what they’re doing.

The problem with writing a blog post about build scripts is it’s pretty boring. No one idly browsing their feed reader makes it through an entire post without being knocked unconscious. Ooh, that reminds me: if you’re currently operating heavy machinery or piloting a jet plane, for your safety please stop reading this blog post. Thanks.

But. But, even though it’s well known that this kind of stuff is boring to read about, I still want to collect all the knowledge on this earth related to psake and how people are using it. And I’ve done that below (at least as of 2011-08-10).

Unfortunately for you, my dear reader, I’ve made no attempt to process my raw data collection into something readable, what with sentences, paragraphs, code samples and topical grouping. That takes way too long. I’m too lazy for that.

Instead, I’m linkblogging a clump of psake scripts and mentioning what pieces you may want to steal for your own build script.

As a bonus (and because it’s part of what I’m researching), I’ve included a bunch of links to deployment-related blog posts and deployment scripts. These things are gold, and despite their seeming tinyness and insignificance, represent hours of sweat and toil.

Don’t Read This Blog Post – Search It

So I don’t expect anyone to, you know, read this post. But, if you’re like me, you’ll find that when it comes time to, say, add a NUnit test runner to your build script, or say, deploy to a remote IIS server, you’ll fire up your handy browser search (CTRL+F) and go looking for a script.

Well, maybe go ahead and read when I tell you to pay attention

A few places where I think a build script has done something novel, I’ll put a small note telling you to pay attention. It’s not meant to be insulting, but a way to un-zombify your brain so that you actually read that bullet point—so that it stands out from the endless sea of text and bullet points. I know, I could take the time to blog an entire post about each one of these points, and maybe I will. But for now, bet on my laziness and assume I won’t, and pay a little extra attention to how these folk put together their build scripts.

It’s like the famous quote from Passenger 57: “You ever play roulette? Always bet on Peter being lazy.” –Wesley Snipes, Passenger 57, word-for-word quote

Now that you’re mentally prepared for the hail of bullets that is to follow (bullet points, that is), have at it.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

JP Boodhoo wrote the first* non-trivial publicly-available psake script, and thus you’ll notice all the other scripts have borrowed bits and pieces from his script (particularly the ruby_style_naming_convention which_is_not_camel_case like_PowerShell_should_be):
*that I remember

  • build script
    • He is the only person who doesn’t rely on Solutions/Project files to compile his project, instead relying on aspnet_compiler.exe. Note, for those of you unaware, if you set the OutDir parameter for MSBuild, it will compile web application projects with surprisingly pleasant results.
    • He has written his own miniature database migration tool using only PowerShell. Not bad if I do say so myself.
    • He makes clever use of “dir” to lazily find all files he needs to compile (e.g. “dir * -include *.cs -recurse")

Ayende’s scripts:

  • Rhino ESB – default.ps1 and psake-ext.ps1
    • Compiles by running MSBuild on the .sln file
    • Packages with the NuGet.exe command-line tool
    • Zips files using the 7zip (7za.exe) command-line tool
    • Runs XUnit tests via xunit.console.clr4.exe
    • Generates AssemblyInfo.cs (which, if you’re unaware, is where you get your assembly version number from)
    • Pulls the desired version number from Git source control using the git.exe command-line tool
  • RavenDB – default.ps1 and psake-ext.ps1
    • Neat way to check for installed software (prerequisites)—this checks to ensure you have .NET 4.0 installed (see the “Verify40” task)
    • Runs a complex test scenario in the “TestSilverlight” task—it fires up a local Raven server in RAM, runs Silverlight-related unit tests, then kills the Raven server.
    • Packages files from disparate sources—RavenDB shows how it’s done. Hint: it’s not pretty.
    • Zips files using the zip.exe command-line tool (i.e., not the same tool at 7zip)
    • Builds what appears to be an intense NuGet package
    • Uploads static web content to a live environment using S3Uploader.exe
    • Note the simple build instructions found here
  • Texo (his jokingly/admittedly-NIH PowerShell Continuous Integration server)
    • builder.ps1
      • Sends email
      • Tries to get latest on a git branch via raw git.exe commands

DotLess:

  • default.ps1
    • Compiles by running MSBuild on the .csproj files
    • Runs ILMerge
    • Builds a gem (as in, RubyGems gem)
    • Builds a NuGet package

LINQToEPiServer:

  • default.ps1
    • Compiles by running MSBuild on the .sln file
    • Starts the MSDTC service (SQL Server distributed transactions) using net start
    • Does extreme funkiness with NUnit impersonating MSTest…I have no idea why.
    • Modifies all config files with a simple homebrew templating engine (think string.format’s {0} {1} etc.).

CodeCampServer:

  • psake.bat
    • A pretty good psake launcher that does everything you need to run the build script, plus highlights failed builds.
  • default.ps1
    • Compiles by running MSBuild on the .sln file
    • Includes a large number of helper functions. Pay attention to the fact that in psake, you don’t have to use tasks for everything—by all means write first-class functions that accept arguments! Arguments! They’re awesome! Use them!
    • Runs Tarantino (database migration tool)
    • Runs FXCop and something called “SourceMonitor”
    • Runs NUnit both with and without NCover code coverage metrics
    • Zips whole directories
  • nant.build
    • I know this has nothing to do with psake, but there’s a lot of stuff in there. A lot of the command-line call-outs can be converted to your needs.
  • Deployment helper functions nicely packaged into PowerShell module files (psm1)
    • Database.psm1 - Uses .NET’s SMO objects(?) to interact with SQL Server
      • Creates SQL Server user (an Integrated user, not a native SQL user) on the SQL instance and on the SQL database
      • Does something scary-looking that appears to export an entire database, but not the way you’re thinking—not the normal way of exporting a database.
    • Package.psm1 – Uses a COM object called “shell.application” to Zip a directory
      • Unlike my (and everyone else’s) implementation, this zip function makes use of object piping to receive the list of files. Nice.
    • ScheduledJobs.psm1 – Uses a COM object “schedule.service” to manipulate Windows Scheduled Tasks
      • Creates a new scheduled task.
    • Windows.psm1 – Uses PowerShell’s WMI support to create local (not domain) users and assigns users to groups.
      • Creates a local user on the machine
      • Adds a user to a local group
    • IIS.psm1 – uses the “WebAdministration” IIS cmdlets to manipulate IIS
      • Creates an IIS website object and actually sets the bindings successfully (yessssssssss).

Aaron Weiker’s blog series

  • sample psake script from his blog post
    • Compiles by running MSBuild on the .sln file
    • Configures app.configs with environment-specific modifications using XPath (i.e. a lot more like the NAnt/MSBuild helpers, and less hacky than doing string search & replace)
    • Runs RoboCopy
    • One neat thing I haven’t started doing, but desperately need to start doing, is to start throwing exceptions if script/function parameters are not passed in. Pay attention and see lines #1-4 of his psake script to see what I mean by this. I’ve lost hours of my life I will never get back troubleshooting PowerShell scripts over the years only to find that I passed in a paramter called “-name” when I needed to pass in a parameter called “-fullname”. So, if you don’t do this either, start doing it.

Darrel Mozingo’s blog series

  • sample psake script from his blog post
    • Compiles by running MSBuild on the .sln file
    • Runs NCover and NCoverExplorer
    • Includes helper methods that won’t make any sense to you until you actually use PowerShell and are annoyed by the same things that caused him to write those one-line helper methods. Pay attention to the little things he does in his helper methods that you probably think are fluff. Pop quiz: why did he write a create_directory helper method? I’ve experienced the pain and know the answer. If you haven’t, take my and his word for it and at least attempt to figure out why those helper methods exist.
  • Four-part series on deployment with PowerShell (1, 2, 3, 4)
    • Part 2:
      • Modifies web.config via PowerShell’s built-in [xml] object wrapper (but only making a minor edit)
      • Pre-compiles the ASP.NET site
      • Writes a CPS-style (CPS-style-style? I feel better now.) function that maps a network share, yields to the caller, then unmaps when done.
      • Takes a configuration backup of the live ASP.NET site
    • Part 3:
      • Remotely manages IIS via PowerShell remoting (starting & stopping IIS)
    • Part 4:
      • Rewrites the system hosts file
      • Tests current DNS settings (cool!)
      • Loads Internet Explorer to ping the website to force it to compile itself
      • Verifies emails are being sent (so hot!)

A blog series

  • psake script and run.bat (download demo.zip linked from this site if you want to see the raw psake script)
    • The run.bat sample does something novel—pay attention to how it loads PowerShell as a shell (REPL environment), not as a run-and-exit script. Smooth.
    • IIS adminstration via a mix of IIS (“WebAdministration”) cmdlets and WMI. Smooth. Creates a website and a new AppPool.

Señor Hanselman apparently wrote a whitepaper about deploying with PowerShell

  • Gets latest from a SVN repository via a .NET SVN library
  • Does heap big remoting work pre-PowerShell 2.0 (i.e. ,before PowerShell had any built-in remoting support)

Mikael Lundin (litemedia) blogged

I should mention Derick Bailey’s Albacore project for .NET – it’s a collection of Rake (Ruby) tasks that are the equivalent of a lot of what I’ve listed above. And from what I’ve seen, it has some things I haven’t covered above. Here’s list of things it does, machine-gun-style:

  • csc.exe, docu, FluentMigrator, MSBuild, MSpec, MSTest, NAnt, NChurn, NCover, NDepend, NUnit, NuSpec, Plink, SpecFlow, Sqlcmd, zip/unzip, XBuild, XUnit.