Posey's Tips & Tricks

Best Practices for PowerShell Script Version Control, Part 1

Semantic versioning gives PowerShell script changes clear meaning so you can evolve scripts quickly without letting updates devolve into chaos.

As someone who works with PowerShell on a daily basis, I have accumulated a fairly large collection of scripts that I use for various purposes. These scripts tend to be anything but static. I am constantly adding new features and capabilities and addressing bugs or shortcomings. In doing so, I learned long ago that the only way to keep this rapid code evolution from devolving into chaos is to practice version control. As such, I wanted to share with you some best practices based on my own experiences.

The first best practice that I want to talk about is that version numbers shouldn't be arbitrary. I will admit that there was a time when my versioning practices consisted of little more than saying, "I've been using 1.x.x for a really long time. Maybe it's time to switch to version 2."

Since that time, I have adopted a practice called semantic versioning. It's easy to think of semantic versioning as being one of those things that only professional developers care about, but the practice actually works really well for PowerShell scripts.

The idea behind semantic versioning is that software versions are made up of three numbers, separated by periods. You might, for example, see an application with a version number such as 4.2.65. These numbers each mean something.

To illustrate the meaning of these numbers, let's forget about the numbers for a moment and express a version as X.Y.Z. The X position is what is known as the major version number. The Y position pertains to the minor version number, and the Z position is the patch number. Let's take a moment and unpack what all of this means, starting with the patch number.

The patch number is the number that typically changes the most frequently. In my own environment, I increase the patch number any time that I fix a bug, make a correction to a script's logic, or make a change that is going to improve error handling or optimize performance. The caveat, however, is that these changes do not change the way that the script looks or behaves, aside from any visible changes that might occur as a result of fixing a bug.

Minor version updates are typically feature updates. The key however, is that the script still works the same way that it always did and the changes do not break anything.

Admittedly, this is delving a bit into developer territory, so let's bring it back to PowerShell. Suppose for a moment that you have a PowerShell script that includes a function that is designed to accept a single parameter. Now, let's suppose that you decide to modify the function so that it can accept an additional parameter. The key to figuring out whether the change warrants a major or minor version update is functionality. If you can still use a single parameter, even though the function now allows you to use two parameters, then the change only warrants a minor version number. The key is that the function is still backward compatible. In other words, it's a major version if you have removed or renamed the original supported parameter or made it so that the function cannot work without two parameters. If on the other hand, you can still interact with the function in the same way that you always have in the past and the function still behaves in the same way that it always has, then the change is considered to be minor. It's only considered to be a major change (in this example) if someone is going to be forced to change the way that they call the function.

Even though I have been focusing on functions in this particular example, the same basic concept applies to scripts as a whole. After all, it is extremely common for one PowerShell script to call another. If a script has been modified in a way that would break another script that depends on it, that constitutes a major version change.

Incidentally, major version numbers don't always start with 1. Prerelease scripts almost always use a version number that starts with zero. With such scripts, you can use the minor version number to get a feel for the state of the script. A low minor version number represents an early prototype, while a high minor version number (such as 8 or 9) means that the script is nearly ready for production use, but not quite. When the code is eventually given a version number of 1.0.0, that version number is an indication to anyone who might use the script that the script is stable and ready for production use.

A general rule of thumb is that if a script's patch number increases, then the change only serves to fix bugs and so the script should be safe to deploy. If the minor version number changes then there are probably some new options contained in the script, so it's a good idea to read the release notes. A new major version number indicates that substantial changes have been made and that the script needs to be thoroughly tested before using it in production.

So now that I have discussed version numbers, I want to talk about some of my other versioning best practices in Part 2.

About the Author

Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.

Featured

comments powered by Disqus

Subscribe on YouTube