Our first day of developement is all about getting project ready
for the agile developement process. We don't want to worry about
packing, file manifests or doing daily builds the next 24 days, so
the first thing to do on this project is getting the infrastructure
setup.
This will require:
- Source Code repository
- A build server
- A clean project structure containing all files
- A package manifest for installing the package on umbraco
- A nant script for putting the package together and automating
manifests, zipping etc
- Som misc utillities for handling files in the package
Source code
Blog 4 umbraco is already on codeplex, so we will keep it there
and modify the current project to fit our needs, source and issue
tracker can be found on:
http://www.codeplex.com/blog4umbraco
Build server
We already use TeamCity for our Contour, Courier and Concierge
build processes, it's easy to setup, has a fantastic UI and works
fantasticly with nant and subversion, cannot recommend this enough.
As there is alreay enough documentation out there on how to setup
Team City, I won't spend more time on this, but it's awesome, your
build process just works and you don't have to worry about
anything. As we use Nant for building the code we can also test the
entire build process locally, by running the nant scripts on the
local developement machine.
Get TeamCity here: http://www.jetbrains.com/teamcity/
Project Structure
We put everything in our visual studio project to ensure it can
build anywhere, so it will contain our nant script and package
manifest files for easy editing. For the project files themselves
we've setup this simple structure:
- Solution items
contains nant script, package manifes and utillities
- Css
All css files for the presentation
- EventHandlers
Classes that hook into the eventmodel
- Images
images for the presentation
- Library
The Blog xslt extension
- Scripts
javascript files
- Templates
Master template files
- UserControls
usercontrols for macros
- Xslt
xslt files for macros
Everything is now in source control so our build server can
fetch it every night and put together a nice package and hotfix
Package Manifest
The package manifest is the part of the project that tells
umbraco how the different items should be installed it contains
refences to all files, templates, macros, css etc. Normally package
files are created in the umbraco backend by using the package
located in the developer section. However, we need to have the
package file updated every night, and don't want to spend time on
this. So instead we will generate a very basic package manifest,
using the umbraco packager, which includes all document types,
template references and other items that are unlikely to change.
This basic package manifest will then be updated on every build to
keep it uptodate.
For this project we installed the current blog package and then
generated a new package containing all templates, document types,
stylessheets, macros etc. and added its manifest to the visual
studio solution.
Nant scripting
Nant is a automated build tool, which performs tasks in a build
script (wikipedia).
But it does so much more then building source code. In this project
I've setup nant to perform the following tasks (so I don't have
to)
- Build the source code
- Move files from the project into a package folder
- Modify the package.xml manifest with the list of current
files
- Add template markup to the package manifest from the template
files in the project
- Add stylesheets to the package manifest
- update the version number
- Zip the files as a package with a manifest
- Zip files as a hotfix to make it easy to update current
installations
- publish the files on nightly.umbraco.org
- Clean up
I've setup a nant project a couple of times now, and making nant
perform the above tasks took about 40 minuts to do. So how do you
setup Nant to do these things, download the source from codeplex
and view the nant.build file and go through the below chapters:
You need to have nant installed on your developement machine to
be able to use nant. It can be downloaded and installed from here:
http://nant.sourceforge.net/release/0.85/help/introduction/installation.html
To run the nant script, open cmd.exe, browse to the blog4umbraco
directory and write the command "nant" hit enter and it will
execute the .build file.
Nant script structure
The script is divided into different targets (<target>
elements)
- Compile
- Movefiles
- Manifest
- Zip
- Publish
These targets handle a different part of the process. You can
execute all targets by call the command "nant" or just some of them
by calling the comman "nant <name of target>" (ex: "nant
manifest"). Each target depends on another target which ensures
that everything is done in the right order.
Using nant to build your project
The first thing we need to do is compiling the source code. We
use the Msbuild.exe which is included in the .net framework.
msbuild is alot more picky about building visual solutions and
forces you to clean up missing files, wrong page declarations etc.
To make nant perform the build we call the msbuild.exe file
directly and tell it to build out solution:
<exec program="${msbuild.app}"
basedir="${root.dir}">
<arg value="UmLaut.Umb.Blog.sln"
/>
<arg
value="/p:Configuration=Debug"/>
<arg
value="/p:Platform="Any CPU""/>
</exec>
Adding template markup to the package manifest
We keep our templates as files in the project, but to install
them, we need to move the markup to the package manifest, this is
done by executing a nant task called loadfile and then xmlpoke:
<loadfile file="${core.dir}\templates\Blog.master"
property="blog.master" />
<xmlpoke file="${zip.dir}\package.xml"
xpath="/umbPackage/Templates/Template [Alias = 'Blog']/Design"
value="<![CDATA[${blog.master}]]>" />
We load the template file into a property, and then inject the
contents of that file into the package manifest. The xpath tells
xmlpoke where to place the value ${blog.master} which is the
contents of the file. We use the same technique for all the
templates and for the stylesheets as well.
Gathering files for the package and zipping them
For our package we need to gather all the files umbraco needs
for the installation and tell umbraco what path to place them on.
For this we create a temporary folder and copy the needed files. We
place them in the right structure as well. We use simple nant tasks
to copy these files and make new directories
<!-- Images -->
<mkdir dir="${package.dir}\images"
/>
<copy todir="${package.dir}\images"
includeemptydirs="true" flatten="false" failonerror="false"
overwrite="true">
<fileset
basedir="${core.dir}\images">
<include name="*.*"
/>
</fileset>
</copy>
<!-- Usercontrols -->
<mkdir
dir="${package.dir}\usercontrols\${dist.name}" />
<copy
todir="${package.dir}\usercontrols\${dist.name}"
includeemptydirs="true" flatten="false" failonerror="false"
overwrite="true">
<fileset
basedir="${core.dir}\usercontrols">
<include
name="*.ascx" />
</fileset>
</copy>
When we have the files collected in the folder, we execute a
small utillity which registers all files in the package.xml
manifest and moves them to the folder they will be zipped in. The
current package format requires that all files are located in the
root of the zipped folder so we also rename all files to a guid to
ensure that nothing is overwritten. The utillity
"AddFilesTopackages.exe" takes care of this as well (included in
the blog 4 umbraco project)
<!-- here we will append files in the
package directory to the package file-->
<!-- arguments: package.xml manifest, folder
with files in correct structure, folder to send to for
zipping-->
<exec
program="${root.dir}\AddFilesToPackage.exe">
<arg
value="${package.dir}\package.xml" />
<arg value="${package.dir}"
/>
<arg value="${zip.dir}"
/>
</exec>
Finally we will zip everything into 2 packages, one is the
installable umbraco package with all files located in the root of
the folder, the other a hotfix release with all files named and
located correctly so it's easy to xcopy to an existing
installation.
<!-- Zip everything -->
<zip zipfile="${root.dir}\package.zip"
includeemptydirs="true" >
<fileset
basedir="${zip.dir}">
<include name="*"
/>
<include name="**/*"
/>
</fileset>
</zip>
<!-- Zip hotfix -->
<zip zipfile="${root.dir}\hotfix.zip"
includeemptydirs="true" >
<fileset
basedir="${package.dir}">
<include name="*"
/>
<include name="**/*"
/>
<exclude
name="package.xml" />
</fileset>
</zip>
These are all small snippets of the build script. I recommend
you open up the nant.build file and investegate it further, it is a
fantastic tool for automating anything and for handling the tedious
task of maintaining a package manifest it is a real time-saver.
Moving forward
With nant, codeplex and teamcity in place, we are now ready to
start adding features, we don't have to worry about spending time
on releasing packages and can move forward much faster.
Nightly builds will be available on http://nightly.umbraco.org/Blog4Umbraco/
both as installable package and a hotfix.
The source code is on codeplex: http://blog4umbraco.codeplex.com/
where you can also add suggestions, snippets and post bugs
Tutorials on nant can be found here
http://nant.sourceforge.net/release/latest/help/introduction/
and here http://blog.jpboodhoo.com/NAntStarterSeries.aspx
for those who want to learn more.
End of the first chapter of the umbraco christmas calendar! I
promise the next chapters will not be this long or filled with nant
tasks xml.