bozo 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGUwMTRlYmExMGUzY2FhMGMxMGI1YWRhOTE1Njg4ZTQ2NDk2MzM4NA==
4
+ MTZhNmM4OTA4NjQwZDI3NTUxN2I0MDE4NmYyNTJmOTg0OGViOGZmMA==
5
5
  data.tar.gz: !binary |-
6
- OGY3NmY1ZmI2MmVlMjg4NjhlY2NiYjU0ZjZkYjJjNTM2YjYwZWVhYw==
6
+ N2EwMGFlOTJhZTFmMjI5MzQ2MjQzMzQ4OTAxZGQ2NTU1OGQwMTQxYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTU5Y2UxZjRiOGY0ZjNmMGRjMjlmYjI2NmEwYWVmYWYxY2YwNTFjOWY3NTNj
10
- Mjc4NGM1OWRkNWJmYmQ3MDgxMjJlNmU0NGYwYjcxMjRiZDE0Y2Y1NjRlZjVl
11
- MmJhYTZhOTJhNzkyODkyMDVkZDQ0MjJmYjg3NjY3OWI3NjUzMDk=
9
+ ZmM1YzhiZmEwYjE3YWJiMGE1MTMzNTU3NWUyNjdiZjU0NGRiZTk5MGRmNjI1
10
+ MThiZWY5ODI2ZDZjZjQwNjg3NGY1ZGNjZWY3ZGRjMjdiNGVjZWQ3NDRjNmRl
11
+ YjY3Nzk4ODYxYTFmMzBkMGU3MTFkYTRhMGU5NTFkMmMzMjMxNTk=
12
12
  data.tar.gz: !binary |-
13
- YjIwODU3NjQ4YmU5OTc2ZTJhMzZhYTc2ZDExNWE0OWFlY2M1MGE4ZmMzMjM1
14
- ZWE1MDUwYmI0YTJiNGVmODY3YWE4NmZlNDBiYjYwOTQ4MDMyZWE4NjY4MDg1
15
- NDk0NTg4YWE2ZTRjMTFjMDVjMDUyNmRhYjBlODI1MGVlZGI0YWE=
13
+ OTJmNmFmYWJkY2M0Y2I4MWY3ODU2MjY0ZWQ3Mjg5YmQyM2MxYTYwNmY2Y2Rj
14
+ MDc0YTY2NzQ1YTM1NWRkMDgwOGI5YTkwMmRmNDY1MjU2ZTZlNTU0YjcyMDli
15
+ YTg5MWJjZTNkMWMwOTdlZmFhZTUxNGI0ZDdhNWQwZWU2MzMxYzk=
data/README.md CHANGED
@@ -1,427 +1,444 @@
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
- ### pre_release?
124
-
125
- Returns `true` when the build is being run with the `--pre-release` switch,
126
- otherwise `false`.
127
-
128
- This is a shortcut for `params[:pre_release]`.
129
-
130
- ### env
131
-
132
- Returns the hash of environment variables. Initially populated by calling
133
- `ENV.to_hash` this may be added to by runners and hooks to enable lightweight
134
- communication and to cache the result of expensive calls.
135
-
136
- ### environment
137
-
138
- Returns the name of the environment that the build is running in, eg.
139
- `'development'`.
140
-
141
- This is a shortcut for `global_params[:environment]`.
142
-
143
- ### execute_command(tool, args)
144
-
145
- Executes a command line tool.
146
-
147
- Raises a `Bozo::ExecutionError` if the command responds with a non-zero exit
148
- code.
149
-
150
- #### Parameters
151
-
152
- * __tool [Symbol]__ A friendly identifier for the tool
153
- * __args [Array]__ An array of arguments making up the command to execute
154
-
155
- ### global_params
156
-
157
- Returns the hash of global parameters passed to bozo. All key symbols are
158
- converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
159
- idiomatic for Ruby.
160
-
161
- ### log_debug(msg)
162
-
163
- Records an `debug` log message.
164
-
165
- #### Parameters
166
-
167
- * __msg [String]__ The message to log
168
-
169
- ### log_fatal(msg)
170
-
171
- Records an `fatal` log message.
172
-
173
- #### Parameters
174
-
175
- * __msg [String]__ The message to log
176
-
177
- ### log_info(msg)
178
-
179
- Records an `info` log message.
180
-
181
- #### Parameters
182
-
183
- * __msg [String]__ The message to log
184
-
185
- ### log_warn(msg)
186
-
187
- Records an `warn` log message.
188
-
189
- #### Parameters
190
-
191
- * __msg [String]__ The message to log
192
-
193
- ### params
194
-
195
- Returns the hash of command parameters passed to bozo. All key symbols are
196
- converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
197
- idiomatic for Ruby.
198
-
199
- ### version
200
-
201
- Returns the version of the build.
202
-
203
- This is a shortcut for `build_configuration.version`.
204
-
205
- ## Creating step runners
206
-
207
- The structure of all runners is the same. They must be defined within the
208
- appropriate module, dependency resolvers in the `Bozo::DependencyResolvers`
209
- module, project preparers must be defined within the `Bozo::Preparers`
210
- module, compilers in the`Bozo::Compilers` module, test runners in the
211
- `Bozo::TestRunners` module, packagers in the `Bozo::Packagers` module and
212
- publishers in the `Bozo::Publishers` module. They must have a parameterless
213
- constructor and they must expose an `#execute` method which will be invoked
214
- when they should execute whatever task they are meant to perform. They can
215
- optionally define a `#required_tools` method which returns the name of any
216
- build tools it requires that cannot be retrieved through dependency
217
- resolvers, for example a dependency resolving executable such as `nuget.exe`.
218
-
219
- When executing a command line executable they should use the
220
- `execute_command(tool, args)` method so that the command will be logged in if
221
- the correct format and if executable completes with an error exit code the
222
- build will be aborted. They should also use the `log_info(msg)` and
223
- `log_debug(msg)` methods to ensure their output is formatted correctly and
224
- the verbosity of the messages can be controlled centrally.
225
-
226
- The runner will be passed back to the configuration code via an optional
227
- block so if further configuration of the runner is possible, or required,
228
- this should be exposed through public methods on the runner. If required
229
- configuration is omitted then a `Bozo::ConfigurationError` with a message
230
- explaining the problem and how to rectify it should be raised when the
231
- `#execute` method of the runner is called.
232
-
233
- ### Registration
234
-
235
- Runners are registered through step-specific methods:
236
-
237
- * `dependency_resolver(identifier, &block)` registers dependency resolvers
238
- * `prepare(identifier, &block)` registers project preparers
239
- * `compile_with(identifier, &block)` registers compilers
240
- * `test_with(identifier, &block)` registers test runners
241
- * `package_with(identifier, &block)` registers packagers
242
- * `publish_with(identifier, &block)` registers publishers
243
-
244
- ### Example
245
-
246
- Here is an example of a 'compiler' that logs `"Hello, <name>!"` where name is
247
- configured from the optional block and a `Bozo::ConfigurationError` is raised
248
- if no name has been configured:
249
-
250
- ```ruby
251
- module Bozo::Compilers
252
-
253
- class HelloWorld
254
-
255
- def name(name)
256
- @name = name
257
- end
258
-
259
- def execute
260
- raise Bozo::ConfigurationError.new('You must specify a name to say "Hello" to') if @name.nil?
261
- log_info "Hello, #{@name}!"
262
- end
263
-
264
- end
265
-
266
- end
267
- ```
268
-
269
- This compiler would be added to your build via the configuration:
270
-
271
- ```ruby
272
- compile_with :hello_world do |hw|
273
- hw.name 'Bozo'
274
- end
275
- ```
276
-
277
- ## Creating hooks
278
-
279
- The structure of all hooks is the same. The must be defined within the
280
- `Bozo::Hooks` module and they must have a parameterless constructor. They can
281
- optionally define a `#required_tools` method which returns the name of any
282
- build tools it requires that cannot be retrieved through dependency resolvers,
283
- for example a dependency resolving executable such as `nuget.exe`.
284
-
285
- When executing a command line executable they should use the
286
- `execute_command(tool, args)` method so that the command will be logged in if
287
- the correct format and if executable completes with an error exit code the
288
- build will be aborted. They should also use the `log_info(msg)` and
289
- `log_debug(msg)` methods to ensure their output is formatted correctly and the
290
- verbosity of the messages can be controlled centrally.
291
-
292
- The hook will be passed back to the configuration code via an optional block
293
- so if further configuration of the hook is possible, or required, this should
294
- be exposed through public methods on the hook. If required configuration is
295
- omitted then a `Bozo::ConfigurationError` with a message explaining the
296
- problem and how to rectify it should be raised when a hook method is called.
297
-
298
- A hook can be called several times. In order to hook around a step all that is
299
- required is that an appropriately named method is defined within the class.
300
- For example, this hook logs a message both before and after the compile step
301
- is run:
302
-
303
- ```ruby
304
- module Bozo::Hooks
305
-
306
- class CompilingMessages
307
-
308
- def pre_compile
309
- log_info 'About to compile'
310
- end
311
-
312
- def post_compile
313
- log_info 'Finished compiling'
314
- end
315
-
316
- end
317
-
318
- end
319
- ```
320
-
321
- Which steps the hook wants to execute on is determined by checking the
322
- response to the `#respond_to?` method so if you wish to use `#method_missing`
323
- to add functionality you need to ensure that the response to `#respond_to?`
324
- reflects that.
325
-
326
- ### Registration
327
-
328
- As hook instances can listen to one or more pre- or post-stage hooks there are
329
- multiple ways to register a hook. However, they are all functionally identical
330
- and are just aliases to the same method so that your configuration can read
331
- more clearly.
332
-
333
- The registration methods are:
334
-
335
- * `with_hook(identifier, &block)` (recommended when hooking several stages)
336
- * `pre_build(identifier, &block)`
337
- * `post_build(identifier, &block)`
338
- * `pre_clean(identifier, &block)`
339
- * `post_clean(identifier, &block)`
340
- * `pre_dependencies(identifier, &block)`
341
- * `post_dependencies(identifier, &block)`
342
- * `pre_prepare(identifier, &block)`
343
- * `post_prepare(identifier, &block)`
344
- * `pre_compile(identifier, &block)`
345
- * `post_compile(identifier, &block)`
346
- * `pre_test(identifier, &block)`
347
- * `post_test(identifier, &block)`
348
- * `pre_package(identifier, &block)`
349
- * `post_package(identifier, &block)`
350
- * `pre_publish(identifier, &block)`
351
- * `post_publish(identifier, &block)`
352
-
353
- Failed hooks exist that are called when a stage fails, in these cases the
354
- relevant `post` hook is not called.
355
-
356
- * `failed_build(identifier, &block)`
357
- * `failed_clean(identifier, &block)`
358
- * `failed_dependencies(identifier, &block)`
359
- * `failed_prepare(identifier, &block)`
360
- * `failed_compile(identifier, &block)`
361
- * `failed_test(identifier, &block)`
362
- * `failed_package(identifier, &block)`
363
- * `failed_publish(identifier, &block)`
364
-
365
- ## Build tools
366
-
367
- Build tools are usually executables that you need to perform a task that are
368
- not available via some other means.
369
-
370
- For example, at Zopa we use in Nuget to resolve our .NET dependencies. This is
371
- a chicken and egg situation in that you can't use a dependency management
372
- system like Nuget until you've got a copy of the Nuget executable you can
373
- call. The build tools function aims to resolve this loop of cyclical dependency.
374
-
375
- Your build tools are resolve as the first part of the "resolve dependencies"
376
- step. When possible you should use real package management systems to retrieve
377
- dependencies rather than using the build tools function.
378
-
379
- ### Specifying required build tools
380
-
381
- All the runners and hooks you create can optionally specify a `required_tools`
382
- method which returns the name of one or more required build tools:
383
-
384
- ```ruby
385
- module Bozo::DependencyResolvers
386
-
387
- class Nuget
388
-
389
- def required_tools
390
- :nuget # or for many [:nuget, :open_wrap]
391
- end
392
-
393
- end
394
-
395
- end
396
- ```
397
-
398
- ### How it works
399
-
400
- Within the example configuration there is a single line:
401
-
402
- ```ruby
403
- build_tools_location '//SERVER/network/path' # Defines the location build tools can be copied from
404
- ```
405
-
406
- This specifies the location that build tools should be retrieved from. This
407
- location is then joined with the name of the build tool to find the directory
408
- that must be copied into the `./build/tools` directory. For example with a
409
- `build_tools_location` of `//SERVER/network/path` along with a required
410
- build tool called `:nuget` will result in the directory
411
- `//SERVER/network/path/nuget` being copied to `./build/tools/nuget` directory.
412
- By knowing the contents of this directory you can then invoke the executables
413
- contained within it:
414
-
415
- ```ruby
416
- module Bozo::DependencyResolvers
417
-
418
- class Nuget
419
-
420
- def execute
421
- execute_command :nuget, File.join('build', 'tools', 'nuget', 'NuGet.exe')
422
- end
423
-
424
- end
425
-
426
- end
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
+ ### pre_release?
124
+
125
+ Returns `true` when the build is being run with the `--pre-release` switch,
126
+ otherwise `false`.
127
+
128
+ This is a shortcut for `params[:pre_release]`.
129
+
130
+ ### env
131
+
132
+ Returns the hash of environment variables. Initially populated by calling
133
+ `ENV.to_hash` this may be added to by runners and hooks to enable lightweight
134
+ communication and to cache the result of expensive calls.
135
+
136
+ ### environment
137
+
138
+ Returns the name of the environment that the build is running in, eg.
139
+ `'development'`.
140
+
141
+ This is a shortcut for `global_params[:environment]`.
142
+
143
+ ### execute_command(tool, args)
144
+
145
+ Executes a command line tool.
146
+
147
+ Raises a `Bozo::ExecutionError` if the command responds with a non-zero exit
148
+ code.
149
+
150
+ #### Parameters
151
+
152
+ * __tool [Symbol]__ A friendly identifier for the tool
153
+ * __args [Array]__ An array of arguments making up the command to execute
154
+
155
+ ### global_params
156
+
157
+ Returns the hash of global parameters passed to bozo. All key symbols are
158
+ converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
159
+ idiomatic for Ruby.
160
+
161
+ ### log_debug(msg)
162
+
163
+ Records an `debug` log message.
164
+
165
+ #### Parameters
166
+
167
+ * __msg [String]__ The message to log
168
+
169
+ ### log_fatal(msg)
170
+
171
+ Records an `fatal` log message.
172
+
173
+ #### Parameters
174
+
175
+ * __msg [String]__ The message to log
176
+
177
+ ### log_info(msg)
178
+
179
+ Records an `info` log message.
180
+
181
+ #### Parameters
182
+
183
+ * __msg [String]__ The message to log
184
+
185
+ ### log_warn(msg)
186
+
187
+ Records an `warn` log message.
188
+
189
+ #### Parameters
190
+
191
+ * __msg [String]__ The message to log
192
+
193
+ ### params
194
+
195
+ Returns the hash of command parameters passed to bozo. All key symbols are
196
+ converted from the CLI style of `:'multi-word'` to `:multi_word` to be more
197
+ idiomatic for Ruby.
198
+
199
+ ### version
200
+
201
+ Returns the version of the build.
202
+
203
+ This is a shortcut for `build_configuration.version`.
204
+
205
+ ## Creating step runners
206
+
207
+ The structure of all runners is the same. They must be defined within the
208
+ appropriate module, dependency resolvers in the `Bozo::DependencyResolvers`
209
+ module, project preparers must be defined within the `Bozo::Preparers`
210
+ module, compilers in the`Bozo::Compilers` module, test runners in the
211
+ `Bozo::TestRunners` module, packagers in the `Bozo::Packagers` module and
212
+ publishers in the `Bozo::Publishers` module. They must have a parameterless
213
+ constructor and they must expose an `#execute` method which will be invoked
214
+ when they should execute whatever task they are meant to perform. They can
215
+ optionally define a `#required_tools` method which returns the name of any
216
+ build tools it requires that cannot be retrieved through dependency
217
+ resolvers, for example a dependency resolving executable such as `nuget.exe`.
218
+
219
+ When executing a command line executable they should use the
220
+ `execute_command(tool, args)` method so that the command will be logged in if
221
+ the correct format and if executable completes with an error exit code the
222
+ build will be aborted. They should also use the `log_info(msg)` and
223
+ `log_debug(msg)` methods to ensure their output is formatted correctly and
224
+ the verbosity of the messages can be controlled centrally.
225
+
226
+ The runner will be passed back to the configuration code via an optional
227
+ block so if further configuration of the runner is possible, or required,
228
+ this should be exposed through public methods on the runner. If required
229
+ configuration is omitted then a `Bozo::ConfigurationError` with a message
230
+ explaining the problem and how to rectify it should be raised when the
231
+ `#execute` method of the runner is called.
232
+
233
+ ### Registration
234
+
235
+ Runners are registered through step-specific methods:
236
+
237
+ * `dependency_resolver(identifier, &block)` registers dependency resolvers
238
+ * `prepare(identifier, &block)` registers project preparers
239
+ * `compile_with(identifier, &block)` registers compilers
240
+ * `test_with(identifier, &block)` registers test runners
241
+ * `package_with(identifier, &block)` registers packagers
242
+ * `publish_with(identifier, &block)` registers publishers
243
+
244
+ ### Example
245
+
246
+ Here is an example of a 'compiler' that logs `"Hello, <name>!"` where name is
247
+ configured from the optional block and a `Bozo::ConfigurationError` is raised
248
+ if no name has been configured:
249
+
250
+ ```ruby
251
+ module Bozo::Compilers
252
+
253
+ class HelloWorld
254
+
255
+ def name(name)
256
+ @name = name
257
+ end
258
+
259
+ def execute
260
+ raise Bozo::ConfigurationError.new('You must specify a name to say "Hello" to') if @name.nil?
261
+ log_info "Hello, #{@name}!"
262
+ end
263
+
264
+ end
265
+
266
+ end
267
+ ```
268
+
269
+ This compiler would be added to your build via the configuration:
270
+
271
+ ```ruby
272
+ compile_with :hello_world do |hw|
273
+ hw.name 'Bozo'
274
+ end
275
+ ```
276
+
277
+ ## Creating hooks
278
+
279
+ The structure of all hooks is the same. The must be defined within the
280
+ `Bozo::Hooks` module and they must have a parameterless constructor. They can
281
+ optionally define a `#required_tools` method which returns the name of any
282
+ build tools it requires that cannot be retrieved through dependency resolvers,
283
+ for example a dependency resolving executable such as `nuget.exe`.
284
+
285
+ When executing a command line executable they should use the
286
+ `execute_command(tool, args)` method so that the command will be logged in if
287
+ the correct format and if executable completes with an error exit code the
288
+ build will be aborted. They should also use the `log_info(msg)` and
289
+ `log_debug(msg)` methods to ensure their output is formatted correctly and the
290
+ verbosity of the messages can be controlled centrally.
291
+
292
+ The hook will be passed back to the configuration code via an optional block
293
+ so if further configuration of the hook is possible, or required, this should
294
+ be exposed through public methods on the hook. If required configuration is
295
+ omitted then a `Bozo::ConfigurationError` with a message explaining the
296
+ problem and how to rectify it should be raised when a hook method is called.
297
+
298
+ A hook can be called several times. In order to hook around a step all that is
299
+ required is that an appropriately named method is defined within the class.
300
+ For example, this hook logs a message both before and after the compile step
301
+ is run:
302
+
303
+ ```ruby
304
+ module Bozo::Hooks
305
+
306
+ class CompilingMessages
307
+
308
+ def pre_compile
309
+ log_info 'About to compile'
310
+ end
311
+
312
+ def post_compile
313
+ log_info 'Finished compiling'
314
+ end
315
+
316
+ end
317
+
318
+ end
319
+ ```
320
+
321
+ Which steps the hook wants to execute on is determined by checking the
322
+ response to the `#respond_to?` method so if you wish to use `#method_missing`
323
+ to add functionality you need to ensure that the response to `#respond_to?`
324
+ reflects that.
325
+
326
+ ### Registration
327
+
328
+ As hook instances can listen to one or more pre- or post-stage hooks there are
329
+ multiple ways to register a hook. However, they are all functionally identical
330
+ and are just aliases to the same method so that your configuration can read
331
+ more clearly.
332
+
333
+ The registration methods are:
334
+
335
+ * `with_hook(identifier, &block)` (recommended when hooking several stages)
336
+ * `pre_build(identifier, &block)`
337
+ * `post_build(identifier, &block)`
338
+ * `pre_clean(identifier, &block)`
339
+ * `post_clean(identifier, &block)`
340
+ * `pre_dependencies(identifier, &block)`
341
+ * `post_dependencies(identifier, &block)`
342
+ * `pre_prepare(identifier, &block)`
343
+ * `post_prepare(identifier, &block)`
344
+ * `pre_compile(identifier, &block)`
345
+ * `post_compile(identifier, &block)`
346
+ * `pre_test(identifier, &block)`
347
+ * `post_test(identifier, &block)`
348
+ * `pre_package(identifier, &block)`
349
+ * `post_package(identifier, &block)`
350
+ * `pre_publish(identifier, &block)`
351
+ * `post_publish(identifier, &block)`
352
+
353
+ Failed hooks exist that are called when a stage fails, in these cases the
354
+ relevant `post` hook is not called.
355
+
356
+ * `failed_build(identifier, &block)`
357
+ * `failed_clean(identifier, &block)`
358
+ * `failed_dependencies(identifier, &block)`
359
+ * `failed_prepare(identifier, &block)`
360
+ * `failed_compile(identifier, &block)`
361
+ * `failed_test(identifier, &block)`
362
+ * `failed_package(identifier, &block)`
363
+ * `failed_publish(identifier, &block)`
364
+
365
+ ## Build tools
366
+
367
+ Build tools are usually executables that you need to perform a task that are
368
+ not available via some other means.
369
+
370
+ For example, at Zopa we use in Nuget to resolve our .NET dependencies. This is
371
+ a chicken and egg situation in that you can't use a dependency management
372
+ system like Nuget until you've got a copy of the Nuget executable you can
373
+ call. The build tools function aims to resolve this loop of cyclical dependency.
374
+
375
+ Your build tools are resolved as the first part of the "resolve dependencies"
376
+ step. When possible you should use real package management systems to retrieve
377
+ dependencies rather than using the build tools function.
378
+
379
+ ### Specifying required build tools
380
+
381
+ All the runners and hooks you create can optionally specify a `required_tools`
382
+ method which returns the name of one or more required build tools:
383
+
384
+ ```ruby
385
+ module Bozo::DependencyResolvers
386
+
387
+ class Nuget
388
+
389
+ def required_tools
390
+ :nuget # or for many [:nuget, :open_wrap]
391
+ end
392
+
393
+ end
394
+
395
+ end
396
+ ```
397
+
398
+ Tools that aren't `required_tools` of another runner can be specified using the following:
399
+
400
+ ```ruby
401
+ required_tool :nuget
402
+
403
+ required_tool :tool_with_configuration do |n|
404
+ n.tool_version '1.0'
405
+ end
406
+ ```
407
+
408
+ In the case of the configuration `required_tool` method only the `Bozo::Tools` module is used.
409
+
410
+ ### How it works
411
+
412
+ There are two ways which tools may be resolved when required by another module, either
413
+ from the `build_tools_location` or via a `Bozo::Tool` module class. A class in the `Bozo::Tool` module
414
+ takes priority over the `build_tools_location`, if Bozo fails to find a class with the same name then
415
+ the `build_tools_location` is used.
416
+
417
+ Within the example configuration there is a single line:
418
+
419
+ ```ruby
420
+ build_tools_location '//SERVER/network/path' # Defines the location build tools can be copied from
421
+ ```
422
+
423
+ This specifies the location that build tools should be retrieved from. This
424
+ location is then joined with the name of the build tool to find the directory
425
+ that must be copied into the `./build/tools` directory. For example with a
426
+ `build_tools_location` of `//SERVER/network/path` along with a required
427
+ build tool called `:nuget` will result in the directory
428
+ `//SERVER/network/path/nuget` being copied to `./build/tools/nuget` directory.
429
+ By knowing the contents of this directory you can then invoke the executables
430
+ contained within it:
431
+
432
+ ```ruby
433
+ module Bozo::DependencyResolvers
434
+
435
+ class Nuget
436
+
437
+ def execute
438
+ execute_command :nuget, File.join('build', 'tools', 'nuget', 'NuGet.exe')
439
+ end
440
+
441
+ end
442
+
443
+ end
427
444
  ```