bozo 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +408 -0
- data/VERSION +1 -0
- data/lib/bozo/bozo.rb +7 -0
- data/lib/bozo/bozo_configuration.rb +300 -0
- data/lib/bozo/class_name_helpers.rb +17 -0
- data/lib/bozo/configuration_error.rb +30 -0
- data/lib/bozo/execution_error.rb +36 -0
- data/lib/bozo/executor.rb +282 -0
- data/lib/bozo/logging.rb +40 -0
- data/lib/bozo/runner.rb +58 -0
- data/lib/bozo/versioning/version.rb +87 -0
- data/lib/bozo/versioning/version_bump_error.rb +30 -0
- data/lib/bozo/versioning/version_bumper.rb +36 -0
- data/lib/bozo.rb +131 -0
- data/test/bozo_configuration_version_tests.rb +42 -0
- data/test/test_helper.rb +3 -0
- data/test/version_bumper_tests.rb +62 -0
- data/test/version_tests.rb +26 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzliYmE5YTJhYmMzY2NiOWZmZWQyMGUwZGIxMzdjOTkzYWNiZmYzOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTYyZGFjZjNiODRhMzBjZjM4MTU4ZmQzYmNhMmYwOWI5OWUyOTYyMA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmExMTBhMDEwNmQwYWEwYjIyNWExOTU4ZGQxN2MwMmYxNjdkYjlkNjM0NzFj
|
10
|
+
OTk3MmEwZDYyOTA3MDhhY2U5ZDM2ZTE5ODRhMzk5NDkzNzM4ZmEwMGNlZDBi
|
11
|
+
NzAyZDQ1YTM4MzljYTBmMzM2NDY3YTFlMTg3ZWRmZDg2NzFlNTc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OGFmNDE3NGY2OGU0ZTRlYTQ5YmYxYzJiOTJkZDVlNDcxOTM3YTg1MjU4MTVi
|
14
|
+
ZTQ0MjU2NDNjMzhmODczN2FlZmU0MjJiMTg4MWViMTQ3MDQ5ODAzYmNkMmRh
|
15
|
+
MzhiMWUyOTM4ZjNlYWRmZjM1NDIzMDE0NzNhZTYxMzcyYjIwMmQ=
|
data/README.md
ADDED
@@ -0,0 +1,408 @@
|
|
1
|
+
# Bozo
|
2
|
+
|
3
|
+
Bozo is a build system written in Ruby. It is designed to be rigid yet
|
4
|
+
extensible.
|
5
|
+
|
6
|
+
## Steps
|
7
|
+
|
8
|
+
There is a fixed set of steps, they are currently:
|
9
|
+
|
10
|
+
1. Clean
|
11
|
+
2. Resolve dependencies
|
12
|
+
3. Prepare
|
13
|
+
4. Compile
|
14
|
+
5. Test
|
15
|
+
6. Package
|
16
|
+
7. Publish
|
17
|
+
|
18
|
+
The steps are sequential but you can run up to any of them. For example `bozo
|
19
|
+
compile` executes the `clean`, `dependencies`, `prepare` and `compile` steps
|
20
|
+
whereas `bozo dependencies` only executes the `clean` and `dependencies`
|
21
|
+
steps.
|
22
|
+
|
23
|
+
Bozo is a framework that provides a skeleton which can be populated by custom
|
24
|
+
runners and hooks. Bozo itself provides no runners or hooks a reference
|
25
|
+
project for runners and hooks can be found in the [bozo-scripts
|
26
|
+
project](https://github.com/zopaUK/bozo-scripts/).
|
27
|
+
|
28
|
+
Each step allows several runners to execute, for example you may run RSpec
|
29
|
+
unit tests followed by Cucumber integration tests within the scope of the
|
30
|
+
`test` step. Each step, along with the entire build, also expose pre- and
|
31
|
+
post-step hooks.
|
32
|
+
|
33
|
+
## Configuration
|
34
|
+
|
35
|
+
A bozo build is configured through a single Ruby file, by convention this
|
36
|
+
should be `bozorc.rb` located at the root of your project.
|
37
|
+
|
38
|
+
Bozo makes use of a VERSION file in the root directory of the project. Versions can be specified in whatever format
|
39
|
+
is required but a string in the format [major].[minor].[point] is generally expected.
|
40
|
+
|
41
|
+
### Conventions
|
42
|
+
|
43
|
+
Dependency resolvers must be defined within the `Bozo::DependencyResolvers`
|
44
|
+
module, project preparers must be defined within the `Bozo::Preparers`
|
45
|
+
module, compilers must be defined within the `Bozo::Compilers` module, test
|
46
|
+
runners must be defined within the `Bozo::TestRunners` module, packagers must
|
47
|
+
be defined within the `Bozo::Packagers`, publishers must be defined within
|
48
|
+
the `Bozo::Publishers` module and hooks, regardless of the steps they relate
|
49
|
+
to, must be defined within the `Bozo::Hooks` module.
|
50
|
+
|
51
|
+
Runners are specified by convention with the relevant module being inspected
|
52
|
+
for a matching class definition. For example, the configuration `compile_with
|
53
|
+
:msbuild` will resolve to the class definition `Bozo::Compilers::Msbuild`.
|
54
|
+
The symbol provided will be converted to Pascal Case prior to resolution. For
|
55
|
+
example, the configuration `pre_compile :common_assembly_info` will resolve
|
56
|
+
to the class definition `Bozo::Hooks::CommonAssemblyInfo`.
|
57
|
+
|
58
|
+
Each runner and hook must provide a parameterless constructor and Bozo will
|
59
|
+
invoke that constructor before registering and passing the instance to any
|
60
|
+
block provided as part of the configuration. A runner or hook should be able
|
61
|
+
to run with the default configuration whenever possible with customizations
|
62
|
+
being provided through the block:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
test_with :nunit do |n| # Creates and registers a new Bozo::TestRunners::Nunit instance
|
66
|
+
n.project 'Project.Tests' # Adds additonal configuration to the instance
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
If there are several runners for the same step then they will be executed in
|
71
|
+
the order the are specified within the configuration.
|
72
|
+
|
73
|
+
As soon as one runner or hook raises an error through either failing to
|
74
|
+
execute a command successfully or some custom condition then the build is
|
75
|
+
aborted.
|
76
|
+
|
77
|
+
### Configuration example
|
78
|
+
|
79
|
+
The exact syntax is still a work in progress though the concepts will remain
|
80
|
+
the same.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
require 'bozo_scripts' # Makes custom runners and hooks available
|
84
|
+
|
85
|
+
prepare :common_assembly_info # Defines that the common assembly info should be prepared for the project
|
86
|
+
|
87
|
+
compile_with :msbuild # Defines that the project should be compiled with the `msbuild` compiler
|
88
|
+
|
89
|
+
test_with :nunit do |n| # Defines that the project should be tested with the `nunit` test runner
|
90
|
+
n.project 'Project.Tests' # Runner specific configuration - in this case defining the assemblies to run
|
91
|
+
end
|
92
|
+
|
93
|
+
package_with :nuget do |p| # Defines that the project should be packaged with `nuget`
|
94
|
+
p.project 'Project' # Runner specific configuration - in this case the projects to package
|
95
|
+
p.project 'Project.Testing'
|
96
|
+
end
|
97
|
+
|
98
|
+
resolve_dependencies_with :nuget # Defines that project dependencies should be resolved with `nuget`
|
99
|
+
|
100
|
+
with_hook :git_commit_hashes # Defines that the `git_commit_hashes` hook should be executed with the build
|
101
|
+
with_hook :timing # Defines that the `timing` hook should be executed with the build
|
102
|
+
|
103
|
+
build_tools_location '//SERVER/network/path' # Defines the location build tools can be copied from
|
104
|
+
```
|
105
|
+
|
106
|
+
## Creating step runners and hooks
|
107
|
+
|
108
|
+
Both step runners and hooks have their nuances which are covered in their
|
109
|
+
dedicated sections. However, both are extended by the `Bozo::Runner` module
|
110
|
+
that makes a collection of methods available to them.
|
111
|
+
|
112
|
+
### build_configuration
|
113
|
+
|
114
|
+
Returns the `Bozo::Configuration` of the build.
|
115
|
+
|
116
|
+
### build_server?
|
117
|
+
|
118
|
+
Returns `true` when the build is being run with the `--build-server` switch,
|
119
|
+
otherwise `false`.
|
120
|
+
|
121
|
+
This is a shortcut for `global_params[:build_server]`.
|
122
|
+
|
123
|
+
### env
|
124
|
+
|
125
|
+
Returns the hash of environment variables. Initially populated by calling
|
126
|
+
`ENV.to_hash` this may be added to by runners and hooks to enable lightweight
|
127
|
+
communication and to cache the result of expensive calls.
|
128
|
+
|
129
|
+
### environment
|
130
|
+
|
131
|
+
Returns the name of the environment that the build is running in, eg.
|
132
|
+
`'development'`.
|
133
|
+
|
134
|
+
This is a shortcut for `global_params[:environment]`.
|
135
|
+
|
136
|
+
### execute_command(tool, args)
|
137
|
+
|
138
|
+
Executes a command line tool.
|
139
|
+
|
140
|
+
Raises a `Bozo::ExecutionError` if the command responds with a non-zero exit
|
141
|
+
code.
|
142
|
+
|
143
|
+
#### Parameters
|
144
|
+
|
145
|
+
* __tool [Symbol]__ A friendly identifier for the tool
|
146
|
+
* __args [Array]__ An array of arguments making up the command to execute
|
147
|
+
|
148
|
+
### global_params
|
149
|
+
|
150
|
+
Returns the hash of global parameters passed to bozo. All key symbols are
|
151
|
+
converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
|
152
|
+
idiomatic for Ruby.
|
153
|
+
|
154
|
+
### log_debug(msg)
|
155
|
+
|
156
|
+
Records an `debug` log message.
|
157
|
+
|
158
|
+
#### Parameters
|
159
|
+
|
160
|
+
* __msg [String]__ The message to log
|
161
|
+
|
162
|
+
### log_fatal(msg)
|
163
|
+
|
164
|
+
Records an `fatal` log message.
|
165
|
+
|
166
|
+
#### Parameters
|
167
|
+
|
168
|
+
* __msg [String]__ The message to log
|
169
|
+
|
170
|
+
### log_info(msg)
|
171
|
+
|
172
|
+
Records an `info` log message.
|
173
|
+
|
174
|
+
#### Parameters
|
175
|
+
|
176
|
+
* __msg [String]__ The message to log
|
177
|
+
|
178
|
+
### log_warn(msg)
|
179
|
+
|
180
|
+
Records an `warn` log message.
|
181
|
+
|
182
|
+
#### Parameters
|
183
|
+
|
184
|
+
* __msg [String]__ The message to log
|
185
|
+
|
186
|
+
### params
|
187
|
+
|
188
|
+
Returns the hash of command parameters passed to bozo. All key symbols are
|
189
|
+
converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
|
190
|
+
idiomatic for Ruby.
|
191
|
+
|
192
|
+
### version
|
193
|
+
|
194
|
+
Returns the version of the build.
|
195
|
+
|
196
|
+
This is a shortcut for `build_configuration.version`.
|
197
|
+
|
198
|
+
## Creating step runners
|
199
|
+
|
200
|
+
The structure of all runners is the same. They must be defined within the
|
201
|
+
appropriate module, dependency resolvers in the `Bozo::DependencyResolvers`
|
202
|
+
module, project preparers must be defined within the `Bozo::Preparers`
|
203
|
+
module, compilers in the`Bozo::Compilers` module, test runners in the
|
204
|
+
`Bozo::TestRunners` module, packagers in the `Bozo::Packagers` module and
|
205
|
+
publishers in the `Bozo::Publishers` module. They must have a parameterless
|
206
|
+
constructor and they must expose an `#execute` method which will be invoked
|
207
|
+
when they should execute whatever task they are meant to perform. They can
|
208
|
+
optionally define a `#required_tools` method which returns the name of any
|
209
|
+
build tools it requires that cannot be retrieved through dependency
|
210
|
+
resolvers, for example a dependency resolving executable such as `nuget.exe`.
|
211
|
+
|
212
|
+
When executing a command line executable they should use the
|
213
|
+
`execute_command(tool, args)` method so that the command will be logged in if
|
214
|
+
the correct format and if executable completes with an error exit code the
|
215
|
+
build will be aborted. They should also use the `log_info(msg)` and
|
216
|
+
`log_debug(msg)` methods to ensure their output is formatted correctly and
|
217
|
+
the verbosity of the messages can be controlled centrally.
|
218
|
+
|
219
|
+
The runner will be passed back to the configuration code via an optional
|
220
|
+
block so if further configuration of the runner is possible, or required,
|
221
|
+
this should be exposed through public methods on the runner. If required
|
222
|
+
configuration is omitted then a `Bozo::ConfigurationError` with a message
|
223
|
+
explaining the problem and how to rectify it should be raised when the
|
224
|
+
`#execute` method of the runner is called.
|
225
|
+
|
226
|
+
### Registration
|
227
|
+
|
228
|
+
Runners are registered through step-specific methods:
|
229
|
+
|
230
|
+
* `dependency_resolver(identifier, &block)` registers dependency resolvers
|
231
|
+
* `prepare(identifier, &block)` registers project preparers
|
232
|
+
* `compile_with(identifier, &block)` registers compilers
|
233
|
+
* `test_with(identifier, &block)` registers test runners
|
234
|
+
* `package_with(identifier, &block)` registers packagers
|
235
|
+
* `publish_with(identifier, &block)` registers publishers
|
236
|
+
|
237
|
+
### Example
|
238
|
+
|
239
|
+
Here is an example of a 'compiler' that logs `"Hello, <name>!"` where name is
|
240
|
+
configured from the optional block and a `Bozo::ConfigurationError` is raised
|
241
|
+
if no name has been configured:
|
242
|
+
|
243
|
+
```ruby
|
244
|
+
module Bozo::Compilers
|
245
|
+
|
246
|
+
class HelloWorld
|
247
|
+
|
248
|
+
def name(name)
|
249
|
+
@name = name
|
250
|
+
end
|
251
|
+
|
252
|
+
def execute
|
253
|
+
raise Bozo::ConfigurationError.new('You must specify a name to say "Hello" to') if @name.nil?
|
254
|
+
log_info "Hello, #{@name}!"
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
```
|
261
|
+
|
262
|
+
This compiler would be added to your build via the configuration:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
compile_with :hello_world do |hw|
|
266
|
+
hw.name 'Bozo'
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
## Creating hooks
|
271
|
+
|
272
|
+
The structure of all hooks is the same. The must be defined within the
|
273
|
+
`Bozo::Hooks` module and they must have a parameterless constructor. They can
|
274
|
+
optionally define a `#required_tools` method which returns the name of any
|
275
|
+
build tools it requires that cannot be retrieved through dependency resolvers,
|
276
|
+
for example a dependency resolving executable such as `nuget.exe`.
|
277
|
+
|
278
|
+
When executing a command line executable they should use the
|
279
|
+
`execute_command(tool, args)` method so that the command will be logged in if
|
280
|
+
the correct format and if executable completes with an error exit code the
|
281
|
+
build will be aborted. They should also use the `log_info(msg)` and
|
282
|
+
`log_debug(msg)` methods to ensure their output is formatted correctly and the
|
283
|
+
verbosity of the messages can be controlled centrally.
|
284
|
+
|
285
|
+
The hook will be passed back to the configuration code via an optional block
|
286
|
+
so if further configuration of the hook is possible, or required, this should
|
287
|
+
be exposed through public methods on the hook. If required configuration is
|
288
|
+
omitted then a `Bozo::ConfigurationError` with a message explaining the
|
289
|
+
problem and how to rectify it should be raised when a hook method is called.
|
290
|
+
|
291
|
+
A hook can be called several times. In order to hook around a step all that is
|
292
|
+
required is that an appropriately named method is defined within the class.
|
293
|
+
For example, this hook logs a message both before and after the compile step
|
294
|
+
is run:
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
module Bozo::Hooks
|
298
|
+
|
299
|
+
class CompilingMessages
|
300
|
+
|
301
|
+
def pre_compile
|
302
|
+
log_info 'About to compile'
|
303
|
+
end
|
304
|
+
|
305
|
+
def post_compile
|
306
|
+
log_info 'Finished compiling'
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
```
|
313
|
+
|
314
|
+
Which steps the hook wants to execute on is determined by checking the
|
315
|
+
response to the `#respond_to?` method so if you wish to use `#method_missing`
|
316
|
+
to add functionality you need to ensure that the response to `#respond_to?`
|
317
|
+
reflects that.
|
318
|
+
|
319
|
+
### Registration
|
320
|
+
|
321
|
+
As hook instances can listen to one or more pre- or post-stage hooks there are
|
322
|
+
multiple ways to register a hook. However, they are all functionally identical
|
323
|
+
and are just aliases to the same method so that your configuration can read
|
324
|
+
more clearly.
|
325
|
+
|
326
|
+
The registration methods are:
|
327
|
+
|
328
|
+
* `with_hook(identifier, &block)` (recommended when hooking several stages)
|
329
|
+
* `pre_build(identifier, &block)`
|
330
|
+
* `post_build(identifier, &block)`
|
331
|
+
* `pre_clean(identifier, &block)`
|
332
|
+
* `post_clean(identifier, &block)`
|
333
|
+
* `pre_dependencies(identifier, &block)`
|
334
|
+
* `post_dependencies(identifier, &block)`
|
335
|
+
* `pre_prepare(identifier, &block)`
|
336
|
+
* `post_prepare(identifier, &block)`
|
337
|
+
* `pre_compile(identifier, &block)`
|
338
|
+
* `post_compile(identifier, &block)`
|
339
|
+
* `pre_test(identifier, &block)`
|
340
|
+
* `post_test(identifier, &block)`
|
341
|
+
* `pre_package(identifier, &block)`
|
342
|
+
* `post_package(identifier, &block)`
|
343
|
+
* `pre_publish(identifier, &block)`
|
344
|
+
* `post_publish(identifier, &block)`
|
345
|
+
|
346
|
+
## Build tools
|
347
|
+
|
348
|
+
Build tools are usually executables that you need to perform a task that are
|
349
|
+
not available via some other means.
|
350
|
+
|
351
|
+
For example, at Zopa we use in Nuget to resolve our .NET dependencies. This is
|
352
|
+
a chicken and egg situation in that you can't use a dependency management
|
353
|
+
system like Nuget until you've got a copy of the Nuget executable you can
|
354
|
+
call. The build tools function aims to resolve this loop of cyclical dependency.
|
355
|
+
|
356
|
+
Your build tools are resolve as the first part of the "resolve dependencies"
|
357
|
+
step. When possible you should use real package management systems to retrieve
|
358
|
+
dependencies rather than using the build tools function.
|
359
|
+
|
360
|
+
### Specifying required build tools
|
361
|
+
|
362
|
+
All the runners and hooks you create can optionally specify a `required_tools`
|
363
|
+
method which returns the name of one or more required build tools:
|
364
|
+
|
365
|
+
```ruby
|
366
|
+
module Bozo::DependencyResolvers
|
367
|
+
|
368
|
+
class Nuget
|
369
|
+
|
370
|
+
def required_tools
|
371
|
+
:nuget # or for many [:nuget, :open_wrap]
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
```
|
378
|
+
|
379
|
+
### How it works
|
380
|
+
|
381
|
+
Within the example configuration there is a single line:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
build_tools_location '//SERVER/network/path' # Defines the location build tools can be copied from
|
385
|
+
```
|
386
|
+
|
387
|
+
This specifies the location that build tools should be retrieved from. This
|
388
|
+
location is then joined with the name of the build tool to find the directory
|
389
|
+
that must be copied into the `./build/tools` directory. For example with a
|
390
|
+
`build_tools_location` of `//SERVER/network/path` along with a required
|
391
|
+
build tool called `:nuget` will result in the directory
|
392
|
+
`//SERVER/network/path/nuget` being copied to `./build/tools/nuget` directory.
|
393
|
+
By knowing the contents of this directory you can then invoke the executables
|
394
|
+
contained within it:
|
395
|
+
|
396
|
+
```ruby
|
397
|
+
module Bozo::DependencyResolvers
|
398
|
+
|
399
|
+
class Nuget
|
400
|
+
|
401
|
+
def execute
|
402
|
+
execute_command :nuget, File.join('build', 'tools', 'nuget', 'NuGet.exe')
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
end
|
408
|
+
```
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.3
|