Skip to content

Portable Build Scripts

Roman Kuzmin edited this page Jan 4, 2013 · 9 revisions

It is possible and even expected in some cases to have a copy of Invoke-Build tools kept together with build scripts and make the build tool set portable, only assuming PowerShell is installed and configured for invoking scripts. Invoke-Build.ps1 is often enough, other tools and files are optional.

Another reason to keep a copy of Invoke-Build with build scripts is use of incompatible build engine versions. Existing build scripts do not have to be upgraded for a newer version, they may continue to use old tools.

Build scripts which do not call Invoke-Build.ps1 and Invoke-Builds.ps1 are already portable. Otherwise there are some challenges:

  • How to invoke Invoke-Build.ps1 from tasks, that is, call it nested?
  • How to invoke parallel builds by Invoke-Builds.ps1 from tasks?
  • How to avoid accidental calls to incompatible tools in the path?

These challenges are resolved with the special aliases defined by the engine:

  • Invoke-Build is a self-alias of the currently running script Invoke-Build.ps1
  • Invoke-Builds is an alias of the script Invoke-Builds.ps1 in the same directory.

Portable build scripts follow one simple rule. They invoke other builds by aliases, not by script names with extensions or paths. With file extensions or paths Invoke-Build.ps1 and Invoke-Builds.ps1 are invoked only from command lines or standard PowerShell scripts, not build scripts.

Example

The task Test in .build.ps1 simply dispatches the call to other scripts:

$TestScripts = ('SmokeTest.build.ps1', 'MoreTests.build.ps1', ...)

task Test {
    foreach($_ in $TestScripts) {
        Invoke-Build Test $_
    }
}

Note that the script uses the alias Invoke-Build for building other scripts. But the script itself is invoked differently from command lines. For example, if Invoke-Build.ps1 is in the same directory then it is called by its relative path:

./Invoke-Build.ps1 Test .build.ps1

Or, if Invoke-Build.ps1 is kept separately in a known directory then it is called using its full path:

C:/Scripts/InvokeBuild/Invoke-Build.ps1 Test .build.ps1

Or, if the directory is defined by an environment variable:

& $env:InvokeBuild/Invoke-Build.ps1 Test .build.ps1

As far as the example build script uses the alias Invoke-Build then nested calls work fine even if the build engine is not in the path. And if there is yet another copy of Invoke-Build.ps1 in the path, normally a newer possibly not compatible version, then it is not called.