Fire
(火)¶ ↑
Homepage / Report Issue / Source Code / IRC Channel
Fire
is a rules-based build tool and continuous integration system. The creative spark that created Fire
is “logic programming meets build tool”. With it the Ruby developer defines project states and rules to follow when those state are met. In this manner, a project can all but manage itself!
Instruction¶ ↑
Rule Files¶ ↑
Rule files by default are looked up from a project’s root directory matching task/file.rb
or task/*.fire.rb
. All matching files will be loaded. If you prefer to use a different location, you can create a .fire/script.rb
file and only that file will be used. In it you can import any other paths you like.
Rule files are Ruby scripts, containing primarily a collection of state
and rule
definitions. States define conditions and rules define procedures to take based on such states.
States¶ ↑
States are conditions upon which rule depend to decide when a rules procedure should run or not. States are defined using the state
method with a code block to express the condition. General rules are given a specific name.
state :happy_hour? do t = Time.now; t.hour >= 2 && t.hour <= 3 end
Named states define a method internally, which is called when defining rules (see below). But states can also be anonymous. A common type of anonymous state is the file
state, which automatically creates a condition to check for files on disk that have changed since the previous “firing”.
file('lib/**/*.rb')
Another such state is the env
state, which is used to match system environment variables. The variable’s value can be matched against a specific string or a regular expression.
env('PATH'=>/foo/)
Rules¶ ↑
Rules take a state as an argument and attaches it to an action procedure. When fired, if the state condition evaluates as true, the rule procedure will be called.
# Mast handles manifest updates. state :update_manifest? do ! system "mast --recent" end rule update_manifest? do system "mast -u" end
To create a Rule for a file state, we can use the file
state method mentioned previously.
rule file('demo/*.md') do |files| system `qed #{files.join(' ')}` end
But using file
isn’t necessary when it is the only condition b/c rules that use a string or a regular expression for the state are automatically interpreted to be a file state.
rule 'man/*.ronn' do |paths| system 'ronn ' + paths.join(' ') end
State Logic¶ ↑
Rules sometimes require more nuanced conditions based on multiple states. Fire
has a state logic system based on set logic that can be used to build complex states using logical operators &
(And) and |
(Or).
rule happy_hour? & file('*.happy') do |files| puts "These are you happy files:" puts files.join("\n") end
Tasks¶ ↑
Rules work admirably for most usecases, but sometimes it is necessary just to trigger a single action and not have all ones rules come to bare. For this Fire
provides tasks.
task :test do sh 'rubytest' end
These rules are then triggered via the command line, or as prerequisite actions of other tasks or rules (see below). To make a tasks accessible via the command line, a description must be given using the desc
method before the task definition.
desc "run all unit tests" task :test do sh "rubytest" end
Btw, rules can be given descriptions too, as can states. This information isn’t important to the Fire’s functionality but can useful to a user who can request help information about a system.
Prerequisites¶ ↑
Sometimes rules have prerequisite actions. And often different rules may share the same prerequisite actions. But a prerequisite is only ever run once for any given run regardless.
desc "Run all unit tests" task :test => [:setup] do sh "rubytest" end desc "Run unit tests when a test file changes." rule 'test/**/test_*.rb' => [:setup] do |files| sh "rubytest #{files.join(' ')}" end task :setup do mkdir_p 'tmp' end
Notice how both the test rule and the test task relay on the same prequisite task.
Running¶ ↑
To run your rules simply use the fire
command.
fire
There are few was to manually trigger builds. For file rules, the -n
option will cause the digest to be “null and void”, which will cause all files to appear out-of-date and thus all be triggered.
Triggers are specified as a command argument.
fire test
Continuous Integration¶ ↑
Fire
can be run continuously by running autofire. To set the interval provide then number of seconds to wait between firings.
autofire -w 60
This will run fire every 60 seconds. By default the periodicity is 300 seconds, or every 5 minutes. To stop autofiring run autofire again.
Building Useful Rules¶ ↑
Fire
doesn’t dictate how rule procedures are coded. It’s just Ruby. While it does provide easy access to FileUtils methods, beyond that the how of things is completely up to the developer.
We do offer one recommendation that will likely make endeavors in this regard much easier. Have a look at the Detroit Toolchain. It has numerous tools largely preconfigured and with built-in smarts to make them quick and easy to put into action.
Copyright & License¶ ↑
Fire
is copyrighted open-source software.
Copyright © 2011 Rubyworks. All rights reserved.
It is modifiable and redistributable under the terms of the BSD-2-Clause license.
See the enclosed LICENSE.txt file for details.