Octopus Deploy has had two different ways to execute PowerShell scripts. Initially, we hosted PowerShell inside an AppDomain and invoked a pipeline. That approach had problems, so now we simply call PowerShell.exe over the script and pipe the results.
One problem I hit when I changed our approach is the way PowerShell uses return codes. I assumed (wrongly) that if a script ran successfully, 0 would be returned, and if it failed (an exception, invalid syntax, etc.) the code would be non-zero.
So here’s a test; create this file in PowerShell:
# Call a command that doesn't exist
rubbish
Now, run it and print the return code it returns:
Now, try this script:
# Parser error
!
Another:
# Invalid argument
New-Item -Dwarf Sneezy
Obviously, exit code 0 in PowerShell can signify anything from “the script ran perfectly” to “your script is so utterly broken that PowerShell will be uninstalled”. One might argue that this is the correct behavior, because PowerShell did its job successfully (running a script), but that the script was incorrect, and that’s not PowerShell’s fault. Personally, I disagree with that approach. It would be like the C# compiler returning exit code 0 for code that doesn’t compile, because it’s not the compilers fault that the code is bad.
So, I couldn’t rely on exit codes alone to tell Octopus that a script failed.
However, all of these kinds of errors do write to the stderr stream, which is good, so I figured, if the script is writing to stderr
, there’s some kind of problem with the script, and we can use a write to stderr
as a signal to fail the script. That’s what I did in Octopus 1.4.
But this didn't work so well in practice, it turns out people use stderr
a lot for things that they don’t want to fail the deployment. So I got a lot of bug reports about scripts that ran “OK” but were being treated as fails.
Now, I don’t do anything with the return code (oh, except I do set the PowerShell exit code if $LastExitCode
is non-zero). It’s up to you to check for errors and return an appropriate exit code when your script runs. PowerShell makes it really easy to do that.
Writes to stderr
will result in a warning in your deployment log, however. And you can use the special Octopus variable OctopusTreatWarningsAsErrors
to have Octopus fail the deployment if there’s a warning. So this is a way you can have Octopus fail when stderr
is written even if PowerShell exited with code 0.
Learn more
- PowerShell and IIS: 20 Practical Examples
- Documentation: Custom Scripts
- Documentation: Running an Azure PowerShell script step
- Browse our Community Step Template library with hundreds of sample scripts