How to make a CI Build for a custom DSC Resource with Appveyor & PowerShell Gallery

A while back I created a custom DSC resource which enabled you to manage packages installed with Chocolatey (awesome package manager for Windows, like apt-get).

You can do some cool stuff with it, like build out a dev box in azure with one script, use for deployment or just to setup your machine after a rebuild.

So it turns out people have been doing just that, it’s had over 1,200 downloads from the PowerShell Gallery!

image

Not only that but it’s been improved by the community with pull requests adding functionality and improving the resource.

image

I wasn’t really expecting this to happen so didn’t have a clear idea of how to test, merge and publish these contributions. In the past, on other projects like powergist, I’ve used Appveyor to handle the CI as it’s free for OSS projects and it’s great to use. I thought I’d give it a spin here and see if I could get it to play ball with the PowerShell Resouce.

What I wanted from my DSC CI Build

  1. Do some simple tests to make sure the resources are valid.
  2. Increment the manifest file version number.
  3. Publish the updated resources to the Powershell Gallery.
  4. Checkin the updated manifest file to Git, so we can track the releases back to the source.

Before we get started it’s worth covering some basics of appveyor. Firstly the service lets you store config information and access it via environment variables. For secure variables you can encypt these as well. Secondly it lets you checkin your build definition and have it sit alongside you’re code as an ‘appveyor.yaml’ file. You can see mine here.

My yaml file defines but can do lots more too:

  • The OS build I’d like, we’ve using WMF5 but you might want VS2013 etc.
  • Any install scripts to run before building, here we make sure nuget is setup and ready.
  • The environment variables, secure and simple.
  • Finally the script to run for the build.

With that done we move onto where the meat of the work is going on - the build script. Throughout the description below I’ve linked to the lines/sections in question, click the links to see the accompanying code.

A the start of the script I pull in the environment variables for my modules name, the folder it’s been cloned too, the nuget key used to publish PSGallery and the Build number. These are all then used later in the script, separating these out makes it easy to chance them or use the script for another DSC resource in the future.

1. Testing the Resource

There is a great package for designing and testing custom resources called ‘xDSCResourceDesigner’ and a great blog here on how to use this to run tests.

I adapted the script and added it to my CI Build script, you can see the chunk here.

It loops through the resources, tests them and, should any fail, exits with an error code so a broken package isn’t pushed to the PSGallery.

2. Increment the version number from the manifest

To do this I read in the file here and invoke is as an expression, it’s a PowerShell hashtable so that’s the quickest way to get at it’s content. Once we have it we can then create a new version number, add it in and write the updated file back out to disk.

N.B I couldn’t get the ‘Update-ModuleManifest’ cmdlet to work in appveyor, if I had it would have simplified this process greatly as I could drop the ‘ConvertTo-PSON’ function etc.

This is a simple one liner here, which takes in the Nuget key and pushes the package up to the gallery.

4. Pushing back to GIT

This is a bit more complex and there is a great guide here by the appveyor guys.

Appveyor, by default, only checks out the commit that triggered the build, not a branch so early on in the script I checkout the master branch to ensure we can push later.

Then I’ve created an oauth token to authorize the build agent with the repo and stored it in Appveyor, as a secure variable. This is then retreived as an environment variable and used to to push the updated file push back to the repo.

N.B Because of the way the git commands write out to stderr I use the start-process command to prevent these from registering as build failures. Also, depending on how you work with git and appveyor, you might not want to checkout the master branch and only build a specific commit, however, this simple approach works well for me at the moment.

Done

I now have a nice build that checks the DSC resource, publishes an update version to PSGallery and commits an updated version number in Github. You can see the build for yourself here and all the code involved, including the yaml and build script are here.

Ultimately it means I won’t be a bottleneck for the project, hopefully allowing more contributions more often and  making for a healthy OSS project.

image