The PowerShell Build Tools are a toolbox for build, test and deployment automation. The Build Tools combine XML configuration and PowerShell scripting in a new way to get the best of both worlds. NHunspell is a wrapper for the Open Office Spell Checker Hunspell. Although NHunspell is a small project, it has a rather complex build and deployment workflow due to its native assemblies. We want to make this a bit easier so we switched the NHunspell build process to our new PowerShell based Build Tools.
NHunspell Build and Deployment
These are the steps that should be performed during a NHunspell build:
- Version Update
Update all version strings in the solution to match the current build - Compile the 32Bit Native DLL
- Compile the 64Bit Native DLL
- Compile the NHunspell Assembly
- Check the Files
Check if all files are compiled and have the correct version resource - Run the Unit Tests
- Create Zip Files
- Create NuGet Packages
- Test Deploy the Packages
So these steps are automated using the PowerShell Build Tools.
PowerShell Build Tools in Action
In this video, we show how NHunspell is built from PowerShell, within Visual Studio and on a Jenkins Build Server. It also shows how the build configuration can be edited and debugged.
Watch directly on Youtube - Building the NHunspell Spell Checker with PowerShell Build Tools
Build Configuration
The PowerShell Build Tools use a XML configuration file with the default name BuildConfig.xml. Here are the most important parts from the NHunspell BuildConfig.xml:
XML Declaration
This XML declaration is as follows:
="1.0"="utf-8"
<BuildConfig xmlns="http://www.crawler-lib.net/build-tools"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.crawler-lib.net/build-tools
http://download.crawler-lib.net/BuildTools/BuildConfig.xsd?action=view">
It links to the current build tools schema definition and can be used to enable IntelliSense in Visual Studio.
Build Labeling
<Label>
<BuildRevisionTimestamp/>
</Label>
The Build is labeled with the Build/Revision Timestamp tool. It works the same way as assemblies are versioned when *.* is specified as build and revision numbers.
Credentials for the Build Steps
<Credentials>
<Plain>
NuGetFeed=http://buildserver:8050/nuget/Test
NuGetApiKey=b763316f-25c2-4d17-bf0a-1c22e071eb05
</Plain>
</Credentials>
The credentials section allows to specify credentials for use in the build steps later.
Solutions and Versions
<Solutions>
<Solution Name="NHunspell">
<Version>
<AppendLabel>1.2</AppendLabel>
</Version>
...
The PowerShell Build Tools are able to build a bunch of solutions during one build. The typical use case for this are solutions that need to have the same build label, but use different versioning. The versioning tool is specified for each solution and in this case, it appends simply the build label to a fully qualified version.
Build Sequences
<BuildSequences>
The build sequences are collections of build steps that can be executed to get to a certain stage in the build process. The PowerShell Build Tools use an incremental approach to get a build done. There is a special sequence called "Clear-Build
" that clears the current build and forces a completely new build.
New-Build Sequence
<BuildSequence Name="New-Build">
<Autover Path="..\HunspellWindows\HunspellWindows.sln" />
<Autover Path="NHunspell.sln" />
<MSBuild Path="..\HunspellWindows\HunspellWindows.sln"
Configuration="Release" Platform="x86" />
<MSBuild Path="..\HunspellWindows\HunspellWindows.sln"
Configuration="Release" Platform="x64" />
<MSBuild Path="NHunspell.sln"
Configuration="Release" Platform="Any CPU" />
<VerifyFile Path="UnitTests\bin\release\Hunspellx86.dll"
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx86.pdb"
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx64.dll"
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx64.pdb"
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\NHunspell.dll"
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\NHunspell.pdb"
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\UnitTests.exe"
FileVersion="true" ProductVersion="true" New="true"/>
</BuildSequence>
The NHunspell build uses the New-Build Sequence to patch the versions of all projects in the solutions with the Autover tool. After that, the native DLLs and NHunspell is compiled using MSBuild. Least it is checked if the generated files are new and if they have the correct version.
Test-Build Sequence
<BuildSequence Name="Test-Build"
Depends="New-Build" NewBuild="false">
<NUnit Path="UnitTests\bin\release\UnitTests.exe" />
<FxCop Path="UnitTests\bin\release\NHunspell.dll" />
</BuildSequence>
The Test-Build Sequence runs NUnit and FxCop to test NHunspell. The Test-Build sequence depends on the New-Build sequence. If the build is clear, the Build Tools will execute the New-Build sequence first. If there is a current build with a successful New-Build sequence, the Test-Build sequence will use the current build and perform the tests on the already available build results. This concept allows to modularize the steps and cuts down the time needed to develop a certain build sequence.
Complete-Build Sequence
<BuildSequence Name="Complete-Build"
Depends="Test-Build" NewBuild="false">
<Zip Path="UnitTests\bin\release\Hunspellx86.dll" Target="Hunspellx86.dll"
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx86.pdb" Target="Hunspellx86.pdb"
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx64.dll" Target="Hunspellx64.dll"
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx64.pdb" Target="Hunspellx64.pdb"
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\NHunspell.dll" Target="NHunspell.dll"
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\NHunspell.pdb" Target="NHunspell.pdb"
Output="NHunspell.$($context.PackageVersion).zip" />
<AppendText Output="NHunspell.$($context.PackageVersion).zip.info.xml">
<![CDATA[
</AppendText>
<NuSpecUpdate>
<NuSpec Path ="NHunspell.nuspec" />
</NuSpecUpdate>
<NuGetPack Path ="NHunspell.nuspec"/>
</BuildSequence>
The Complete-Build sequence depends on the Test-Build sequence, so the build can only be completed if successfully tested. In the Complete-Build
sequence, the Zip- and NuGet packages are created. As you can see, some string
values contain PowerShell code which is escaped with the dollar sign ($) as usual in PowerShell.
Publish-Build Sequence
<BuildSequence Name="Publish-Build"
Depends="Test-Build" NewBuild="false">
<NuGetPush Path ="NHunspell.$($context.PackageVersion).nupkg"
ApiKey="$($context.Credentials.NuGetApiKey)"
Feed="$($context.Credentials.NuGetFeed)"/>
</BuildSequence>
</BuildSequences>
</Solution>
</Solutions>
</BuildConfig>
The Publish-Build sequence performs a publish step on our internal test NuGet feed.