fire 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|