Albacore v0.2.0 Preview 2 Is Available
I’ve pushed another preview release of albacore up to rubygems.org. This release builds on the changes that I talked about in the Preview 1 Notes and adds (what I think is) some great new capabilities for contributors and end-users, both.
Installing The Preview
This is all you need to install the preview version:
1: gem install albacore --pre
</div> </div>
The inclusion of ‘–pre’ on the command line will tell the gem system that you want to install the latest preview version of albacore. You will then need to modify your rake file to use the preview version (v0.2.0.preview2):
1: require 'rubygems'
2: gem 'albacore', '=0.2.0.preview2'
3: require 'albacore'
4:
</div> </div>
The second line tells the gem system to use the specific version of Albacore that you want, when the Albacore gem is required.
A Refocus (Again)
In the preview 1 notes, I talked about a few tasks being removed and gave a reason why – to focus albacore down to it’s core of build related tasks. In the time since then, there has been numerous discussions of this on the albacore mailing list. The end result of the discussion was a realization that the focus of albacore should not be “build” vs deploy tasks, but “high quality, value adding” tasks related to building .NET based systems. This shift in focus came after some great counterpoints and discussion on how build vs. deploy is often a gray area, and how splitting out into multiple gems for these concerns would likely be a bad thing in the long run. Rather than focus on an arbitrary distinction such as build vs. deploy, we are now moving forward with the idea that the tasks we do include should be of the highest quality and should add significant value. We shouldn’t repeat a task or a capability that is found elsewhere in ruby or a ruby gem unless we are creating something that is truly valuable and unique in comparison.
Note that the tasks listed as going away in the preview 1 notes are still going away. We are simply re-stating why they are going away: they didn’t add value, or they duplicated functionality that can be found elsewhere.
Albacore Task Updates
There are not a lot of task updates in this preview release, but the ones that are there are fairly significant.
CSC Task
A handful of new options have been put into this task, which should hopefully make it close to if not ready for prime-time. I imagine that we’ll still need some additional options, but this version of the csc task is on the right track.
The new options include:
- debug: tell csc whether or not (and how much) debug information to put into the assembly.
- define: set compiler symbols for your builds
- doc: generate xml documentation for your assembly
- optimize: optimize the code in your assembly
- resources: embed resources into your assembly. this is a simple version that only embeds files directly. no options for identifier or accessibility exist, yet.
1: csc :build do |csc|
2: csc.resources "file1", "file2", ... "fileN"
3: csc.debug = true # true, false, :full, :pdbonly
4: csc.define :whatever, :something, :etc
5: csc.doc = "path/to/docfile.xml"
6: csc.optimize = true # true or false
7: end
</div> </div>
For more information on these options, see the csc command line documentation.
SQLCmd Task
A few new attributes have been added to this task that will make it easier to use and add more options for authentication. These options include:
- trusted_connection: use a trusted connection instead of supplying a username and password
- batch_abort: “on error batch abort” – causes sqlcmd to return a failure code if any of the scripts run encounters an error
There are some behavioral changes related to these options, as well. If you do not specify a username and password, then the sqlcmd task will default to a trusted connection. This means you don’t need to specify any authentication information or options when setting up your sqlcmd tasks and sqlcmd will assume you want to use a trusted connection. If you specify a username OR password, though, the sqlcmd task will assume you do not want a trusted connection. You can manually override the trusted connection behavior by specify .trusted_connection in your tasks.
Batch abort will be assumed, by default, if you provide more than one script for sqlcmd to run. You can override this behavior by explicitly setting .batch_abort to false in your tasks.
And finally, the task will search your “program files” folder for SQL Server 2005 or 2008 if you don’t specify a .command attribute, directly. Note that it currently does not look in the “x86” program files folder on x64 machines. That will be done hopefully in the next release (preview or final release of v0.2.0).
1: sqlcmd :runscripts do |sql|
2: sql.trusted_connection = true # or false
3: sql.batch_abort = true # or false
4: end
</div> </div>
For more information on the new options, see the sqlcmd documentation.
AssemblyInfo Task
To support attributes that need more complex parameters or have other complex needs, a .custom_attributes attribute has been added to the assemblyinfo task.
1: assemblyinfo do |asm|
2: asm.custom_data(
3: '[assembly: XmlnsDefinition("http://www.acme.com", "Acme.Common.I18N")]',
4: '[assembly: XmlnsDefinition("http://www.acme.com", "Acme.Views.Helpers")]'
5: )
6: end
</div> </div>
Internal Cleanup And A Plug-In System
This release has a lot of internal cleanup of the codebase, the way tasks are created, the handling of the Albacore.configure block along with the code that plugs into it, and much more. In addition to removing many of the files that used to make up albacore (as they were no longer needed), we also reduced the size of the gem from ~400K downto ~40K by filtering out additional files that are not necessary at runtime. This means albacore will download and install faster than ever! This should also reduce the amount of time it takes to load the albacore codebase in your rake tasks.
The net result of the cleanup effort has produced a lot of good results: a reduction in the number of files that represent that albacore framework; an easier to work with framework that allows tasks to be created with only a simple include statement; and a plug-in system that allows contributors and end-users with specific needs not currently baked into albacore to develop their own tasks and plug directly into the albacore configuration with ease.
Custom Tasks
It’s now easier than ever to task advantage of the albacore features and create your own rake tasks. I’ve talked about how simple it is to create your own rake tasks, already, but the albacore framework gives you more than just a way to create tasks. It also gives you access to a unified logger, the configuration api, easy-to-create and use hash and array attributes for your object model, and more.
To create your own task with the albacore framework, you only need to do a few things:
- “include AlbacoreTask”. this module will bring most of the albacore functionality into your class and it will create a custom rake task for you, using the name of your class.
- a no-args initializer. all albacore task classes need to have an initializer that can be run with no parameters. you can allow optional parameters if you want.
- an execute method. all albacore task classes need to have an execute method – again, with no parameters – so that the task can call .execute on your class
I’ve built a small example task to replace the old ‘expandtemplates’ task (which is deprecated in v0.2.0). This new version of the task uses the build in ERB functionality of ruby and accepts a hash as the key / value data to populate the ERB template.
1: require 'erb'
2:
3: class ExpandTemplate
4: include AlbacoreTask
5:
6: attr_accessor :template, :output
7: attr_hash :settings
8:
9: def execute
10: expand_template(@template, @output, @settings)
11: end
12:
13: def expand_template(template_file, output_file, settings)
14: template = File.read template_file
15:
16: vars = OpenStruct.new(settings)
17: vars_binding = vars.send(:binding)
18:
19: erb = ERB.new template
20: output = erb.result(vars_binding)
21:
22: File.open(output_file, "w") do |file|
23: puts "Generating #{file.path}"
24: file.write(output)
25: end
26: end
27: end
</div> </div>
Once you have this class defined in a file, you only need to “require” it in your rakefile (or you can put this class directly in your rakefile if you want). The inclusion of “AlbacoreTask” on line 4 will automatically create an “expandtemplate” task for you. You can then call the task like any other albacore or other rake task:
1: expandtemplate :appconfig do |tmp|
2: tmp.template = "templates/app.config.template"
3: tmp.output = Files[:output] + ".config"
4: tmp.settings(
5: :mysetting => "this is some settings",
6: :connectionstring => "some connection string"
7: )
8: end
</div> </div>
To see this example do it’s thing, take a look at my vimbacore project on github. It’s my playground where I test out a lot of the new features and functionality of albacore, and I’ve included this (and a config example) in that project.
Custom Task Names
There are times when you want to name a task’s class one thing, but you want to have the task method (the method that you call in your rakefile) named something else. An example of this in albacore is the “nunit” task. The class that runs and defines this task is actually called NunitTestRunner. To avoid having tasks with long, ugly names like that, you can specify one (or more) task method names in your class by specifying a “TaskName” constant prior to the “include AlbacoreTask” line in your class. Here’s how the NunitTestRunner class is defined:
1: class NUnitTestRunner
2: TaskName = :nunit
3: include AlbacoreTask
4: # ...
5: end
</div> </div>
The use of “TaskName = :nunit” instructs albacore to create the task method “nunit” instead of “nunittestrunner”. You can also specify multiple names if you want aliases for your task:
1: class MyCustomTask
2: TaskName = [:task1, :task2, :taskN]
3: include AlbacoreTask
4: end
</div> </div>
This will create 3 task methods that you can use from your rakefile: task1, task2 and taskN.
1: task1 :foo do |t|
2: # ...
3: end
4:
5: task2 :bar do |t|
6: # ...
7: end
8:
9: taskN :baz do |t|
10: # ...
11: end
</div> </div>
Custom Configuration
The Albacore.configure block also support plug-in capabilities. All you need to do is create a ruby module that includes “Albacore::Configuration” and your module will automatically become part of the Albacore.configure block. Here’s an example that doesn’t really do much (again, this example is in my vimbacore project) but illustrates how simple it is:
1: module ExpandTemplateConfig
2: include Albacore::Configuration
3:
4: def expandtemplate
5: puts "..........Albacore.configure.expandtemplate was called. This is a demonstration of the configuration plugin system.rnrn"
6: end
7: end
</div> </div>
You can then call .expandtemplate in the Albacore.configure block:
1: Albacore.configure do |config|
2: config.expandtemplate
3: end
</div> </div>
Like I said – this example doesn’t do much. But it does illustrate how simple it is to create a plugin for the configuration system.
Automatic Configuration Mixins
If you are creating your own tasks using albacore, you can have your configuration options automatically mixed in by placing your config module in a “config” folder next to the file that your task is defined in. Look at the way I’ve set up the vimbacore project:
and the config folder:
The file names are important for the config module to be automatically included. Name the config file after the task’s class with “config” at the end of it. In this case the class is named “ExpandTemplate” so the config file is located in ./config/expandtemplateconfig.rb
By adhering to that simple layout, your config module will be loaded up and runtime. Combine this with the “include Albacore::Configuration” that I mentioned agove, and you have automatic Albacore.configure mixins!
Moving Forward…
As the final release of v0.2.0 approaches, we’ll be working to do additional clean up on the albacore functionality, add more options to existing tasks, and create a few new tasks. We’ll also be documenting the albacore functionality so that others can take advantage of it without having to read through the source of existing tasks. We want to make albacore easy to use and highly customizable, and that requires a comprehensive set of documents describing how to access the functionality in albacore.