fire 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.index +53 -0
- data/.yardopts +10 -0
- data/HISTORY.md +33 -0
- data/LICENSE.txt +29 -0
- data/README.md +217 -0
- data/bin/autofire +5 -0
- data/bin/fire +5 -0
- data/demo/03_runner/01_applying_rules.md +51 -0
- data/demo/03_runner/02_resolve_prerequisites.md +95 -0
- data/demo/applique/ae.rb +1 -0
- data/demo/applique/fire.rb +1 -0
- data/demo/applique/rules.rb +5 -0
- data/demo/overview.md +14 -0
- data/lib/fire.rb +3 -0
- data/lib/fire.yml +53 -0
- data/lib/fire/cli.rb +64 -0
- data/lib/fire/core_ext.rb +4 -0
- data/lib/fire/core_ext/boolean.rb +10 -0
- data/lib/fire/core_ext/cli.rb +56 -0
- data/lib/fire/core_ext/true_class.rb +58 -0
- data/lib/fire/digest.rb +112 -0
- data/lib/fire/dsl.rb +34 -0
- data/lib/fire/match.rb +26 -0
- data/lib/fire/rule.rb +103 -0
- data/lib/fire/rulefile.rb +12 -0
- data/lib/fire/runner.rb +76 -0
- data/lib/fire/session.rb +268 -0
- data/lib/fire/shellutils.rb +77 -0
- data/lib/fire/state.rb +91 -0
- data/lib/fire/system.rb +244 -0
- data/lib/fire/task.rb +71 -0
- data/man/fire.1 +47 -0
- data/man/fire.1.html +130 -0
- data/man/fire.1.ronn +52 -0
- metadata +135 -0
data/.index
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
---
|
2
|
+
revision: 2013
|
3
|
+
type: ruby
|
4
|
+
sources:
|
5
|
+
- var
|
6
|
+
authors:
|
7
|
+
- name: Trans
|
8
|
+
email: transfire@gmail.com
|
9
|
+
organizations:
|
10
|
+
- name: Rubyworks
|
11
|
+
requirements:
|
12
|
+
- name: notify
|
13
|
+
- groups:
|
14
|
+
- build
|
15
|
+
development: true
|
16
|
+
name: detroit
|
17
|
+
- groups:
|
18
|
+
- build
|
19
|
+
development: true
|
20
|
+
name: mast
|
21
|
+
conflicts: []
|
22
|
+
alternatives: []
|
23
|
+
resources:
|
24
|
+
- type: home
|
25
|
+
uri: http://rubyworks.github.com/fire
|
26
|
+
label: Homepage
|
27
|
+
- type: code
|
28
|
+
uri: http://github.com/rubyworks/fire
|
29
|
+
label: Source Code
|
30
|
+
- type: bugs
|
31
|
+
uri: http://github.com/rubyworks/fire/issues
|
32
|
+
label: Issue Tracker
|
33
|
+
repositories:
|
34
|
+
- name: upstream
|
35
|
+
scm: git
|
36
|
+
uri: git://github.com/rubyworks/fire.git
|
37
|
+
categories: []
|
38
|
+
copyrights:
|
39
|
+
- holder: Rubyworks
|
40
|
+
year: '2010'
|
41
|
+
license: BSD-2-Clause
|
42
|
+
customs: []
|
43
|
+
paths:
|
44
|
+
lib:
|
45
|
+
- lib
|
46
|
+
created: '2010-07-05'
|
47
|
+
summary: The best build tool, logically!
|
48
|
+
title: Fire
|
49
|
+
version: 0.2.0
|
50
|
+
name: fire
|
51
|
+
description: ! "Fire is a continuous integration build tool with a slick set logic
|
52
|
+
\nstate/rules system."
|
53
|
+
date: '2013-02-12'
|
data/.yardopts
ADDED
data/HISTORY.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# RELEASE HISTORY
|
2
|
+
|
3
|
+
## 0.2.0 / 2013-02-12
|
4
|
+
|
5
|
+
This is the last version with tasks. Tasks are being deprecated
|
6
|
+
for two reasons: a) they add a great deal of complexity to the
|
7
|
+
syntax and the implementation via their need for dependencies;
|
8
|
+
and b) tasks have proven to be an excuse for poorly designed
|
9
|
+
rules, which, if properly written, would do the job just as well
|
10
|
+
if not better than any task. So it was decided that if tasks are
|
11
|
+
needed, then they should be provided via dedicated task system,
|
12
|
+
not via the rules system.
|
13
|
+
|
14
|
+
Changes:
|
15
|
+
|
16
|
+
* Default rule file is now `.fire/rules.rb` or `rules.rb`.
|
17
|
+
* Rules can depend on tasks using same hash notation as tasks.
|
18
|
+
* Modified the `#rule` method to define file rules given a string.
|
19
|
+
* Deprecated the `file` method for defining file rules.
|
20
|
+
|
21
|
+
|
22
|
+
## 0.1.0 / 2012-04-10
|
23
|
+
|
24
|
+
This is the initial release of Fire. Fire is state and rules-based
|
25
|
+
continuous integration and build tool.
|
26
|
+
|
27
|
+
Special thanks to Ari Brown for letting us take over the fire gem
|
28
|
+
for this project. "Fire" is perfect fit.
|
29
|
+
|
30
|
+
Changes:
|
31
|
+
|
32
|
+
* Happy first release day!
|
33
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Fire - Rules-based BI and Build Tool
|
2
|
+
(http://github.com/rubyworks/fire)
|
3
|
+
|
4
|
+
Copyright (c) 2011 Rubyworks. All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms,
|
7
|
+
with or without modification, are permitted provided that the following
|
8
|
+
conditions are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
18
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
20
|
+
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
22
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
24
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
28
|
+
SPDX License: BSD-2-Clause
|
29
|
+
|
data/README.md
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
# Fire (火)
|
2
|
+
|
3
|
+
[Homepage](http://rubyworks.github.com/fire) /
|
4
|
+
[Report Issue](http://github.com/rubyworks/fire/issues) /
|
5
|
+
[Source Code](http://github.com/rubyworks/fire) /
|
6
|
+
[IRC Channel](http://chat.us.freenode.net/rubyworks)
|
7
|
+
|
8
|
+
|
9
|
+
Fire is a rules-based build tool and continuous integration system.
|
10
|
+
The creative spark that created Fire is "logic programming meets build tool".
|
11
|
+
With it the Ruby developer defines project states and rules to follow
|
12
|
+
when those state are met. In this manner, a project can all but manage
|
13
|
+
itself!
|
14
|
+
|
15
|
+
|
16
|
+
## Instruction
|
17
|
+
|
18
|
+
### Rule Files
|
19
|
+
|
20
|
+
Rule files by default are looked up from a project's root directory
|
21
|
+
matching `task/file.rb` or `task/*.fire.rb`. All matching files will
|
22
|
+
be loaded. If you prefer to use a different location, you can create
|
23
|
+
a `.fire/script.rb` file and only that file will be used. In it you
|
24
|
+
can import any other paths you like.
|
25
|
+
|
26
|
+
Rule files are Ruby scripts, containing primarily a collection of
|
27
|
+
`state` and `rule` definitions. States define conditions and
|
28
|
+
rules define procedures to take based on such states.
|
29
|
+
|
30
|
+
### States
|
31
|
+
|
32
|
+
States are conditions upon which rule depend to decide when a
|
33
|
+
rules procedure should run or not. States are defined using the
|
34
|
+
`state` method with a code block to express the condition. General
|
35
|
+
rules are given a specific name.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
state :happy_hour? do
|
39
|
+
t = Time.now; t.hour >= 2 && t.hour <= 3
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
Named states define a method internally, which is called when
|
44
|
+
defining rules (see below). But states can also be anonymous.
|
45
|
+
A common type of anonymous state is the `file` state, which
|
46
|
+
automatically creates a condition to check for files on disk
|
47
|
+
that have changed since the previous "firing".
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
file('lib/**/*.rb')
|
51
|
+
```
|
52
|
+
|
53
|
+
Another such state is the `env` state, which is used to match
|
54
|
+
system environment variables. The variable's value can be matched
|
55
|
+
against a specific string or a regular expression.
|
56
|
+
|
57
|
+
```
|
58
|
+
env('PATH'=>/foo/)
|
59
|
+
```
|
60
|
+
|
61
|
+
### Rules
|
62
|
+
|
63
|
+
Rules take a state as an argument and attaches it to an action
|
64
|
+
procedure. When fired, if the state condition evaluates as true,
|
65
|
+
the rule procedure will be called.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# Mast handles manifest updates.
|
69
|
+
|
70
|
+
state :update_manifest? do
|
71
|
+
! system "mast --recent"
|
72
|
+
end
|
73
|
+
|
74
|
+
rule update_manifest? do
|
75
|
+
system "mast -u"
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
To create a Rule for a file state, we can use the `file` state
|
80
|
+
method mentioned previously.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
rule file('demo/*.md') do |files|
|
84
|
+
system `qed #{files.join(' ')}`
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
But using `file` isn't necessary when it is the only condition b/c
|
89
|
+
rules that use a string or a regular expression for the state are
|
90
|
+
automatically interpreted to be a file state.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
rule 'man/*.ronn' do |paths|
|
94
|
+
system 'ronn ' + paths.join(' ')
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
### State Logic
|
99
|
+
|
100
|
+
Rules sometimes require more nuanced conditions based on multiple states.
|
101
|
+
Fire has a state logic system based on *set logic* that can be used
|
102
|
+
to build complex states using logical operators `&` (And) and `|` (Or).
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
rule happy_hour? & file('*.happy') do |files|
|
106
|
+
puts "These are you happy files:"
|
107
|
+
puts files.join("\n")
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
### Tasks
|
112
|
+
|
113
|
+
Rules work admirably for most usecases, but sometimes it is necessary
|
114
|
+
just to trigger a single action and not have all ones rules come
|
115
|
+
to bare. For this Fire provides *tasks*.
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
task :test do
|
119
|
+
sh 'rubytest'
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
These rules are then triggered via the command line, or as prerequisite
|
124
|
+
actions of other tasks or rules (see below). To make a tasks accessible
|
125
|
+
via the command line, a description must be given using the `desc` method
|
126
|
+
before the task definition.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
desc "run all unit tests"
|
130
|
+
task :test do
|
131
|
+
sh "rubytest"
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
Btw, rules can be given descriptions too, as can states. This information
|
136
|
+
isn't important to the Fire's functionality but can useful to a user
|
137
|
+
who can request help information about a system.
|
138
|
+
|
139
|
+
### Prerequisites
|
140
|
+
|
141
|
+
Sometimes rules have prerequisite actions. And often different rules may
|
142
|
+
share the same prerequisite actions. But a prerequisite is only ever run
|
143
|
+
once for any given run regardless.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
desc "Run all unit tests"
|
147
|
+
task :test => [:setup] do
|
148
|
+
sh "rubytest"
|
149
|
+
end
|
150
|
+
|
151
|
+
desc "Run unit tests when a test file changes."
|
152
|
+
rule 'test/**/test_*.rb' => [:setup] do |files|
|
153
|
+
sh "rubytest #{files.join(' ')}"
|
154
|
+
end
|
155
|
+
|
156
|
+
task :setup do
|
157
|
+
mkdir_p 'tmp'
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
Notice how both the test rule and the test task relay on the same
|
162
|
+
prequisite task.
|
163
|
+
|
164
|
+
### Running
|
165
|
+
|
166
|
+
To run your rules simply use the `fire` command.
|
167
|
+
|
168
|
+
```
|
169
|
+
fire
|
170
|
+
```
|
171
|
+
|
172
|
+
There are few was to manually trigger builds. For file rules, the `-n` option
|
173
|
+
will cause the digest to be "null and void", which will cause all files to
|
174
|
+
appear out-of-date and thus all be triggered.
|
175
|
+
|
176
|
+
Triggers are specified as a command argument.
|
177
|
+
|
178
|
+
```
|
179
|
+
fire test
|
180
|
+
```
|
181
|
+
|
182
|
+
|
183
|
+
### Continuous Integration
|
184
|
+
|
185
|
+
Fire can be run continuously by running autofire. To set the
|
186
|
+
interval provide then number of seconds to wait between firings.
|
187
|
+
|
188
|
+
```
|
189
|
+
autofire -w 60
|
190
|
+
```
|
191
|
+
|
192
|
+
This will run fire every 60 seconds. By default the periodicity is 300
|
193
|
+
seconds, or every 5 minutes. To stop autofiring run autofire again.
|
194
|
+
|
195
|
+
|
196
|
+
### Building Useful Rules
|
197
|
+
|
198
|
+
Fire doesn't dictate how rule procedures are coded. It's just Ruby. While it
|
199
|
+
does provide easy access to FileUtils methods, beyond that the how of things
|
200
|
+
is completely up to the developer.
|
201
|
+
|
202
|
+
We do offer one recommendation that will likely make endeavors in this regard
|
203
|
+
much easier. Have a look at the [Detroit Toolchain](http://rubyworks.github.com/detroit).
|
204
|
+
It has numerous tools largely preconfigured and with built-in smarts to make
|
205
|
+
them quick and easy to put into action.
|
206
|
+
|
207
|
+
|
208
|
+
## Copyright & License
|
209
|
+
|
210
|
+
Fire is copyrighted open-source software.
|
211
|
+
|
212
|
+
Copyright (c) 2011 Rubyworks. All rights reserved.
|
213
|
+
|
214
|
+
It is modifiable and redistributable under the terms of the *BSD-2-Clause* license.
|
215
|
+
|
216
|
+
See the enclosed LICENSE.txt file for details.
|
217
|
+
|
data/bin/autofire
ADDED
data/bin/fire
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
## Applying Rules
|
2
|
+
|
3
|
+
The `Runner` class handles running rules. It takes `System` as an argument and
|
4
|
+
can run all applicable rules or trigger a named task.
|
5
|
+
|
6
|
+
### True/False Rules
|
7
|
+
|
8
|
+
The simplist rule state is `true`, which means it will always run, or
|
9
|
+
`false` which means it will never run. These states are not very useful,
|
10
|
+
but they should still work.
|
11
|
+
|
12
|
+
Given a @system defined with a simple always-true rule, and another
|
13
|
+
always-false rule:
|
14
|
+
|
15
|
+
rule true do
|
16
|
+
assert true
|
17
|
+
end
|
18
|
+
|
19
|
+
rule false do
|
20
|
+
assert false
|
21
|
+
end
|
22
|
+
|
23
|
+
Then the Runner should run the true rule and not the false rule when
|
24
|
+
applying the system's rules.
|
25
|
+
|
26
|
+
runner = Fire::Runner.new(@system)
|
27
|
+
|
28
|
+
runner.run_rules
|
29
|
+
|
30
|
+
### Simple State Rule
|
31
|
+
|
32
|
+
Given a @system defined with a simple state:
|
33
|
+
|
34
|
+
state :simple do
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
rule simple do
|
39
|
+
assert true
|
40
|
+
end
|
41
|
+
|
42
|
+
rule false do
|
43
|
+
assert false
|
44
|
+
end
|
45
|
+
|
46
|
+
Then the Runner should run the simple rule, but not the other.
|
47
|
+
|
48
|
+
runner = Fire::Runner.new(@system)
|
49
|
+
|
50
|
+
runner.run_rules
|
51
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Resolving Prerequisites
|
2
|
+
|
3
|
+
The `Runner` class handles running rules. It takes `System` as an argument and
|
4
|
+
can run all applicable rules or trigger a named task.
|
5
|
+
|
6
|
+
## Task Prerequisites
|
7
|
+
|
8
|
+
### Handles Simple Prerequisite
|
9
|
+
|
10
|
+
Given a @system defined with a simple prerequisite:
|
11
|
+
|
12
|
+
task :a => [:b] do
|
13
|
+
end
|
14
|
+
|
15
|
+
task :b do
|
16
|
+
end
|
17
|
+
|
18
|
+
Then the Runner should resolve to this single prerequisite.
|
19
|
+
|
20
|
+
runner = Fire::Runner.new(@system)
|
21
|
+
|
22
|
+
a = @system.tasks[:a]
|
23
|
+
|
24
|
+
prelist = runner.send(:resolve, a)
|
25
|
+
prelist.assert == [:b]
|
26
|
+
|
27
|
+
### Handles DAG
|
28
|
+
|
29
|
+
Given a @system defined with a DAG:
|
30
|
+
|
31
|
+
task :a => [:b, :c] do
|
32
|
+
end
|
33
|
+
|
34
|
+
task :b => [:c] do
|
35
|
+
end
|
36
|
+
|
37
|
+
task :c do
|
38
|
+
end
|
39
|
+
|
40
|
+
Then the Runner should remove the redundancy from the list of
|
41
|
+
prerequisites to be run.
|
42
|
+
|
43
|
+
runner = Fire::Runner.new(@system)
|
44
|
+
|
45
|
+
a = @system.tasks[:a]
|
46
|
+
|
47
|
+
prelist = runner.send(:resolve, a)
|
48
|
+
prelist.assert == [:b, :c]
|
49
|
+
|
50
|
+
### Prevents Recursion
|
51
|
+
|
52
|
+
Given a @system defined with recursive prerequisites:
|
53
|
+
|
54
|
+
task :a => [:b] do
|
55
|
+
end
|
56
|
+
|
57
|
+
task :b => [:a] do
|
58
|
+
end
|
59
|
+
|
60
|
+
Then the Runner should resolve the requirements without the
|
61
|
+
infinite repetition.
|
62
|
+
|
63
|
+
runner = Fire::Runner.new(@system)
|
64
|
+
|
65
|
+
a = @system.tasks[:a]
|
66
|
+
|
67
|
+
prelist = runner.send(:resolve, a)
|
68
|
+
prelist.assert == [:b, :a]
|
69
|
+
|
70
|
+
Note: it would be better if this raised an error reporting the recursion,
|
71
|
+
but this has not been implemented yet.
|
72
|
+
|
73
|
+
|
74
|
+
## Rule Prerequisites
|
75
|
+
|
76
|
+
### Handles Simple Prerequisite
|
77
|
+
|
78
|
+
Given a @system defined with a simple prerequisite:
|
79
|
+
|
80
|
+
rule true => [:b] do
|
81
|
+
end
|
82
|
+
|
83
|
+
task :b do
|
84
|
+
end
|
85
|
+
|
86
|
+
Then the Runner should resolve to this single prerequisite.
|
87
|
+
|
88
|
+
runner = Fire::Runner.new(@system)
|
89
|
+
|
90
|
+
a = @system.rules.first # only one there is
|
91
|
+
|
92
|
+
prelist = runner.send(:resolve, a)
|
93
|
+
prelist.assert == [:b]
|
94
|
+
|
95
|
+
|