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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MDMyMGEyNGUwMzNjMjFjNjY2NTg2MWQyMjE5ZGFkMWIxYWMzYWM5Mg==
4
+ YzliYmE5YTJhYmMzY2NiOWZmZWQyMGUwZGIxMzdjOTkzYWNiZmYzOA==
5
5
  data.tar.gz: !binary |-
6
- ZjMwNWM2ODk0NmU3NjU3YzgzNDY2N2RiMmIzYTQxY2MyMzhlZGIyMA==
6
+ YTYyZGFjZjNiODRhMzBjZjM4MTU4ZmQzYmNhMmYwOWI5OWUyOTYyMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NDk1Nzc5ZTBlOTA5OTBmOWJhNzJlYzc1MTI1YjA2NjFhMzI1MmNlZmE1NWRi
10
- NzU1MTY3ODcxOTc5MDExNDczYzQzNzdlMGJkYmM0ZDJkOTZhMzk5MWE4MTI2
11
- NGE2ZjQxZmZjMWY1MzUzN2M1MWQ4YTc3NThlZmE2ZWQ0ZGRjZjg=
9
+ MmExMTBhMDEwNmQwYWEwYjIyNWExOTU4ZGQxN2MwMmYxNjdkYjlkNjM0NzFj
10
+ OTk3MmEwZDYyOTA3MDhhY2U5ZDM2ZTE5ODRhMzk5NDkzNzM4ZmEwMGNlZDBi
11
+ NzAyZDQ1YTM4MzljYTBmMzM2NDY3YTFlMTg3ZWRmZDg2NzFlNTc=
12
12
  data.tar.gz: !binary |-
13
- ZTA1NWE1NWViMjc1NTY4MjM2MzIyM2JkMGI4ZDVjYzNmMDY4NzNjZmZkODFl
14
- YWE2NWY0ZWFiZTg4OTRlODM0NTI3ZmE2MzY4N2Y5NTg4ZDBjNzE2YWI1ZTg1
15
- MWI5YzViNDdlYzEzZmNlNjM4OWJlMGQ2YWQ5NDMyOWQxNWVkNzM=
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
data/lib/bozo/bozo.rb ADDED
@@ -0,0 +1,7 @@
1
+ # The top level module for Bozo's functionality.
2
+ module Bozo
3
+
4
+ # The version of Bozo in use.
5
+ VERSION = File.read(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../../VERSION')).strip
6
+
7
+ end