Der ReleaseBuild
Der ReleaseBuild wird bei Bedarf manuell ausgeführt. Er wird dann benötigt, wenn eine neue Version des Projektes veröffentlicht werden soll, oder eine Iteration oder Projektphase abgeschlossen ist.Der ReleaseBuild kopiert zusätzlich zum ContinuousBuild alle Assemblies ins Deploy Verzeichnis, erstellt beim Vorhandensein von WiX Projekten die MSI basierten Installer, zählt die Build Nummer hoch und versioniert den Source Code im Repository mit der Version des Builds.
Je nachdem, ob Subversion oder SourceSafe als Repository verwendet wird, unterscheidet sich die Vorlage in den Targets, welche das Repository aktualisieren. Die Unterschiede werden jeweils erläutert.
Als erstes werden die Targets für die Erstellung der MSI Setups aus den WiX Projekten und das Kopieren aller Lieferobjekte ins Deploy Verzeichnis angeschaut.
<!-- Compile the WiX projects -->
<Target Name="BuildWix" DependsOnTargets="BuildCode">
<Message Text="Building the WiX projects..." Importance="high" />
<Message Text="BuildTargets: $(BuildTargets)" Importance="high" />
<Message Text="WixOutputPath: $(WixOutputPath)" Importance="high" />
<!-- Build the assemblies -->
<MSBuild Projects="@(WixProjects)"
Targets="$(BuildTargets)"
Properties="Configuration=$(Configuration);Platform=$(Platform);OutputPath=$(WixOutputPath);">
<Output TaskParameter="TargetOutputs"
ItemName="CompiledMsiFiles"/>
</MSBuild>
</Target>
<!--
Deploy into the according version vX.X.X.X folder. Add any other files than *.dll or *.exe
or change the deploy directory structure here.
If you add any sort of installer or package, you might want to create that first
and copy it to the deploy folder.
-->
<Target Name="Deploy" DependsOnTargets="GetBuildNumber;GetRevisionNumber;BuildWix">
<!-- Create a property with the latest version folder name -->
<CreateProperty Value="v$(Major).$(Minor).$(BuildNumber).$(RevisionNumber)">
<Output TaskParameter="Value" PropertyName="DeployDestinationFolder" />
</CreateProperty>
<Copy SourceFiles="@(CodeAssemblies->'%(FullPath)')"
DestinationFolder="$(DeployFolder)\$(DeployDestinationFolder)" />
<Copy SourceFiles="@(CompiledMsiFiles->'%(FullPath)')"
DestinationFolder="$(DeployFolder)\$(DeployDestinationFolder)\setup" />
</Target>
Wenn das Projekt WiX basierte Installer enthält werden, diese im Target BuildWix erstellt. Dazu wird lediglich ein weiterer MSBuild Task aufgerufen, welchem jedes WiX Projektfile übergeben wird. Für das anschliessende Kopieren der Setups ins Deploy Verzeichnis werden die erstellten MSI Dateien im Item CompliedMsiFiles gespeichert.
Das Target Deploy erstellt im gleichnamigen Verzeichnis anhand der Versionsnummer einen neuen Folder. In diesen werden mit einem einfachen Copy Task alle vorher erstellten Assemblies und Installer kopiert.
Während des Builds sind nun die Dateien BuildNumber.txt und AssemblyInfoCommon.cs verändert worden. Diese Änderungen sollen nun im Repository gespeichert werden. Zusätzlich soll dieser ReleaseBuild auch zu einem späteren Zeitpunkt wiederhergestellt werden können. Unter Subversion wird deshalb anschliessend ein Tag, in Visual SourceSafe ein Label erstellt.
Standardmässig ist in MSBuild keine Unterstützung für Subversion und, was etwas mehr erstaunt, für SourceSafe enthalten. Die MSBuild Community Tasks schliessen diese Lücke und stellen für beide (und diverse andere) System geeignete Tasks bereit, mit welchen sich alle benötigten Repository Operationen automatisieren lassen.
Das Target Deploy erstellt im gleichnamigen Verzeichnis anhand der Versionsnummer einen neuen Folder. In diesen werden mit einem einfachen Copy Task alle vorher erstellten Assemblies und Installer kopiert.
Während des Builds sind nun die Dateien BuildNumber.txt und AssemblyInfoCommon.cs verändert worden. Diese Änderungen sollen nun im Repository gespeichert werden. Zusätzlich soll dieser ReleaseBuild auch zu einem späteren Zeitpunkt wiederhergestellt werden können. Unter Subversion wird deshalb anschliessend ein Tag, in Visual SourceSafe ein Label erstellt.
Standardmässig ist in MSBuild keine Unterstützung für Subversion und, was etwas mehr erstaunt, für SourceSafe enthalten. Die MSBuild Community Tasks schliessen diese Lücke und stellen für beide (und diverse andere) System geeignete Tasks bereit, mit welchen sich alle benötigten Repository Operationen automatisieren lassen.
Subversion
Die folgenden Targets führen ein Commit der geänderten Dateien durch und Erstellen ein Tag im Repository.
<!-- Subversion Targets -->
<Target Name="SvnVerify">
<Error Text="The Subversion credentials are not specified."
Condition=" '$(SvnUsername)' == '' Or '$(SvnPassword)' == '' " />
</Target>
<!-- Commit the changes (BuildNumber.txt etc.) to the repository. -->
<Target Name="SvnCommitChanges"
DependsOnTargets="SvnVerify">
<CreateProperty Value="Automatic commit by $(ComputerName) as part of build $(BuildNumber)"
Condition=" '$(SvnMessage)' == '' ">
<Output TaskParameter="Value" PropertyName="SvnMessage" />
</CreateProperty>
<!-- Commit to the repository -->
<SvnCommit Targets="."
Username="$(SvnUserName)"
Password="$(SvnPassword)"
Message="$(SvnMessage)" />
</Target>
<!-- Tag the repository -->
<Target Name="SvnTagRepository"
DependsOnTargets="SvnVerify">
<!-- Create a property holding the SVN tag -->
<CreateProperty Condition=" '$(SvnTag)' == '' And '$(AssemblyVersion)' != '' "
Value="Build-$(AssemblyVersion)">
<Output TaskParameter="Value" PropertyName="SvnTag"/>
</CreateProperty>
<!-- Create a property holding the SVN tag message -->
<CreateProperty Condition=" '$(SvnTag)' == '' And '$(AssemblyVersion)' != '' "
Value="Automatic tag by $(ComputerName) as part of build $(BuildNumber)">
<Output TaskParameter="Value" PropertyName="SvnMessage"/>
</CreateProperty>
<!-- Fail the build if the tag has not been specified -->
<Error Text="SvnTag property has not been specified" Condition=" '$(SvnTag)' == '' "/>
<!-- Tag the repository -->
<SvnCopy SourcePath="$(SvnTrunkFolder)"
DestinationPath="$(SvnTagsFolder)/$(SvnTag)"
Message="$(SvnMessage)"
Username="$(SvnUserName)"
Password="$(SvnPassword)" />
<Message Text="Tag created at $(SvnTagsFolder)/$(SvnTag)" Importance="high"/>
</Target>
Das Target SvnVerify überprüft, ob ein Benutzer und ein Passwort für den Zugriff auf das Subversion Repository ans Build Skript übergeben worden ist. Sollten diese Angaben fehlen, wird ein Fehler ausglöst, der Build gilt somit als fehlgeschlagen. Der Benutzer und das Passwort werden in der CruiseControl.NET Konfiguration definiert.
Die Änderungen der Dateien werden im Target SvnCommitChanges im Repository eingespielt, anschliessend wird im Target SvnTagRepository ein Tag erstellt.
Die Änderungen der Dateien werden im Target SvnCommitChanges im Repository eingespielt, anschliessend wird im Target SvnTagRepository ein Tag erstellt.
SourceSafe
Die folgenden Targets sind nur in der Vorlage für Visual SourceSafe enthalten und führen ein Checkin der geänderten Dateien durch und Erstellen ein Label in der VSS Datenbank.
<!-- VSS Targets -->
<Target Name="VssVerify" Condition=" '$(CCNetProject)' != '' " >
<Error Text="The SourceSafe credentials are not specified."
Condition=" '$(VssUsername)' == '' Or '$(VssPassword)' == '' " />
</Target>
<!-- Checkin the changes (BuildNumber.txt, AssemblyInfoCommon.cs) to the repository. -->
<Target Name="VssCheckinChanges"
DependsOnTargets="VssVerify">
<CreateProperty Value="Automatic checkin by $(ComputerName) as part of build $(BuildNumber)"
Condition=" '$(VssCheckinComment)' == '' ">
<Output TaskParameter="Value" PropertyName="VssCheckinComment" />
</CreateProperty>
<!-- Commit to the repository -->
<VssCheckin UserName="$(VssUsername)"
Password="$(VssPassword)"
LocalPath="$(MSBuildProjectDirectory)\BuildNumber.txt"
Recursive="False"
DatabasePath="$(VssDbDir)\srcsafe.ini"
Path="$(VssProjectPath)/BuildNumber.txt"
Comment="$(VssCheckinComment)"
/>
<VssCheckin UserName="$(VssUsername)"
Password="$(VssPassword)"
LocalPath="$(MSBuildProjectDirectory)\src\AssemblyInfoCommon.cs"
Recursive="False"
DatabasePath="$(VssDbDir)\srcsafe.ini"
Path="$(VssProjectPath)/src/AssemblyInfoCommon.cs"
Comment="$(VssCheckinComment)"
/>
</Target>
<!-- Label the repository -->
<Target Name="VssLabelRepository"
DependsOnTargets="VssVerify">
<!-- Create a property holding the VSS label -->
<CreateProperty Condition=" '$(VssLabel)' == '' And '$(AssemblyVersion)' != '' "
Value="Build-$(AssemblyVersion)">
<Output TaskParameter="Value" PropertyName="VssLabel"/>
</CreateProperty>
<!-- Create a property holding the VSS label comment -->
<CreateProperty Condition=" '$(AssemblyVersion)' != '' "
Value="Automatic label by $(ComputerName) as part of build $(BuildNumber)">
<Output TaskParameter="Value" PropertyName="VssLabelComment"/>
</CreateProperty>
<!-- Fail the build if the label has not been specified -->
<Error Text="VssLabel property has not been specified" Condition=" '$(VssLabel)' == '' "/>
<!-- Label the repository recursively -->
<VssLabel UserName="$(VssUsername)"
Password="$(VssPassword)"
DatabasePath="$(VssDbDir)\srcsafe.ini"
Path="$(VssProjectPath)"
Label="$(VssLabel)"
Comment="$(VssLabelComment)" />
<Message Text="VSS Label created: $(VssLabel)" Importance="high"/>
</Target>
Das Target VssVerify überprüft, ob ein Benutzer und ein Passwort für den Zugriff auf die SourceSafe Datenbank an das Build Skript übergeben worden ist. Sollten diese Angaben fehlen, wird ein Fehler ausglöst, der Build gilt somit als fehlgeschlagen. Der Benutzer und das Passwort werden in der CruiseControl.NET Konfiguration definiert.
Die Änderungen der Dateien werden im Target VssCheckinChanges im Repository eingespielt, anschliessend wird im Target VssLabelRepository ein Label erstellt.
Wenn der ReleaseBuild erfolgreich war, wird ebenfalls ein Email ausgelöst, welches einen Downloadlink auf die neue Version beinhaltet.
Die folgenden Targets erstellen und senden diese Emails.
Die Änderungen der Dateien werden im Target VssCheckinChanges im Repository eingespielt, anschliessend wird im Target VssLabelRepository ein Label erstellt.
Build Notifikation
Beim Fehlschlagen eines Unit Tests (ContinuousBuild und ReleaseBuild) wird ein EMail ausgelöst, welches alle Entwickler darüber informiert, dass der Build nicht erfolgreich war.Wenn der ReleaseBuild erfolgreich war, wird ebenfalls ein Email ausgelöst, welches einen Downloadlink auf die neue Version beinhaltet.
Die folgenden Targets erstellen und senden diese Emails.
<!-- Create the build mail text -->
<Target Name="CreateBuildMail" DependsOnTargets="GetBuildNumber;GetRevisionNumber">
<!-- Create the tokens for the InstallBuildEmail template -->
<CreateItem Include="AppVersion" AdditionalMetadata="ReplacementValue=$(AssemblyVersion)">
<Output TaskParameter="Include" ItemName="EmailTokens" />
</CreateItem>
<CreateItem Include="DeployLocation" AdditionalMetadata="ReplacementValue=$(DeployShare)\$(DeployDestinationFolder)">
<Output TaskParameter="Include" ItemName="EmailTokens" />
</CreateItem>
<!-- Create the InstallBuildEmail by replacing the tokens in the template file -->
<TemplateFile Template="$(InstallBuildEmailTemplate)"
OutputFilename="$(InstallBuildEmailFile)"
Tokens="@(EmailTokens)" />
<ReadLinesFromFile File="$(InstallBuildEmailFile)">
<Output TaskParameter="Lines" ItemName="EmailBody"/>
</ReadLinesFromFile>
</Target>
<!-- Send an email to all project members in case a unit test failed -->
<Target Name="SendErrorMail">
<!-- Send e-mail notification of the failed build -->
<Mail SmtpServer="$(SmtpServer)"
To="@(Developers)"
Priority="High"
IsBodyHtml="true"
From="$(BuildMasterMail)"
Subject="$(ProjectName) Build $(AssemblyVersion) failed."
Body="$(ProjectName) Build $(AssemblyVersion) failed. <br/>
<a href='http://$(BuildServer)/ccnet/server/local/project/$(ProjectName)Continuous/ViewLatestBuildReport.aspx'>Build Report</a>"
ContinueOnError="true"/>
</Target>
<!-- Send an email to all project members -->
<Target Name="SendBuildMail"
DependsOnTargets="CreateBuildMail">
<!-- Send e-mail notification of the new build -->
<Mail SmtpServer="$(SmtpServer)"
To="@(Developers)"
Priority="High"
IsBodyHtml="true"
From="$(BuildMasterMail)"
Subject="$(ProjectName) Build $(AssemblyVersion) has been built."
Body="@(EmailBody, '')"
ContinueOnError="true"/>
</Target>
Das Target CreateBuildMail erstellt den Mail Text, mit welchem über den neuen ReleaseBuild informiert werden soll. Im Verzeichnis Install befindet sich eine HTML Vorlage, welche Platzhalter enthält, die durch den TemplateFile Task ersetzt werden. Anschliessend wird der generierte Inhalt in das Item EmailBody eingelesen.
Das ReleaseBuild Email wird schlussendlich im Target SendBuildMail verschickt.
Wenn ein Unit Test fehlgeschlagen ist, wird das Target SendErrorMail aufgerufen. Dieses schickt ein Email an alle Entwickler, um diese zu informieren.
Mit all diesen Targets ist es nun möglich die Build Umgebung zu konfigurieren. Detaillierte Anweisungen dazu sind im Abschnitt CruiseControl.NET Konfiguration enthalten.
Das ReleaseBuild Email wird schlussendlich im Target SendBuildMail verschickt.
Wenn ein Unit Test fehlgeschlagen ist, wird das Target SendErrorMail aufgerufen. Dieses schickt ein Email an alle Entwickler, um diese zu informieren.
Mit all diesen Targets ist es nun möglich die Build Umgebung zu konfigurieren. Detaillierte Anweisungen dazu sind im Abschnitt CruiseControl.NET Konfiguration enthalten.