Overriding rake tasks and rake task dependencies? - ruby

I'm using a build system which defines a number of rake targets, including this one:
task :test => [:all]
This seems incorrect to me, and so I defined my own rake tasks like so:
task :test => [:spec]
task :all => [:test, :build]
task :release => [:all]
task :default => [:release]
However, now I'm getting this error when I try to build my package:
Circular dependency detected: TOP => default => all => test => all
Tasks: TOP => default => all => test
BUILD FAILED
I've come to realize that defining a rake task (or dependencies for a rake task) just appends those tasks/dependencies to the task definition! This is driving me crazy! Why can't I redefine my rake tasks as I see fit?! Is there any way to overwrite a rake task, and/or to overwrite the dependencies of a rake task?

Use this before you define your task:
Rake::Task[:test].clear
This is implemented in the rake gem, file lib/rake/task.rb
You can see it also supports clear_prerequisites, clear_actions, clear_comments, clear_args as well (clear does all four things).

Related

Check if rake task exists from within Rakefile

I'm looking for a way to be able to check if a certain rake task exists from within the Rakefile. I have a task dependency that I only want to include as a dependency if that task is available. In this particular case, the task is only available in a Rails project, but I want my rake tasks to work in a more general Ruby application environment too (not just Rails).
I want to do something like this:
if tasks.includes?('assets:precompile')
task :archive => [:clean, :vendor_deps, 'assets:precompile']
...
end
else
task :archive => [:clean, :vendor_deps]
...
end
end
What is the best way to conditionally include a task dependency in a rake task?
what about doing something like this? Invoke the task if it exists, as opposed to making it an explicit dependency?
task :archive => [:clean, :vendor_deps] do
Rake.application["assets:precompile"].invoke if Rake::Task.task_defined?('assets:precompile')
....
end
or even easier. Since specifying the task again allows you to add to it, something like this appears to work as well.
task :archive => [:clean, :vendor_deps] do
...
end
task :archive => "assets:precompile" if Rake::Task.task_defined?("assets:precompile")
which will conditionally add the dependency on assets:precompile if it is defined.
You should be able to use task_defined?:
Rake::Task.task_defined?('assets:precompile')

Trying to run cucumber tests in jenkins

I'm getting the following error when I try to run my cucumber tests in my (local) Jenkins:
/Users/kris/.rvm/rubies/ruby-1.9.3-p545/bin/rake --rakefile android/rakefile
(in /)
rake aborted!
cannot load such file -- cucumber
My rakefile looks like the following:
require 'cucumber'
require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:features) do |t|
t.profile = 'ci'
end
task :default => :features
I'm just trying to set up a really basic run, it looks like I need to either set up a plugin for cucumber (which I thought I had done) - or set some variable to make cucumber available to Jenkins.
Thanks for any help/suggestions!

How do I Declare a Rake::PackageTask with Prerequisites?

In Rake, I can use the following syntax to declare that task charlie requires tasks alpha and bravo to have been completed first.
task :charlie => [:alpha, :bravo]
This seems to work fine if charlie is a typical Rake task or a file task but I cannot figure out how to do this for a Rake::PackageTask. Here are the relevant parts of the rakefile so far:
require 'rake/packagetask'
file :package_jar => [:compile] do
puts("Packaging library.jar...")
# code omitted for brevity, but this bit works fine
end
Rake::PackageTask.new("library", "1.0") do |pt|
puts("Packaging library distribution artefact...")
pt.need_tar = true
pt.package_files = ["target/library.jar"]
end
task :package => :package_jar
What's happening here is that, for a clean build, it complains that it doesn't "know how to build task 'target/library.jar'". I have to run rake package_jar from the command line manually to get it to work, which is a bit of a nuisance. Is there any way I can make package depend on package_jar?
For what it's worth, I am using Rake version 0.9.2.2 with Ruby 1.8.7 on Linux.
When you run rake package (without previously running anything else to create any needed files) Rake sees that the package task needs the file target/library.jar. Since this file doesn’t yet exist Rake checks to see if it knows how to create it. It doesn’t know of any rules that will create this file, so it fails with the error you see.
Rake does have a task that it thinks will create a file named package_jar, and that task in fact creates the file target/library.jar, but it doesn’t realise this.
The fix is to tell Rake exactly what file is created in the file task. Rake will then automatically find the dependency.
Change
file :package_jar => [:compile] do
to
file 'target/library.jar' => [:compile] do
and then remove the line
task :package => :package_jar
since package_jar no longer exists and Rake will find the dependency on the file by itself.
In general in rake, if you want to add a dependency to a task, you need that task's name. So you need to figure out the name of the actual rake task that Rake::PackageTask is registering.
The easiest way to do this is by running with --trace — it lists each task's name as it is executing.
(I believe the name of a buildr package task is the filename of the package it produces, but I don't remember for certain. Use --trace to find out.)
You can add a dependency to any task by writing,
someTask.enhance [other, tasks]
where other and tasks can be either task names or task objects.
So in your case, you could write:
library = Rake::PackageTask.new(...) do
...
end
task(:package).enhance([library])

Is there a way to run a rake task without running the prerequisites?

Is there a command line switch I'm missing?
At the moment I'm having to do this:
#task :install => :build do
task :install do
end
I seem to have solved this problem by simply adding extra tasks in the format "taskname_no_prerequisites". So for example in the code below executing "rake install_no_prerequisites" would not cause "build" to be executed.
desc "Build"
task :build do
puts "BUILDING..."
end
desc "Install"
task :install => :build do
puts "INSTALLING..."
end
Rake::Task::tasks.each do |task|
desc "#{task} without prerequisites"
task "#{task}_no_prerequisites".to_sym do
task.invoke_without_prerequisites
end
end
module Rake
class Task
def invoke_without_prerequisites
execute
end
end
end
if you define a dependency on a task, it will always be run first. However, you can create your tasks individually and then aggregate them together with another task, like this:
task :build do
...
end
task :install do
...
end
task :go => [:build, :install]
and then you can call the build or install tasks independently, or run the sequence with the go task.
rake build
rake install
rake go
i do this a lot, actually. it makes it very convenient for me to run individual steps when i want to, and have the larger sequence of steps when i need them.

How do I pipe my msbuild output to a log file from rake

I'm using the fabulous albacore gem with rake to build a new .NET project. My organization is still using NAnt, and there are lots of folks who expect to see a log file when the build script executes. How do I save the msbuild task output that gets dumped to STDOUT to a log file?
I figured out a solution. We don't really need a build log file for our CI server (hudson), but it would still be nice to have physical files to check when the build runs locally, particularly when we're doing the check-in dance and the build fails.
Fortunately, the albacore dudes were smart enough to create a ".parameters" option, which can be used with any of the command-line tool tasks to add parameters which aren't explicitly handled by that task. So, for example, you can add a parameter to the msbuild task to specify a logfile for MSBuild. And it goes a little something like this:
BUILD_REPORTS = 'BuildReports'
MSBUILD_EXE = "C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe"
directory BUILD_REPORTS
CLEAN.include BUILD_REPORTS
task :default => [:build]
desc "Build the solution"
msbuild :build => BUILD_REPORTS do |msb|
msb.properties :configuration => :Debug
msb.path_to_command = MSBUILD_EXE
msb.targets :Clean, :Build
msb.solution = "./mysolution.sln"
msb.parameters "/l:FileLogger,Microsoft.Build;logfile=" + log_file("build")
end
def log_file(log_file_name)
BUILD_REPORTS + log_file_name + ".log"
end
Our rakefile is a little more complex than that because it has to do more stuff, but you get the idea.

Resources