Over the past months I've been putting together a minimal library of Octopus Deploy Step templates and "Library" scripts to cover all our common deployment scenarios. one of these was a Step template to unzip a file to a specified location. It took just two parameters -- UnzipFolder (the folder to which to unzip the file), and FilePath (the full path to the file to be unzipped). For a while, everything seemed to work perfectly. Then we found that files were always getting unzipped to the wrong locations.
Now I know that Octopus generates a PSM1 module for Powershell scripts to be executed on a tentacle, so my immediate thought was that there was some kind of caching issue, and an "old" version of the script was getting executed, populated with stale parameters. But after restarting the tentacles, rebooting the Octopus server, and even creating fresh projects, the problem persisted.
An hour later I finally got to the root of the problem: parameters in a Step template WILL BE masked by objects with the same name which occur in a Variable set included in your project. What I'd actually done was create a variable called UNZIPFOLDER, and this was overriding the parameter in my Step template every time the Step template got invoked.
Now, I've raised this with Octopus, and I’m sure they’ll be fixing it soon. But I just want quickly to point out some of the implications this bug has for your Octopus projects.
1. This is a reversal of the normative variable scoping behaviour we expect to find in most programming languages, including Powershell. Our expectation is that we can override a global variable at local scope (for example, within a nested block of code), and expect to recover the value of our global variable when our local scope ends. That won't work here.
2. If you pull in random third-party Step templates, they may not function the way you expect, because they have parameters which happen to conflict with variables you've included in your project.
3. More importantly, if you start "refactoring" your variables in an Octopus Deploy project, you run the risk of breaking your Step templates in insidious and unexpected ways.
OK, so enough doom and gloom. That's the problem in a nutshell. Be aware of it. Now what can you do to get around it?
I suggested to Octopus that they consider scoping each instantiation of a Step template (ie. at deployment time) with the Step template's name, or better still a GUID. The first approach would work, because each Step template within an Octopus project needs to have a unique name (which isn't a design decision I'd endorse; I'll come back to that another time).
However, from a pragmatic point of view, it seems to me the best approach you can take in the interim is to adopt a Variable and Parameter naming convention, such that you will never have a Variable conflict with a Step template parameter. You could, for example, adopt some particular prefix for Step template parameters, and a different prefix (or no prefix) for Variables. Either that, or stop using Step templates, pull your scripts out of them and put them into a common Powershell library, then invoke these scripts directly.