Integrating your Rake / Albacore build scripts with automated build servers is a necessary part of most projects that use these tools. However, path issues can become an obstacle, causing files to not be found and failing builds.
When executing a rakefile directly from the command line, a developer is typically sitting in the same folder as the rakefile. Additionally, relative paths are often used in the rakefile, based on the idea that the rakefile will be executed from the folder that contains it.
For example, projects often have a "src" folder to contain the source code and solution for an .NET solution. When calling MSBuild from the rakefile, with relative paths, it's easy to write code like this:
msbuild :build do |msb| msb.solution = "src/Take.Over.TheWorld.sln" #... other options, here end
This works great when you run rake from the same folder that the rakefile is in. However, it breaks when running from any other folder, because the relative paths are now off.
Build servers, such as TeamCity and Hudson, do not execute your rakefile from the folder that houses the file. They use another folder, such as the project root in Hudson, as the process working directory and execute the rakefile using a relative path from there. This is the equivalent of calling this from the command line:
rake -f my\project\folder\rakefile.rb
When a rakefile is called in this manner, the process working directory is not the folder that houses the rakefile. Relative paths are interpreted from the process working directory, causing problems with files missing, etc.
The solution to this problem is to use three things:
File macro tells you the name of the file that contains the code currently being evaluated. This is always the file that contains the
File macro call. For example, if you have a file named
foo.rb, then the
File macro will return "foo.rb".
File.dirname method does what it sounds like it would do: returns the directory name of the file you specify.
File.expand_path method evaluates a file / folder structure, passed in as a string, and returns a complete, absolute path that represents the target. For example
File.expand_path("foo.rb") called from within the
C:\Dev\Project</code> folder will return "C:\Dev\Project\foo.rb".
By combining these three items, we can convert our relative paths to absolute paths, solving the problem of running our rakefile from a working directory that is relative to the rakefile.
msbuild :build do |msb| my_solution = File.expand_path(File.dirname(__FILE__)) + "/src/Take.Over.TheWorld.sln" msb.solution = my_solution #... other options here end
Your build server will still execute the rakefile from a different relative path, but we are accounting for that with this code, telling MSBuild to use an absolute path to the solution.