Software Craftsmanship by Andrew Smith

15Jan/120

Getting Started with Ruby Rake

Posted by Andrew Smith

Wooden rakes

Rake is a software task management tool written in Ruby. Similarly to make and Apache Ant, it is generally used to automate software build and deployment processes. Unlike make and Ant, rake does not define its tasks in XML, but in Ruby. This offers a great deal of flexibility, fewer XML configuration files and less “XML Hell.”

Prerequisite: - Make sure you have Ruby installed on your machine before you begin. For installing Ruby on Windows, I highly recommend using the RubyInstaller. I am using Ruby version 1.9.2 p290 for the purpose of this article. Download and run to install Ruby on your Windows system.

In this article, I introduce rake as a build automation tool and provide a simple example of its usage. I intend to publish future articles with more in-depth, real world examples of how to utilize rake to its full potential.

Getting Started with Rake

First, let’s install Rake. Open up a Ruby console and use the following command:

gem install rake

Our First Rake Task

task :default do
     puts "This is our default rake task."
end

Remember: rake tasks should always be placed in a file named rakefile, RakeFile, rakefile.rb, or RakeFile.rb.

Now that we have saved our first rake task, change the directory of the Ruby console to the one containing the rakefile and execute the task using the rake command:

rake
This is our default rake task.

Now let’s go back to the rakefile and change its contents to the following:

desc "Initializes the build output folders"
task :init do
      puts "I initialize the project build output folder structure."
end

desc "Compile project"
task :compile do
     puts "I compile the project."
end

 Running the rake command now produces an error:

rake
rake aborted!
Don't know how to build task 'default'

So what happened? When executing the rake command without specifying a task, rake will automatically run the :default task. Since we removed that task and tried running rake without specifying a task, it throws us that error.

However, if you ran rake and specified the task, you would get the following output:

rake init
I initialize the project build output folder structure.

Adding a Description to your Tasks

desc "Compile project"
task :compile do
     puts "I compile the project."
end

You will also notice the desc “Some Text” added above each task. This allows you to place a description of the task and its purpose. This is very helpful when listing all available tasks. Try running this in the Ruby console to see what I mean:

rake -T

Adding a Few More Tasks

I have added a few more rake tasks to our rakefile below:

desc "Loads build settings."
task :load_settings do
	puts "I load build settings."
end

desc "Cleans build output folder."
task :clean do
	puts "I clean the build output folder."
end

desc "Initializes the build output folders"
task :init do
      puts "I initialize the project build output folder structure."
end

desc "Compile project"
task :compile do
     puts "I compile the project."
end

desc "Execute unit tests."
task :unit_tests do
	puts "I execute unit tests and create a report on the results."
end

desc "Deploys application"
task :deploy do
	puts "I deploy the application code to the build output folder."
end

 Task Depedencies

As you can imagine, some of these tasks depend on others having been executed. Rake makes this easy to define a task’s dependencies. Let’s change our example above with the following dependencies:

  1. All tasks require the loading of build settings
  2. unit_tests requires the compile task
  3. deploy requires clean, init, and compile

We can rewrite our tasks enforcing these dependencies as follows:

desc "Loads build settings."
task :load_settings do
	puts "I load build settings."
end

desc "Cleans build output folder."
task :clean => [:load_settings] do
	puts "I clean the build output folder."
end

desc "Initializes the build output folders"
task :init => [:clean] do
      puts "I initialize the project build output folder structure."
end

desc "Compile project"
task :compile => [:load_settings] do
     puts "I compile the project."
end

desc "Execute unit tests."
task :unit_tests => [:load_settings, :compile] do
	puts "I execute unit tests and create a report on the results."
end

desc "Deploys application"
task :deploy => [:clean, :compile] do
	puts "I deploy the application code to the build output folder."
end

Now try running the unit_test task:

rake unit_tests
I load build settings.
I compile the project.
I execute unit test and create a report of the results.

You will notice that the dependencies are upheld. There is one important thing to notice. View line #2 below:

desc "Execute unit tests."
task :unit_tests => [:load_settings, :compile] do
	puts "I execute unit tests and create a report on the results."
end

You will see that unit_tests depends on two other tasks, load_settings and compile. The compile task also depends on the load_settings task. The unit_tests has both an explicit and implicit dependency on load_settings. Despite this, notice from the output that this task was only called once, not twice.

Rake Task Namespacing

Sometimes it is nice to be able to group related tasks together. This can be accomplished in rake by creating a namespace for each group of tasks. In our example, I probably want to group all my setup tasks, my testing tasks, and deployment tasks together. I can do this by creating a namespace for each one as seen below:

namespace :setup do
	desc "Loads build settings."
	task :load_settings do
		puts "I load build settings."
	end

	desc "Cleans build output folder."
	task :clean => [:load_settings] do
		puts "I clean the build output folder."
	end

	desc "Initializes the build output folders"
	task :init => [:clean] do
	      puts "I initialize the project build output folder structure."
	end
end

desc "Compile project"
task :compile => [:load_settings] do
     puts "I compile the project."
 end

namespace :tests do
	desc "Execute unit tests."
	task :unit_tests => [:load_settings, :compile] do
		puts "I execute unit tests and create a report on the results."
	end
end

namespace :deployment do
	desc "Deploys application"
	task :deploy => [:clean, :compile] do
		puts "I deploy the application code to the build output folder."
	end
end

However, there are still some problems with the above code. Now that we have added the namespaces, we need to reference the contained tasks correctly. I can no longer simply call rake init. Instead I can call:

rake setup:init

With this said, we need to update our task dependencies to reflect this. See the below rakefile:

namespace :setup do
	desc "Loads build settings."
	task :load_settings do
		puts "I load build settings."
	end

	desc "Cleans build output folder."
	task :clean => [:load_settings] do
		puts "I clean the build output folder."
	end

	desc "Initializes the build output folders"
	task :init => [:clean] do
	      puts "I initialize the project build output folder structure."
	end
end

desc "Compile project"
task :compile => ["setup:load_settings"] do
     puts "I compile the project."
end

namespace :tests do
	desc "Execute unit tests."
	task :unit_tests => ["setup:load_settings", :compile] do
		puts "I execute unit tests and create a report on the results."
	end
end

namespace :deployment do
	desc "Deploys application"
	task :deploy => ["setup::clean", :compile] do
		puts "I deploy the application code to the build output folder."
	end
end

Notice the highlighted lines above. When creating a dependency on a namespaced task, you must include the namespace prefix and surround the entire thing with quotations.

Summary

In this article, I have covered the very basics of creating rake tasks, adding dependencies, and namespacing. There is much more that has not been covered, as well as having the rake tasks do something more than simply output to the console.

In my next article, I introduce Albacore and use it in a a real world build automation context.

Tagged as: , No Comments
8Jan/120

Tools of the Trade

Posted by Andrew Smith

In the world of crafting software, the tools in your developer toolbox are invaluable. Here is a list of tools, in no particular order, that you may want to consider adding to your workbench.

General Tools

  • Evernote - great software for note taking and organizing your thoughts. Notes are available in the cloud to all your devices; desktop, laptop, iOS and Android devices, and even on the web via your web browser.
  • DiffMerge - a multi-platform diffing and merging tool. Available on Mac, Windows, and Linux.
  • TimeSnapper - takes screen captures and keeps stats on what software you use and for how long. The paid version can be setup to pull tasks from an external source and use keyboard shortcuts to start/stop a task. Great for tracking your time on tasks for future estimating and keeping personal statistics on your productivity.
  • Rake - similar to make, this is an Ruby implementation that is great for scripting build automation.
  • PowerShell - command line shell and scripting language for the Windows platform.
  • psake - similar to Rake, but implemented using PowerShell.Great for those wanting to utilize current skill sets on Windows platforms.
  • Log2Console - offers a very nice, color coded UI to display, filter, and search log messages from varying logging sources; including log4Net, Log4J, and NLog. It can read log events locally, remotely, or even from a file.
  • AutoHotKey - Windows utility to automate tasks via keystrokes and mouse clicks.
  • VMware WorkStation or VMware Player – run multiple operating systems on your PC. While Workstation offers more features, Player is free.
  • Git - used from the command line, git is a distributed version control system. Popular sites such as GitHub have pushed it into the spotlight. However, if you want to host your own private repositories and have an interface like GitHub, you should look into installing Gitorious or GitLab on your own server. Note: you can use git locally without GitHub, Gitorious, or GitLab.
  • Notepad++ – good default, text editor with syntax highlighting and a tabbed interface.
  • PNGGauntlet – optimizes PNG files for lower file sizes.

.NET Development Tools

  • ReSharper - productivity tool for Visual Studio. Once you start using it, you will find it to be incredibly invaluable; simply something you cannot live without.
  • VS Vim – Vim for Visual Studio. If you are not already using Vim, it will take time to become proficient, but once done, you will see your productivity skyrocket.
  • TestDriven.NET - TestDriven.Net makes it easy to run unit tests with a single click, anywhere in your Visual Studio solutions.
  • StyleCop - tool that analyzes C# source code to enforce a set of style and consistency rules. It can be run from inside of Visual Studio or integrated into an MSBuild project.
  • IL Merge – tool capable of merging multiple .NET assemblies into a single .NET assembly.
  • dotPeek - free .NET decompiler by makers of ReShaper.
  • dotCover - code analysis software by makers of ReSharper.
  • dotTrace - performance and memory profiler for .NET applications.
  • Chirpy - Mashes, minifies, and validates your javascript, stylesheet, and dotless files. It can also auto-update T4MVC and other T4 templates.
  • LINQPad – .NET language scratchpad; capable of instantly executing any expression, statement block, or program.
  • NuGet Package Manager - NuGet is a free, open source developer focused package management system for the .NET platform intent on simplifying the process of incorporating third party libraries into a .NET application during development.

Know of something not listed? Leave a comment or shoot me an email and I may add it to the list.

Thanks for stopping by!

Tagged as: No Comments