One of the goals of build automation is to create a robust and reliable process that can be depended upon. To achieve this, our build script needs to be smart, transparent and maintainable.
- Smart because we don’t want our builds to break when really simple things change.
- Transparent because we need to be able to see what the script did.
- Maintainable because we want anyone on the team to be able to maintain the build.
Currently, the build script we wrote last week expects that
msbuild will be available on the PATH. If it isn’t available, the error message isn’t really that helpful:
It’s not a terrible error message - at least it tells you the name of the program that couldn’t be found.
But, when our build stops working, we don’t want people to be guessing about why - and having to find the right error message in the midst of all the other output is a pain.
Let’s add a new task to our build script, one that finds
msbuild for us and generates a good diagnostic message if it couldn’t be found.
There are a few interesting things going on here.
Note how we use
resolve-path to find MSBuild without specifying the entire path. The wildcards (
*) in the path get expanded appropriately, making the script somewhat adaptable if a different edition of Visual Studio is installed on the machine.
If the search for MSBuild fails, we throw an error which gets reported on the console:
If the search works, we get a message telling us exactly which version has been found - useful if we start finding that builds on different machines are delivering different results.
$script scope when we assign to
$msBuildExe is necessary because each Psake task runs in a separate scope; without the
$script modifier, our assignment would be abandoned as soon as the task completed.
To hook this into our original task, we make a couple of minor changes:
-Depends option tells Psake that the
Compile.Assembly task cannot start until the
Requires.MSBuild task has finished. We also needed to modify our command line to use
$msbuildExe when running the build.
We’ve made our build smarter because now it finds
msbuild for itself; it’s not dependent on it being on the PATH. We’ve made our build more transparent because it now tells us which version of
msbuild is being used.
We’ve ensured our task is maintainable by breaking the logic for finding
msbuild out into it’s own well named task.
What else can we do to improve the robustness of our build script?