Today at work I had a need to extract some code that we had been “sharing” between a few projects via manual C&P in the projects. Obviously this wasn’t feasible in the long term. I’d been reading a lot about OpenWrap recently, so I decided to try to bundle the reusable code into a wrap that could be referenced by the consuming projects.
To set the stage, we have the following environment:
- Hudson is our continuous integration software, running on a Windows server. Hudson is hosted by Tomcat running as a local user named
tomcat on port 8080, and we have Apache Web Server doing reverse proxying of http://server/hudson to http://server:8080/hudson.
- Bazaar is used for DVCS.
Goal
My goal is to end up with Foo.Shared as a reusable wrap referenced from FooA and FooB.
Highlevel Steps
Here are the highlevel steps I took:
- Installed OpenWrap locally.
- Created a new shared project.
- Initialized the shared project with OpenWrap.
- Installed OpenWrap on the continuous integration server.
- Configured CI so successful CI builds of the shared project publish the wrap to a local repository on the CI server.
- Configured Apache Web Server to serve up the files from the local repository as an http repository.
- Added the CI server as an OpenWrap repository on my local machine.
- Referenced the new shared wrap from consuming projects.
Installing OpenWrap
First, I downloaded o.exe. Upon successful download, I openned a cmd prompt and ran o.exe. When prompted, I typed i to install o.exe into my PATH.
Shared Project
Creating the project
In VS 2010, I created a new project, Foo.Shared, saved it, and then exited. OpenWrap is fairly opinionated about how projects should be structured, which fortunately matches my usual way of organizing things, so I next created a src\ folder at the top level of my project, and moved the Foo.Shared folder into there. This results in the following structure:
- Foo.Shared
- Foo.Shared.wrapdesc
- src
- wraps
- version
I then edited Foo.Shared.sln to fix the path to Foo.Shared.csproj accordingly. I confirmed the build still worked as expected by building in a command prompt:
C:\Users\pete.johanson\repo\Foo.Shared> msbuild /t:Clean;Build Foo.Shared.sln
Adding OpenWrap to the project
To initialize the OpenWrap information, I returned to my cmd and prompt and performed the following:
C:\Users\pete.johanson\repo\Foo.Shared> o init-wrap -NoSymlinks true -IgnoreFileName .bzrignore -All true
The -NoSymlinks portion is key to keep version control systems like Bazaar happy (without it, OpenWrap creates a “JUNCTION” in the wraps\ folder that confuses Bazaar). I specified the -IgnoreFileName explicitly because otherwise OpenWrap places the .bzrignore file in the wraps\ folder which Bazaar seems to ignore. This produces the following Foo.Shared.wrapdesc:
name: Foo.Shared
depends: openwrap anchored content
use-symlinks: false
I again confirmed that rebuilding the project worked fine after OpenWrap updated the all the .csproj files. Next, I confirmed the OpenWrap configuration worked as expected:
C:\Users\pete.johanson\repo\Foo.Shared> o build-wrap
After that, I added the usual culprits to .bzrignore to prevent adding things I didn’t want to Bazaar, and committed. I think pushed to our central repository location.
Setting up the build server
Installing OpenWrap on the server
I logged into the Hudson server as the local tomcat user. Again, I downloaded o.exe, ran it in a command prompt, and when prompted typed i to install OpenWrap into the PATH on the server.
Creating the server repository
I then created a directory on the server that will serve as the repository:
C:\wraps\
From a command prompt, I think configured the local OpenWrap repository:
C:\wraps> o add-remote local file://C:\wraps\
Exposing the server repository over http
In the httpd.conf in C:\Program Files\Apache Software Foundation\Apache2.2\conf\ I added:
Alias "/wraps" "C:/wraps"
<Directory C:/wraps>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
Publishing the shared project on build
In Hudson, the shared project build consists of three build steps. The first uses the MSBuild plugin for hudson, and is of type “Build a Visual Studio project or solution using MSBuild” and uses the Foo.Shared.sln solution file. The remaining two steps are both of type “Execute Windows batch command”. The first simply creates the wrap:
o build-wrap
And the second publishes it:
o publish-wrap local -Name Foo.Shared
Doing a “Build Now” in Hudson causes the shared library to build built, packaged into a new OpenWrap wrap, and then published to the shared repository.
Consuming the new repository
To consume the new repository on the continuous integration server, we add a new repository:
C:\Users\pete.johanson> o add-remote continuous http://server/wraps/
After adding the repository, we can now list the repository:
C:\Users\pete.johanson> o list-wrap -Remote continuous
# OpenWrap v1.0.0.0 ['C:\Users\pete.johanson\Foo.Shared\wraps\_cache\openwrap-1.0.0.503386209\bin-net35\OpenWrap.dll']
- Foo.Shared (available: 0.0.1.53148463)
Success! We can now properly add Foo.Shared to any other projects.