Octopus deploy – Script Steps sourced from a package

In the latest version of Octopus deploy you can now choose to run script steps where the files exist in a package. This might sound like a minor change but opens up some very neat options. You can read more on the details of the change in https://octopus.com/blog/octopus-deploy-3.3#ScriptsInPackages. Note at the time of writing this is only available in the beta of 3.3 (https://octopus.com/downloads/3.3.0-beta0001)

Ok, so why is this such a good thing?
Step templates are great – there is even a large library of pre-existing templates to download (https://library.octopusdeploy.com/#!/listing). If you’ve not used them before, step templates allow additional scripts to run during your deployment.

Examples could be: post to slack, create certain folders, delete given files etc. Basically anything you can achieve with powershell can be done in step templates.

Lets just stick with step templates then?
If you’ve gone through the process of setting up several deployments with Octopus and find you want to replicate the same functionality across several projects or installs then you need to re-create all the step template configurations each time. It’s not the slowest process but the idea below helps streamline things.

Now that you can run scripts from a package, why not source control the steps you want to run? One key advantage is that you can then see things like history of all the deployment steps.

What needs setting up?
You need to be running version 3.3 or higher of Octopus – see above for the link.

I’ve been using a simple test deployment of an out the box MVC project along with a new project specifically for the scripts.:
solution setup

In Octopus this has 2 steps:

The first is a vanilla website deployment of ‘WebApplication1’. The second the startup scripts:
script step

Note the package id. The idea behind using a separate projects is that the powershell scripts never need to exist in the website project.

The startup script project
solution setup

I chose to use a class library for the simple reason that I could include a reference to Octopack and hence building the output nuget file was trivial.

The nuspec file is important as it tells the packaging to include all powershell files:

Packages simply contains a reference to Octopack:

And finally the scripts:

And the more important one, Startup.ps1

It’s worth noting this should be considered a POC of the approach. The next steps would be to split the scripts up into more meaningful units, remove hello world and update the nuspec with more valid information.

If you struggle with accessing the Octopus Parameters you require, the script in helloworld allows you to dump out all parameters and their values. In the startup script the parameter: $OctopusParameters[‘Octopus.Action[Deploy website].Output.Package.InstallationDirectoryPath’] depends on the name of your deployment in step 1 of your deployment process (Deploy website)

How to write a basic powershell module that includes multiple scripts

As part of a recent project I’ve needed to work closely with some of the Azure api’s. You can achieve some really cool things pretty quickly once you’ve learnt a few basics.

A good tip I picked up was that if you can implement something in .net/c# chance are you can replicate in PowerShell. If there isn’t a specific PowerShell module/api available you can call into the .net dll. This can be loaded via e.g.:

In order to structure your various functions the recommended approach is to use modules. A quick google will bring up more details. What I couldn’t find was how to setup a basic module that includes multiple scripts.

When you create new modules they can live in a couple places, $env:PSModulePath will show you this.

A module structure is pretty basic, you need a psm1 file (and psd1 – see https://www.simple-talk.com/sysadmin/powershell/an-introduction-to-powershell-modules/)
ps structure
Script.ps1 is basic, it contains a simple function:

Custom.psm1 then looks to load all the scripts you have. Note, make sure the folder name matches the psm1 name:

These files need to live in one of your module folders e.g. %UserProfile%\Documents\WindowsPowerShell\Modules

It’s then a case of installing your module:
Check what modules are available to install via: Get-Module -ListAvailable
And install the one you want via: Import-Module Custom. Note, Custom is the name of the folders and psm1 file.

Provided it’s all gone to plan you should now be able to call HiThere from a ps prompt

Debugging Azure web-role startup tasks

One feature Azure offers for getting your  boxes configured is the notion of startup tasks – I won’t go into too much detail here as there is lots available online e.g. https://msdn.microsoft.com/en-us/library/azure/hh180155.aspx

As part of setting these up I thought I’d share a few tips / gotchas that caught me out when running powershell from the cmd tasks.

My solution setup was:

  • Site root
    • StartupScripts
      • Script.cmd
      • Script.ps1

So then I’d reference in the task:

 <Task commandLine=”StartupScripts\script.cmd” executionContext=”elevated” taskType=”simple” />

Nothing rocket science so far! So, why didn’t the script work? I could jump on the box and run the cmd and it would be fine.

How to debug the process?
I found the most useful way was to add markers from the cmd and the ps1. The cmd file looked like:

Note, the .\startupScripts part of the ps1 path is v important!

Then the powershell:

Note, if you try to write to log.txt you will get process locked exceptions as the cmd holds locks on the file.
There are all sorts of techniques for writing to a file, this example uses a StreamWriter. Hit up google for different examples.

Running sql queries from Powershell

Have you ever needed to test out the performance of sets of sql queries?

Recently we had some performance issues on a live infrastructure which needed diagnosing. Getting code released was slightly tricky so instead we concocted some scripts to allow us to run sql queries from Powershell. The advantage of these, we could run from different boxes in the farm to try and isolate where the issues arrived.

The key settings in this setup are:

The connection strings are much like your standard application connection strings.

To then run in bulk you can use the script shown below. Note, adjust the specific queries you want to execute: