<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Reprocessed</title>
  <author>
    <name>Matt Patterson</name>
  </author>
  <generator>Reprocessed.org feed crank</generator>
  <id>tag:reprocessed.org,2003-12-11:/</id>
  <link rel="self" href="http://reprocessed.org/feed.atom"/>
  <link rel="alternate" type="text/html" href="http://reprocessed.org/"/>
  <rights>Copyright 1998-2010, Matt Patterson. Some rights reserved.</rights>
  <link rel="license" type="application/rdf+xml" title="A machine-readable version of this feed's Creative Commons rights license" href="http://creativecommons.org/licenses/by/2.0/uk/"/>
  <link rel="license" type="text/html" title="A human-readable version of this feed's Creative Commons rights license" href="http://creativecommons.org/licenses/by/2.0/uk/"/>
  <updated>2010-06-23T17:47:06+01:00</updated>
  <entry>
    <category term="ubuntu" label="Ubuntu"/>
    <category term="mac_mini" label="Mac Mini"/>
    <category term="dual_boot" label="dual boot"/>
    <category term="linux" label="Linux"/>
    <category term="macosx" label="Mac OS X"/>
    <category term="efi" label="EFI"/>
    <category term="refit" label="rEFIt"/>
    <id>tag:reprocessed.org,2010-06-23:ubuntu_on_mac_mini</id>
    <title type="text">Getting Ubuntu Server (10.04) working on an intel Mac Mini</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Getting Ubuntu's Server edition running directly on a Mac Mini proved to be a bit of a pain, with lots of partial instructions, but with lots of important bits missed out or glossed over. And lots of stuff about the Desktop edition, which has a completely different installer.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/ubuntu_on_mac_mini"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Getting Ubuntu's Server edition running directly on a Mac Mini proved to be a bit of a pain, with lots of partial instructions, but with lots of important bits missed out or glossed over. And lots of stuff about the Desktop edition, which has a completely different installer.</p>

<p>The reason it's not yet straightforward is that Apple's intel-based kit uses <a href="http://en.wikipedia.org/wiki/Extensible_Firmware_Interface">EFI</a>, rather than the older <a href="http://en.wikipedia.org/wiki/BIOS">BIOS</a> based methods. The standard <a href="http://en.wikipedia.org/wiki/GNU_GRUB">GRUB</a> and <a href="http://en.wikipedia.org/wiki/LILO_" title="boot_loader">LILO</a> bootloaders don't yet know how to deal with EFI. Grub 2, in development, will do that, but until it's released and stable we have a problem. Bizarrely, the most aggravating problem I had was when it looked like I'd bricked the machine, but it turned out the keyboard I was using was too new.</p>

<p>There are three basic steps:</p>

<ol>
<li>Partition</li>
<li>Sort out the bootloader issue</li>
<li>Install (includes more partitioning)</li>
</ol>

<p>Actually, 1 and 2 are quite closely linked. My first thought was that I could just wipe the disk and install Ubuntu, but the bootloader problem means that really you need to keep a Mac OS X install hanging around. The solution to the bootloader problem is to use <a href="http://refit.sourceforge.net/">rEFIt</a> which provides an EFI bootloader which can hand off to another bootloader, either Apple's or Ubuntu's. You install it on your Mac OS X partition. As several people have pointed out, keeping an OS X installation around means you can continue to apply firmware updates.</p>

<h2>A digression about keyboards</h2>

<p>I tried to get into Apple's startup manager loader thingy (hold down option on the keyboard after the power-on bong) on the Mini, a Core Duo from 2006 or 2007, and nothing happened. I tried to boot off the CD, (hold down C on the keyboard after the power-on bong). I was trying to do this because I had used the Startup Disk preference panel to boot off the Ubuntu CD, and the installer seemed like it was hanging at the first screen. I couldn't boot into OS X, and it wouldn't boot off the OS X DVD. In a panic, I took it off the genius bar. They couldn't get it to do anything, until they tried an older keyboard. Then it was fine. By the look of things, the problem is that USB is (OS) software, and before you've booted is firmware. The older firmware didn't know how to make the newer apple keyboard work, I assume because it has different special keys and such. Fortunately I had a correct-era keyboard in the office. I guess the lesson is to make sure you always have a keyboard dating back to your oldest bit of hardware. I'd be interested to know if a bog-standard generic PC USB keyboard would have worked...</p>

<p>End of digression.</p>

<h2>Partition</h2>

<p>So, you need to keep your Mac OS X partition around. If, like me, you're wiping the computer then you can boot off the installer DVD, make a small HFS+ partiton for OS X, and leave the rest of the disc as free space. You'll need 12-15GB for Snow Leopard.</p>

<p>If you want to keep your existing OS X install then you can use the Bootcamp Assistant (in 10.4+), or plain old Disk Utility (definitely in 10.6, maybe in 10.5) to resize your existing HFS+ partition.</p>

<h2>Bootloader</h2>

<p>rEFIt is the thing to use. Download it from <a href="http://refit.sourceforge.net/">sourceforge</a>, and install it on the Mini. It installs its stuff in the folder <code>/efi</code>, which you shouldn't delete. I needed to enable it manually, which you can do from Terminal.</p>

<pre><code>cd /efi/refit
./enable-always.sh
</code></pre>

<p>I used <code>enable-always.sh</code> because I want the machine to always boot into Linux.</p>

<p>Reboot to check that it works. If it does, you'll see rEFIt's loader screen. If you do, you're done with this bit.</p>

<h2>Install</h2>

<p>Download and burn the Ubuntu server ISO. Make sure you get the right architecture - the server version defaults to 64-bit, while the desktop version still defaults to 32-bit.</p>

<p>Insert the disc, reboot, and you should see the CD-with-penguin icon in rEFIt. Boot off the installer. Do your partitioning, making sure to leave the HFS+ and the sooper-sekrit EFI partitions well alone. Make a note of which partition you will be installing Ubuntu on, in <code>/dev/sdXN</code> form (i.e. <code>/dev/sda3</code>). You will need it later and there is no way to find out what the correct form is at the point you have to type it in.</p>

<p>Install Ubuntu, and at the install-GRUB step enter <code>/dev/sda3</code> (or whatever the correct place is). Once it's done that it should eject the install CD and you can then reboot. You'll have to select Linux from the rEFIt screen, and it should boot.</p>

<h2>Always booting Linux</h2>

<p>rEFIt has a configuration file which allows you to select, more or less, which operating system will automatically boot. It's in <code>/efi/refit/refit.conf</code> on the Mac OS X partition, so boot into OS X and edit it.</p>

<p>At the end there's a couple of sections about boot choice:</p>

<pre><code># List legacy options first. When enabled, legacy BIOS based boot options
# (e.g. Windows, Linux via LILO or GRUB) will be listed first. This is
# intended as a quick fix to change the default boot choice until full
# configurability arrives.
#
#legacyfirst

# Set the default menu selection.  The available arguments match the
# keyboard accelerators available within rEFIt.  You may select the default
# loader using a one-character abbreviation for the OS name ("M" = Mac OS X,
# "L" = Linux, "W" = Windows).  You may also specify a digit between 1 and
# 9, in which case the Nth loader in the menu will be the default.  You can
# also select a rEFIt tool entry ("S" = EFI Shell, "P" = Partitioning Tool,
# "U" = shutdown).  This is intended as a quick fix to change the default
# boot choice until full configurability arrives.
#
#default_selection L
</code></pre>

<p>I uncommented <code>default_selection L</code> and that seems to work fine for me. I imagine YMMV.</p>

<h3>Acknowledgements</h3>

<p>The basic outline for this came from Victor Costan's post about <a href="http://blog.costan.us/2009/03/ubuntu-810-or-904-on-mac-mini.html">installing the Desktop edition</a>, plus assorted reading of the Ubuntu wiki and rEFIt documentation. Thanks for the info.</p>      </div>
    </content>
    <published>2010-06-23T17:47:06+01:00</published>
    <updated>2010-06-23T17:47:06+01:00</updated>
  </entry>
  <entry>
    <category term="constituent_parts" label="Constituent Parts"/>
    <category term="nosqleu" label="NoSQL Europe"/>
    <category term="oredev" label="Oredev"/>
    <category term="conference" label="conference"/>
    <id>tag:reprocessed.org,2010-04-13:nosqleu</id>
    <title type="text">NoSQL EU</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>There's just over a week to go until <a href="http://nosqleu.com/">NoSQL Europe</a>, our conference about NoSQL technologies, and how you use them. We've got a fantastic line up, including keynotes from Amazon's Werner Vogels, The Guardian's Matt Wall; speakers from Twitter, The BBC, Rackspace, Basho, 10gen, Neo Technology and many others over 2 days. We have some fantastic workshops lined up on <a href="http://riak.basho.com/">Riak</a>, <a href="http://www.mongodb.org/">MongoDB</a>, <a href="http://code.google.com/p/redis/">Redis</a>, and <a href="http://neo4j.org/">Neo4J</a>, from members of their development teams or core contributors.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/nosqleu"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>There's just over a week to go until <a href="http://nosqleu.com/">NoSQL Europe</a>, our conference about NoSQL technologies, and how you use them. We've got a fantastic line up, including keynotes from Amazon's Werner Vogels, The Guardian's Matt Wall; speakers from Twitter, The BBC, Rackspace, Basho, 10gen, Neo Technology and many others over 2 days. We have some fantastic workshops lined up on <a href="http://riak.basho.com/">Riak</a>, <a href="http://www.mongodb.org/">MongoDB</a>, <a href="http://code.google.com/p/redis/">Redis</a>, and <a href="http://neo4j.org/">Neo4J</a>, from members of their development teams or core contributors.</p>

<p>It's going to be an intimate conference -- under 200 people -- so you'll be able to ask those questions, show that demo that doesn't quite work, share code, war stories, and learn from each other. The workshops, too, will be good and small, capped at 20 participants. We're not going to take your money and stick you in the back of huge hall: we're going to stick you in the middle of the action.</p>

<p>We have <a href="http://nosqleu.com/#register">tickets left</a>, so if you're able to make it to London next week, you're interested in development beyond everything-in-SQL, and you're not already coming, what are you waiting for! (The workshops are almost sold out, so you'll need to move fast if you want <a href="http://nosqleu.com/#register">tickets for those</a>) </p>      </div>
    </content>
    <published>2010-04-13T17:30:11+01:00</published>
    <updated>2010-04-13T17:30:11+01:00</updated>
  </entry>
  <entry>
    <category term="macosx" label="Mac OS X"/>
    <category term="sysadmin" label="sysadmin"/>
    <category term="testing" label="testing"/>
    <category term="continuous_integration" label="Continuous Integration"/>
    <category term="acceptance_testing" label="acceptance_testing"/>
    <category term="selenium" label="Selenium"/>
    <category term="release_management" label="Release management"/>
    <category term="hudson" label="Hudson"/>
    <id>tag:reprocessed.org,2010-01-25:easy_rails_ci_with_hudson</id>
    <title type="text">Easy Rails CI with Hudson</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>For a long time I've thought that it would be a good idea to have a <a href="http://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> server that could run all the tests for a project on checkin to source control. Until I started making use of <a href="http://cukes.info/">Cucumber</a> I didn't really have a full test run that took long enough to make buying a separate CI server feel more like an investment than an indulgence.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/easy_rails_ci_with_hudson"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>For a long time I've thought that it would be a good idea to have a <a href="http://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> server that could run all the tests for a project on checkin to source control. Until I started making use of <a href="http://cukes.info/">Cucumber</a> I didn't really have a full test run that took long enough to make buying a separate CI server feel more like an investment than an indulgence.</p>

<p>And then I started using <a href="http://seleniumhq.org/">Selenium</a> to run in-browser tests for the Ajaxy parts of site, and Selenium is slow. Really slow.</p>

<p>Suddenly, a thirty-second full test run, which had crept up to one minute or so with Cucumber, was taking six minutes. What to do?</p>

<p>Enter CI, stage left.</p>

<h2>What's CI good for?</h2>

<p>If you've got more than one developer on a project then CI's a no-brainer. Knowing that your last commit and your colleague's last commit together break things, and knowing it as soon it happens, is priceless knowledge.</p>

<p>If you've got a large, layered, suite of tests, then it's also a fairly obvious one. For example, in a typical Rails app I tend to have three layers: Fast-running lower-level RSpec examples covering models, controllers, and views in isolation. Above that are end-to-end acceptance-level Cucumber scenarios which use Rails' integration testing (so, no browser involved), which take a lot longer to run. And above that are the Cucumber scenarios which drive a real browser for testing things (typically involving Ajax or something else Javascripty). Those take a long time to run.</p>

<p>Waiting for a long test run can really suck the productivity out of you. I don't generally need to run the Cucumber test layers as often as I do the RSpec layer (which I run constantly through <a href="http://zentest.rubyforge.org/ZenTest/Autotest.html">Autotest</a>). In fact, I can usually get away with only running all of them when I've done enough work to warrant a commit. (Obviously, if I'm working on something Ajaxy I'll run those specific features). So, why not let a magic box check out my commit and run all those tests for me. And, let's be honest, I'm not going to take that six-minute test run hit often enough if a machine doesn't do it for me.</p>

<h2>Choosing one</h2>

<p>I've looked at various bits of CI software over the years I've been skirting round this issue. <a href="http://buildbot.net/trac">Buildbot</a>, <a href="http://integrityapp.com/">Integrity</a>, <a href="http://cruisecontrol.sourceforge.net/">CruiseControl</a>, <a href="http://cruisecontrolrb.thoughtworks.com/">CruiseControl.rb</a> all got poked at to some extent, some I tried installing and configuring, I even succeeded with CC.rb, and others looked too complex to set up over lunch. </p>

<p>Buzz was building around <a href="http://hudson-ci.org/">Hudson</a>, but I didn't get much past my knee-jerk anti-confluence response. Reader, I was a fool. After much prompting (Thanks, <a href="http://www.redmonk.com/jgovernor/">James Governor</a>!) I installed, configured, and got a basic test run with Hudson over a lunchtime. Hudson wins.</p>

<h1>Setting up Hudson</h1>

<p>I originally followed, broadly, this <a href="http://juretta.com/log/2008/11/11/hudson_test_drive_part_1_rails/">Hudson setup blog post over at juretta.com</a> and evolved the setup so I could get test reporting for RSpec and Cucumber. Because the ground to cover for basic setup is so short, I'm going to cover everything from download to build again. I'm assuming you're on Mac OS X, but everything will work on *nix varieties unless I explicitly say otherwise. You can use Hudson with Windows, and there are <a href="http://wiki.hudson-ci.org/display/HUDSON/Installation+and+Execution#InstallationandExecution-WindowsInstallation">instructions on their site</a>.</p>

<p>The basic steps look like this:</p>

<ol>
<li>Download and installing the latest version of Hudson.</li>
<li>Add the Hudson plugins needed to rub Rake and Ruby tasks (happily, easier than it sounds)</li>
<li>Set up a Hudson build job</li>
<li>Post-commit hooks for Github</li>
<li>Add the rake tasks to your Rails app to enable test reporting (very cool, much easier than it used to be, too)</li>
<li>On a box of its own</li>
</ol>

<h2>Download and install</h2>

<p>Dead simple, this. Either <a href="http://hudson-ci.org/">download the latest version from this page</a>, or from this direct link: <a href="http://hudson.gotdns.com/latest/hudson.war">http://hudson.gotdns.com/latest/hudson.war</a>. (If you're on Debian or Ubuntu, <a href="http://wiki.hudson-ci.org/display/HUDSON/Installing+Hudson+on+Ubuntu">there are packages</a>) Once that's downloaded, run it from the command line like this:</p>

<pre><code>java -jar /path/to/downloads/hudson.war
</code></pre>

<p>Visit <a href="http://localhost:8080/">http://localhost:8080/</a> in your browser. If you see the Hudson dashboard page, it works.</p>

<h2>The Hudson plugins for Rails</h2>

<p>Hudson uses plugins to extend its core functionality, and you can install them through Hudson's own web interface. The whole process is painless, which was a nice surprise: I'd thought 'Java' and panicked slightly.</p>

<p>You can see available plugins in the 'available' pane of the plugin section in your Hudson management interface (<a href="http://localhost:8080/pluginManager/available">http://localhost:8080/pluginManager/available</a>). They're installed by checking the box next to their name and pressing the install button at the bottom right of the page. You can install several plugins at once, and once the process is over you need to restart Hudson.</p>

<p>You'll definitely need the Rake plugin. Hudson supports Subversion out of the box, but if you're using Git for source control you'll need a plugin. </p>

<h2>The build</h2>

<p>A couple of quick notes. Unless gem dependencies are vendorised you'll need to ensure the box you're running Hudson has your dependencies installed.</p>

<ul>
<li>From the main Hudson dashboard, click the 'new job' link. Enter a name, check 'Build a free-style software project', then hit OK.</li>
<li>Check the radio button for your source control system. Assuming git, put a URL for your project in. If you're using Github, then the URL for your repository in the management interface is the one to use. Leave the build triggers section alone for now.</li>
<li>Add a rake build step for your testing rake tasks, from the 'Add build step' drop down. In the text box for tasks, put the name of rake task which runs your tests, <code>spec</code>, for example. You can add multiple tasks to the box. I tend to add more tasks to Hudson to ensure a clean environment for each run (this only caused me problems with the environment differences between the Selenium- and non-Selenium Cucumber runs).</li>
<li>Hit the 'Save' button to save the changes</li>
</ul>

<p>That's it for the basics. Hudson should be able to run your specs and will report a build fail if rake exits with a non-zero status code, which is exactly what you want. Hit the 'Build now' button in the sidebar to verify it all works. If it doesn't work, chances are that one of these two things has happened:</p>

<ol>
<li>You're missing some of the dependencies of your project. (This is particularly likely to happen if you're putting Hudson on a fresh box)</li>
<li>Rake and/or Ruby aren't in the <code>$PATH</code> which Hudson is seeing. If <code>rake</code> and <code>ruby</code> work for you, then it's may be that you invoked Hudson from a different environment (like a system startup script) and that's the problem.</li>
</ol>

<h2>Running a build automatically -- Post-commit hooks</h2>

<p>There's lots of great intelligence you can get about your build from test reporting or metrics, but the number-one thing is to run the build after every commit. Fortunately, it's super simple. First, ensure that there's a public IP and port which points at Hudson's port on your box. Make sure you set up Hudson to require users to authorise - otherwise any old internet person could run arbitrary code on your box. See <a href="http://wiki.hudson-ci.org/display/HUDSON/Quick+and+Simple+Security">Hudson's guide to security for more information</a>. </p>

<p>If you're just using the built-in server, it's really simple. When you start up Hudson, pass a username and password in as command-line args:</p>

<pre><code>java -jar /usr/local/hudson/hudson.war --argumentsRealm.passwd.admin='adminpass' --argumentsRealm.roles.admin=admin
</code></pre>

<p>This creates a user. To enable security, click the 'Manage Hudson' link, select 'Enable Security', then check ''</p>

<p>Once you're secure, set up a post-commit hook in your source control system which makes an HTTP POST call to:</p>

<pre><code>http://{your-IP}:{your-port}/job/{project-name}/build
</code></pre>

<p>That's it. Even if you've got username/password authentication set up, Hudson can allow anonymous POSTs to the project build URL with a simple auth token in the URL, precisely so that robots can start a build for you. Details are in the same <a href="http://wiki.hudson-ci.org/display/HUDSON/Quick+and+Simple+Security">Hudson security guide</a> I mentioned before. I use <a href="http://help.github.com/post-receive-hooks/">GitHub's Service Hooks</a> to start a new build after every <code>git push</code>.</p>

<h2>Reporting</h2>

<p>Hudson can display and track test reports in <a href="http://ant.apache.org/manual/OptionalTasks/junit.html">JUnit's XML reporting format</a> (It seems to be one of those great and mysterious undocumented formats that everyone relies on). Enabling it is as simple as checking the 'Publish JUnit test result report' option and specifying which files to report. The text box takes file globs relative to the Hudson workspace base dir, which is the root of the checked-out source (and so will probably be the same as <code>RAILS_ROOT</code>). I tend to use a glob which allows me to use different sub directories (one for each kind of run, e.g. RSpec, Cucumber-without-Selenium, Cucumber-with-Selenium), like this:</p>

<pre><code>hudson/reports/**/*.xml
</code></pre>

<p>That'll catch any and all .xml files under <code>hudson/reports</code>. The next thing to do is get things to dump reports in the correct format.</p>

<p>Cucumber ships with a formatter for this -- the <code>junit</code> formatter. You set the formatter and point it at a directory, and away it goes. An example cucumber rake task for Hudson:</p>

<pre><code>namespace :hudson do
  def report_path
    "hudson/reports/features/"
  end

  Cucumber::Rake::Task.new({'cucumber'  =&gt; [:report_setup, 'db:prepare']}) do |t|
    t.cucumber_opts = %{--profile default  --format junit --out #{report_path}}
  end

  task :report_setup do
    rm_rf report_path
    mkdir_p report_path
  end
end
</code></pre>

<p>The <code>:report_setup</code> task is worth a quick look. It ensures that your test report directory is clean, and not littered with files from a previous run, which could introduce misleading noise into your reports.</p>

<p>RSpec is a little bit trickier. There's no built-in JUnit formatter, for starters. There is <a href="http://caldersphere.rubyforge.org/ci_reporter/">the <code>ci_reporter</code> gem</a>, however, which neatly rides to the rescue. <code>ci_reporter</code> provides a JUnit RSpec formatter. It's not entirely straightforward, because it needs to do some magic before the specs run, but it's pretty simple and it's easy enough to prevent it doing its magic unless you explicitly want it doing that. Sample tasks look like these:</p>

<pre><code>namespace :hudson do
  task :spec =&gt; ["hudson:setup:rspec", 'db:migrate', 'rake:spec']

  namespace :setup do
    task :pre_ci do
      ENV["CI_REPORTS"] = 'hudson/reports/spec/'
      gem 'ci_reporter'
      require 'ci/reporter/rake/rspec'
    end
    task :rspec =&gt; [:pre_ci, "ci:setup:rspec"]
  end
end
</code></pre>

<p>The <code>ci:setup:rspec</code> is <code>ci_reporter</code>'s own task. The <code>hudson:setup:rspec</code> requires the <code>hudson:setup:pre_ci</code> task, in order to load up <code>ci_reporter</code>, and the <code>ci:setup:rspec</code> task can then perform its magic. All you need to ensure is that <code>ci:setup:rspec</code> runs <strong>before</strong> the main <code>spec</code> task. The <code>rake:spec</code> task is simply an explicit reference to the top-level <code>spec</code> task, otherwise rake would get confused with the <code>hudson:spec</code> task I defined. (It's a bit like using <code>::ClassName</code> in Ruby to get <code>ClassName</code> and not <code>Module::ClassName</code>.)</p>

<h2>Selenium (a brief aside)</h2>

<p>Setting up Selenium-RC for use with Hudson (through Cucumber, I'm assuming) is simply a matter of ensuring that the bits required for Selenium are present on the box, and that the ports for Hudson (by default, 8080) and Selenium's RC server (by default, 4444) don't conflict. See my <a href="http://reprocessed.org/blog/selenium_and_cucumber">article on using Selenium and Cucumber together</a> for more details: all you need to do differently is to use the JUnit formatter if you want reporting. My own setup tends to use separate (and separately cleaned) subdirs of <code>hudson/reports/features</code> to stop the Selenium Cucumber run clobbering the others.</p>

<h2>On a box of its own</h2>

<p>You need to get Hudson to start up automatically. There are <a href="http://wiki.hudson-ci.org/display/HUDSON/Installation+and+Executions">instructions for most platforms on the Hudson site</a>. On a Mac, that means a <a href="http://en.wikipedia.org/wiki/Launchd"><code>launchd</code> startup script</a>. It's perfectly straightforward to set these up. The question is whether you want Hudson to start as a system daemon (at machine startup), or as a global or user-specific 'agent' (on login, either for all users or one specific user). If you're going to be running Selenium then you'll need an agent because a web browser needs to be started from a logged-in GUI user's environment - it can't be started by a system daemon directly. You can, of course, set your machine to automatically log a user in.</p>

<p>A sample startup script looks like this:</p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
  &lt;key&gt;Program&lt;/key&gt;
  &lt;string&gt;/usr/local/hudson/launch-hudson&lt;/string&gt;
  &lt;key&gt;Label&lt;/key&gt;
  &lt;string&gt;org.hudson-ci.hudson&lt;/string&gt;
  &lt;key&gt;OnDemand&lt;/key&gt;
  &lt;false/&gt;
  &lt;key&gt;RunAtLoad&lt;/key&gt;
  &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</code></pre>

<p>(Save this as a file called <code>org.hudson-ci.hudson.plist</code>.) You'll notice that I didn't directly invoke hudson, but used a launch script. That's needed if you use a system like MacPorts in order that you can set the environment up as you need it. Without adding to the <code>$PATH</code> variable nothing launched by Hudson would be able to locate anything installed through MacPorts. That script looks like this:</p>

<pre><code>#!/bin/sh

export PATH=/opt/local/bin:/opt/local/sbin:$PATH

java -jar /usr/local/hudson/hudson.war --argumentsRealm.passwd.admin='adminpass' --argumentsRealm.roles.admin=admin
</code></pre>

<p>It sets <code>$PATH</code> and starts Hudson with arguments which make it require a user named <code>admin</code> with password <code>adminpass</code>. (See <a href="http://wiki.hudson-ci.org/display/HUDSON/Quick+and+Simple+Security">the Hudson security guide</a> for more details about that)</p>

<p>To install these, simply copy them to the appropriate places. For the <code>launchd</code> script this is either <code>/Library/LaunchAgents</code> (for all users), or <code>~/Library/LaunchAgents</code> for a specific user. I put the <code>hudson.war</code> file and the <code>launch-hudson</code> script into <code>/usr/local/hudson</code>, with appropriate permissions (<code>755</code> for <code>launch-hudson</code> and <code>644</code> for <code>hudson.war</code>) and ownership (<code>chown root:wheel</code> for both). That stops local users modifying them (probably what you want). It doesn't stop local users reading them, so your Hudson install would be vulnerable to someone who had already compromised your machine (they could read the Hudson username and password). Although, if someone's compromised your machine a compromised Hudson install is probably the least of your worries...</p>

<p>Once you've got the scripts in place, simply logging out and then in again (or restarting your machine) should make Hudson start without your intervention. If you have problems, try running the launch script from the command line, or looking at your logs. If you're having problems with the <code>launchd</code> <code>.plist</code> then you could try Peter Borg's <a href="http://lingon.sourceforge.net/">Lingon</a>, which is a GUI interface to create these files. It's not maintained anymore, but it should do the trick (even on Snow Leopard). You'll want the 2.1.1 version a <code>.zip</code>, not the 1.2 <code>.dmg</code> which it sticks in the big box at the top.</p>      </div>
    </content>
    <published>2010-01-25T18:49:05+00:00</published>
    <updated>2010-01-25T18:49:05+00:00</updated>
  </entry>
  <entry>
    <category term="games" label="games"/>
    <category term="mirrors_edge" label="Mirror's Edge"/>
    <category term="ea" label="EA"/>
    <category term="review" label="review"/>
    <id>tag:reprocessed.org,2010-01-20:mirrors_edge</id>
    <title type="text">Mirror's Edge, and not breaking my TV</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I guess there were two things I was hoping for when I sat down to play [<em>Mirror's Edge</em>] [1], one being [<em>Jet Set Radio Future</em>] [2], and the other being the original [Prince of Persia reboot <em>Sands of Time</em>] [3]. In both titles moving was a joy: fluid, and well directed. Even if you didn't know exactly where to go when you started moving, if you could read the architecture of the levels, and had the basic control competencies down, you could string move after move together and flow through the environment. The grace and agility of the Prince, in an environment with the scale and affordances of JSRF? In first-person? That's a tantalising prospect.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/mirrors_edge"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I guess there were two things I was hoping for when I sat down to play <a href="http://en.wikipedia.org/wiki/Mirror's_Edge"><em>Mirror's Edge</em></a>, one being <a href="http://en.wikipedia.org/wiki/Jet_Set_Radio_Future"><em>Jet Set Radio Future</em></a>, and the other being the original <a href="http://en.wikipedia.org/wiki/Sands_of_Time">Prince of Persia reboot <em>Sands of Time</em></a>. In both titles moving was a joy: fluid, and well directed. Even if you didn't know exactly where to go when you started moving, if you could read the architecture of the levels, and had the basic control competencies down, you could string move after move together and flow through the environment. The grace and agility of the Prince, in an environment with the scale and affordances of JSRF? In first-person? That's a tantalising prospect.</p>

<p>That prospect didn't survive the first five minutes of play. The visuals are lovely, movement is responsive,the controls are well mapped, and the first-person works, at least to start with. The first-person perspective seemed to have dragged over something I hadn't expected: precision. In retrospect, it seems obvious, but at the time it seemed galling. I could do the moves, but I kept falling to my death. Requiring pixel-perfect platforming in first-person seemed to be a step too far. I persisted with the main game until almost the end of the first chapter, but I was gritting my teeth more and more. And swearing at the screen. I certainly hadn't expected the rage I felt. The protagonist is meant to be an elite free-running courier service. She knows the city. You don't know where you're supposed to go half the time. The runner-vision signposting (objects in the environment go bright red if you should use them to get going) is brilliant, except when the thing you need to use next is out of your field of vision. Inevitably in corridors, with people chasing you. The gameplay felt poisonous: being chased constantly by an armed enemy (you are unarmed) who you can't see chasing you (except when you're doing it wrong), and punished for not having a sense of proprioception that extended into the screen. In first-person no-one can see your feet.</p>

<p>I put the controller down and put the game away. I had a little rant at <a href="http://infovore.org/">Tom Armitage</a> in the office. He said I should try the Time Trial mode, and that it was good. I wasn't sure if I believed him, but I gave it a shot.</p>

<p>The Time Trial mode is like <a href="http://www.youtube.com/results?search_query=crackdown+rooftop+race&amp;search_type=&amp;aq=f"><em>Crackdown</em>'s rooftop races</a>, in as much as you're following a route marked by waypoints across the rooftops of a city. Time Trial does a couple of things to the game, the most important of which is to invert the chase dynamic. It may just be the clock, but you're the one doing the chasing now.</p>

<p>In taking out all the enemies, Time Trial's other big change is to give the game's requirement for precision a reward. Not only do you have to make the jump, but the better you are, the more time, and distance, you can shave off your route. Time Trial's 3-star time rating system gives you something that encourages practice and replay: can you get your time down enough to get that next star? It also makes it quickly apparent that there must be more than one route through the level. You can plot a route, practice, run it perfectly and still be 30 seconds off the next star rating. It even has a gentle introduction to multiple routes: there are three different races through the training level, the latter ones' routes suggesting shortcuts in the previous races.</p>

<p>Those tweaks were enough to transform my experience of the game, the blind panic and rage which had characterised the main game for me replaced with the sense of agency, focus, and plain exhiliration I'd been hoping for to start with. </p>

<p>And the game keeps giving. Once you've set a qualifying (one-star) time for a race, the next time you run it a ghost of your previous time will run the race with you. If you can see your ghost, you're not as fast. You can also download ghosts of your Xbox Live friends, or of high-ranked other gamers on Live. If someone knows a better route, you can see them taking it, and follow their trail of footsteps. Something which integrates the youtube speedrun video into the game, explicitly legitimising that as a form of route exploration and discovery.</p>

<p>And the bottom line is that Time Trial is fun, addictive, and when I get frustrated it's usually because I need to practice, not because I'm being punished. That simple joy in movement is in there too, when you string a sequence of moves together and fly round the course, but it's cut through with the fierce joy of competition, of hitting that obstacle <em>just so</em>, and of hurling yourself between the rooftops at speeds definitely <a href="http://en.wikiquote.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy#Chapter_34">exceeding R</a>.</p>      </div>
    </content>
    <published>2010-01-20T17:02:38+00:00</published>
    <updated>2010-01-20T17:02:38+00:00</updated>
  </entry>
  <entry>
    <category term="selenium" label="Selenium"/>
    <category term="webrat" label="Webrat"/>
    <category term="cucumber" label="Cucumber"/>
    <category term="software_development" label="Software development"/>
    <category term="testing" label="testing"/>
    <category term="acceptance_testing" label="acceptance_testing"/>
    <category term="behaviour_driven_development" label="Behaviour-driven development"/>
    <id>tag:reprocessed.org,2009-11-14:selenium_and_cucumber</id>
    <title type="text">Setting up a more-integrated Selenium, Cucumber, and Rails</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I've been using [Selenium] [1] and [Cucumber] [2] together for a few months now, and I've really enjoyed being able to actually test the Ajaxy parts of my apps. The initial setup was a bit of a pain, and most of the tutorials I found advocated completely separate and parallel Selenium and non-Selenium Cucumber feature directories. I didn't want this, worked out a more integrated way, which changes to Cucumber have since allowed me to make even more straightforward. I'm going to assume you want to set up Selenium with Cucumber, or want to improve your setup, rather than introduce either thing.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/selenium_and_cucumber"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I've been using [Selenium] [1] and [Cucumber] [2] together for a few months now, and I've really enjoyed being able to actually test the Ajaxy parts of my apps. The initial setup was a bit of a pain, and most of the tutorials I found advocated completely separate and parallel Selenium and non-Selenium Cucumber feature directories. I didn't want this, worked out a more integrated way, which changes to Cucumber have since allowed me to make even more straightforward. I'm going to assume you want to set up Selenium with Cucumber, or want to improve your setup, rather than introduce either thing.</p>

<h2>The basic setup</h2>

<p>Installing Cucumber and Selenium is a simple matter these days. You can follow the first couple of paragraphs from <a href="http://wiki.github.com/aslakhellesoy/cucumber/setting-up-selenium">the <em>Setting Up Selenium</em> wiki page</a>, which essentially amount to:</p>

<ol>
<li>Install the selenium-client gem</li>
<li>Make really sure you're using the right version of <code>selenium-client</code> for your version of Webrat</li>
<li>Tweak your Cucumber config appropriately</li>
</ol>

<p>I can't emphasise enough how important that second point is. If your <code>selenium-client</code> and Webrat gems aren't bang on you'll get the worst kind of total, baffling, failure. A simple point-update to <code>selenium-client</code> <strong>will</strong> be enough to throw them out. You have been warned. The <a href="http://wiki.github.com/aslakhellesoy/cucumber/setting-up-selenium">cucumber wiki page</a> above usually has the correct version numbers, although it seems to be out of date. <code>selenium-client</code> 1.2.17 works with <code>webrat</code> 0.5.3 for me.</p>

<h2>The less basic setup</h2>

<p>What I wanted was a way to pick out certain Scenarios from a Feature to run through Selenium to run, and not to also run those through Rails integration tests. <a href="http://wiki.github.com/aslakhellesoy/cucumber/tags">Cucumber's tags</a> provide a good mechanism for that, but don't solve the problem of needing to use an entirely different setup and Webrat mode. After much fiddling, I managed to get a pretty sane setup by tweaking the standard Rake tasks and using Cucumber profiles.</p>

<p>To cut a long story short, the selenium profile sets an environment variable that we pick up in <code>support/env.rb</code> and use to set the right Webrat mode, and whatever other tweaks are needed. Ben Mabey's <a href="http://github.com/bmabey/database_cleaner">database_cleaner gem</a> provides a way to keep your test DB under control, since you can't meaningfully use transactions in your steps with Selenium as the app under test is running as a completely different process, and won't see anything done in any transactions you do use...</p>

<p>With that done, you then use the <code>@selenium</code> tag to mark Scenarios (or whole Features, if you want) which ought to be run with Selenium. The standard profile is set to ignore things tagged @selenium, and the selenium profile is set to ignore everything else.</p>

<p>To run them, I set up more Rake tasks. You can either tweak the Rake tasks Cucumber comes with to add Selenium tasks and make the standard tasks invoke the right profiles, or add new ones. I chose to tweak the standard ones so I didn't keep accidentally running the Selenium-specific Scenarios.</p>

<p>I've created an example rails app on GitHub, at <a href="http://github.com/fidothe/cucumber_selenium_example">http://github.com/fidothe/cucumber_selenium_example</a>. Looking at that's probably the easiest way to figure out how to make it work since you have to tweak in several places. The whistlestop tour looks like this:</p>

<h2>Cucumber profiles</h2>

<p>The Cucumber profiles (in <code>rails_app/cucumber.yml</code>) I used look like this:</p>

<pre><code>default:      --color --tags ~@selenium,~@wip        --format pretty
wip:          --color --tags ~@selenium,@wip:2 --wip --format pretty
selenium:     --color --tags @selenium,~@wip         --format pretty cucumber_mode=selenium
selenium_wip: --color --tags @selenium,@wip:2  --wip --format pretty cucumber_mode=selenium
</code></pre>

<p>It provides a default profile which ignores the <code>@selenium</code> and <code>@wip</code> tags, a WIP profile which ignores <code>@selenium</code> WIP features, but runs non-selenium ones, and Selenium versions of those, which ignore things which aren't tagged<code>@selenium</code>.</p>

<p>The <code>cucumber_mode</code> environment variable is used later to pick up that we've been asked to run with Selenium, because all the tags do is affect which Scenarios and Features are presented to be run, rather than the environment they're run in.</p>

<h2><code>features/support/env.rb</code></h2>

<p>I test for which mode (<code>:rails</code> or <code>:selenium</code>) Webrat should use by checking the <code>cucumber_mode</code> environment variable:</p>

<pre><code>case ENV["cucumber_mode"]
when "selenium"
  webrat_mode = :selenium
  db_clean_strategy = :truncation
else
  webrat_mode = :rails
  db_clean_strategy = :transaction
end
</code></pre>

<p>I also decide which database cleaning strategy Database Cleaner should use here, using DB truncation for Selenium, and the faster transaction method with Rails' integration testing.</p>

<h2>Scenario tagging</h2>

<p>The final piece is to actually mark some scenarios for running with Selenium. This is just a matter of tagging the Scenario (or entire Feature) with the <code>@selenium</code> tag. A trivial example:</p>

<pre><code>Feature: Example
  In order to demonstrate using Selenium
  As the developer
  I want one of these Scenarios to invoke Selenium, and the other not to.

  @selenium
  Scenario: Via Selenium
    When I go to the homepage
    Then I should be on the homepage

  Scenario: Not via Selenium
    When I go to the homepage
    Then I should be on the homepage
</code></pre>

<h2>The end</h2>

<p>Have a look at the example Rails app I put together, which is on GitHub at <a href="http://github.com/fidothe/cucumber_selenium_example">http://github.com/fidothe/cucumber_selenium_example</a>. That app puts all the pieces together, and you can look back over the history to see exactly what I had to change.</p>      </div>
    </content>
    <published>2009-11-14T11:04:52+00:00</published>
    <updated>2009-11-14T11:04:52+00:00</updated>
  </entry>
  <entry>
    <category term="firefox" label="Firefox"/>
    <category term="selenium" label="Selenium"/>
    <category term="macosx" label="Mac OS X"/>
    <category term="macosx_10.6" label="Mac OS X 10.6"/>
    <category term="sysadmin" label="sysadmin"/>
    <category term="testing" label="testing"/>
    <category term="constituent_parts" label="Constituent Parts"/>
    <id>tag:reprocessed.org,2009-11-04:snow_leopard_firefox_and_selenium</id>
    <title type="text">Snow Leopard, Firefox, and Selenium</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I've got a longer post about setting up your Cucumber/Selenium environment coming, but since this is a hot issue I'd thought I'd address it. In short: There's a problem running the <code>firefox.sh</code> script on Mac OS X 10.6, which is the definitive way for things to invoke Firefox. [Selenium RC] [1] runs <code>firefox.sh</code> to run tests, and Cucumber in turn uses Selenium RC. The result is that if you use Cucumber with Selenium and upgrade to 10.6, all your Selenium tests fail. The problem is detailed in Firefox's [Bugzilla bug #513747] [2] and Selenium's [bug SRC-743] [2a]. After a bit of poking about, I found a workaround. It's not great but it does get you going again...</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/snow_leopard_firefox_and_selenium"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I've got a longer post about setting up your Cucumber/Selenium environment coming, but since this is a hot issue I'd thought I'd address it. In short: There's a problem running the <code>firefox.sh</code> script on Mac OS X 10.6, which is the definitive way for things to invoke Firefox. <a href="http://seleniumhq.org/">Selenium RC</a> runs <code>firefox.sh</code> to run tests, and Cucumber in turn uses Selenium RC. The result is that if you use Cucumber with Selenium and upgrade to 10.6, all your Selenium tests fail. The problem is detailed in Firefox's <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=513747">Bugzilla bug #513747</a> and Selenium's <a href="http://jira.openqa.org/browse/SRC-743">bug SRC-743</a>. After a bit of poking about, I found a workaround. It's not great but it does get you going again...</p>

<p>The bug is that the Firefox runner script sets the environment variable <code>DYLD_LIBRARY_PATH</code> which causes Firefox's version of SQLite to override OS X's, which causes the crash. The solution is to get Selenium to invoke  Firefox without setting that environment variable. You don't seem to be able to invoke the Firefox binary directly, because it crashes with the same error. I got it to work using a wrapper script:</p>

<pre><code>#!/bin/sh

/Applications/Firefox.app/Contents/MacOS/firefox-bin $@
exit $?
</code></pre>

<p>Next, you need to tell Selenium to use your wrapper script. I use <a href="http://cukes.info/">Cucumber</a> (through <a href="http://gitrdoc.com/brynary/webrat/tree/master/">Webrat</a>) to define and run my Selenium tests, so this next bit is Webrat-specific.</p>

<p>In your Webrat configuration (usually <code>features/support/env.rb</code> with Cucumber) in your <code>Webrat.configure</code> block you need something like:</p>

<pre><code>Webrat.configure do |config|
  config.mode = :selenium
  config.open_error_files = false # Set to true if you want error pages to pop up in the browser
  browser_key = "*chrome"

  # special browser script iff we're running on Snow Leopard
  browser_key = "*chrome ./script/selenium-firefox" unless (`uname -a` =~ /Darwin Kernel Version 10/).nil?

  config.selenium_browser_key = browser_key
end
</code></pre>

<p>I use a test on the result from <code>uname</code> to figure out if we're on Snow Leopard. There may well be a better way to do that which doesn't involve shelling out. That's it - Firefox and Selenium should now successfully collaborate again.</p>

<p>The only caveat is that, for me at least, the Firefox instance spawned by Selenium doesn't quit after a test run. This makes it pretty tricky for use in an unattended environment (like on a Continuous Integration box). I'm keeping my CI box on 10.5 until this is properly resolved.</p>      </div>
    </content>
    <published>2009-11-04T18:30:51+00:00</published>
    <updated>2009-11-04T18:30:51+00:00</updated>
  </entry>
  <entry>
    <category term="rails" label="Rails"/>
    <category term="flickraw" label="Flickraw"/>
    <category term="flickr" label="Flickr"/>
    <category term="web_ops" label="web ops"/>
    <category term="web_development" label="web development"/>
    <category term="dunderhead" label="dunderhead"/>
    <id>tag:reprocessed.org,2009-10-21:flickrawgh</id>
    <title type="text">Flickrawgh</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>The <a href="http://hanklords.github.com/flickraw/">flickraw</a> Rubygem is the most wonderful Ruby <a href="http://www.flickr.com/services/api/">Flickr API client</a> library IN THE WORLD. It is also dumb, in one important way. And, in another important way, so am I. Yesterday the combination was rather embarassing...</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/flickrawgh"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>The <a href="http://hanklords.github.com/flickraw/">flickraw</a> Rubygem is the most wonderful Ruby <a href="http://www.flickr.com/services/api/">Flickr API client</a> library IN THE WORLD. It is also dumb, in one important way. And, in another important way, so am I. Yesterday the combination was rather embarassing...</p>

<p>A Rails app I run uses Flickraw to pull in Flickr photos, but only in a script run by a cron job. However, I listed the gem as a requirement in <code>environment.rb</code>, like a good little boy:</p>

<pre><code>config.gem "flickraw"
</code></pre>

<p>Except, Rails takes that to mean you want the gem required at startup. When Flickraw is <code>require</code>d it hits the Flickr API to retrieve a list of all the API methods, which it turns into Ruby methods you can call. This makes Flickraw permanently up-to-date and a complete API client, which is what makes it so brilliant. Unfortunately, it turns out that if Flickr is down, Flickraw handles it rather badly: it blows up.</p>

<p>Yesterday, Flickr went down. Passenger spawned a new Rails instance, because that's what it does. On startup, that instance tried to hit <code>api.flickr.com</code>, and couldn't, and brought down the whole app. Ouch. The fix? Just this:</p>

<pre><code>config.gem "flickraw", :lib =&gt; false # Stops your app hitting api.flickr.com on startup
</code></pre>

<p>I have learnt my lesson.</p>      </div>
    </content>
    <published>2009-10-21T10:26:15+01:00</published>
    <updated>2009-10-21T10:26:15+01:00</updated>
  </entry>
  <entry>
    <category term="constituent_parts" label="Constituent Parts"/>
    <category term="consultancy" label="consultancy"/>
    <category term="web_development" label="web development"/>
    <category term="pitchspace" label="PitchSpace"/>
    <category term="pr" label="PR"/>
    <category term="startup" label="startup"/>
    <id>tag:reprocessed.org,2009-10-19:what_am_i_up_to</id>
    <title type="text">What am I up to?</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>All of a sudden people have kept coming up and asking me what I'm up to, and whether I'm still involved with <a href="http://reprocessed.org/blog/pitchspace">Pitch Space</a>. I thought it was worth a quick post to bring things up to date. In short: No, I'm not involved with Pitch Space anymore, and haven't been since December last year, and what I'm up to is doing web application development and consultancy through my company, <a href="http://constituentparts.com/">Constituent Parts</a>.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/what_am_i_up_to"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>All of a sudden people have kept coming up and asking me what I'm up to, and whether I'm still involved with <a href="http://reprocessed.org/blog/pitchspace">Pitch Space</a>. I thought it was worth a quick post to bring things up to date. In short: No, I'm not involved with Pitch Space anymore, and haven't been since December last year, and what I'm up to is doing web application development and consultancy through my company, <a href="http://constituentparts.com/">Constituent Parts</a>.</p>

<p>Constituent Parts has had quite an exciting year, with projects for <a href="http://gamecity.org/">GameCity</a>, Nottingham's international videogame festival, the <a href="http://bbc.co.uk/">BBC</a>, and <a href="http://greenbelt.org.uk/">Greenbelt</a> among others. The new, shiny, and horrifically incomplete <a href="http://constituentparts.com/">Constituent Parts site</a> has more information about what I've been up to and I'll be adding more to it over the coming months. If you have a project which needs development, <a href="http://constituentparts.com/contact">why not get in touch?</a></p>      </div>
    </content>
    <published>2009-10-19T14:29:31+01:00</published>
    <updated>2009-10-19T14:29:31+01:00</updated>
  </entry>
  <entry>
    <category term="greenbelt09" label="greenbelt09"/>
    <category term="greenbelt2009" label="greenbelt2009"/>
    <category term="greenbelt_festival" label="Greenbelt Festival"/>
    <category term="newspapers" label="newspapers"/>
    <category term="typography" label="typography"/>
    <category term="design" label="design"/>
    <category term="retrospective" label="Retrospective"/>
    <id>tag:reprocessed.org,2009-09-14:so_we_made_a_newspaper</id>
    <title type="text">So, we made a newspaper</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Having just about survived <a href="http://www.greenbelt.org.uk/blog/2009/09/while-we-were-here/">making the newspaper</a>, enjoyed the last day of <a href="http://greenbelt.org.uk/">Greenbelt</a> enormously, and spent the last couple of days recovering, I'm sat in the Brighton Dome waiting for the <a href="http://2009.dconstruct.org.uk/">dConstruct</a> fun to start, I thought it would be good to reflect on the newspaper experience. [Actually, it took me another week to get around to finishing this, but most of it was written over the dConstruct weekend.]</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/so_we_made_a_newspaper"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Having just about survived <a href="http://www.greenbelt.org.uk/blog/2009/09/while-we-were-here/">making the newspaper</a>, enjoyed the last day of <a href="http://greenbelt.org.uk/">Greenbelt</a> enormously, and spent the last couple of days recovering, I'm sat in the Brighton Dome waiting for the <a href="http://2009.dconstruct.org.uk/">dConstruct</a> fun to start, I thought it would be good to reflect on the newspaper experience. [Actually, it took me another week to get around to finishing this, but most of it was written over the dConstruct weekend.]</p>

<p>Firstly, we actually made it, got it to site and handed it out. That was the first critical thing, the proof that we could do it. Even better, people seemed to really like it. Really like it, actually. That's the second critical thing, the proof that it was worth doing.</p>

<p>The third thing, of course, was that in the possibility space of newspapers covering a three-day, very specific, slice of the internet (stuff relating to Greenbelt 2009 written over the course of the event) we only managed to occupy the slightly rubbish bit in the corner. For a first, utterly unprepared, attempt this is brilliant, since it leaves a thing which was wonderfully received space to become something far, far, better.</p>

<p>You can download the paper from the <a href="http://www.greenbelt.org.uk/blog/2009/09/while-we-were-here/">Greenbelt Blog article about it</a>. <a href="http://jystewart.net/">James</a> and I still have some copies of the real thing, so if you're desperate to see it, let me know. </p>

<h2>It's harder than you think...</h2>

<p>Well, duh.</p>

<p>We had two distinct sets of problems here. The first was that we'd done no prep work, because we didn't think we'd got the money to do it. As I reported before, <a href="http://hp.com/">Hewlett Packard</a> stepped in and forced our hand. We could have done a 4-page A4 (one folded sheet of A3) mono thing, but suddenly we had the money to go the whole hog.</p>

<p>Leaving aside the question of the design itself, our biggest single problem was securing content. We had originally thought that there had been some people who had agreed to write guest posts for the <a href="http://greenbelt.org.uk/blog/">Greenbelt blog</a> over the festival, but we hadn't chased any of that up. We had our wires crossed, so we had to scare up the writers. Since this was a prototype paper, we had planned to rely on stuff created by people close to Greenbelt-the-organisation, using the paper, post-festival, to engage the wider greenbelter community for next year's effort (assuming there was one).</p>

<p>The next biggest problem was our layout work rate. Because we only had one Mac with InDesign and the paper on it, only one person at a time could work stuff up into laid-out pages. Right at the end, as the deadline loomed, this meant we didn't have time to include either late-arriving content (we had some), or planned-but-unfinished content (we had some of that).</p>

<p>There were really only two of us working on this, and with chasing around for content we were overstretched editorially. We really needed another body to turn the raw material for some of our ideas into text or illustrations we could hand over for layout.</p>

<p>Everything takes time too, and more time than you think it will. Making the photo pages was a case in point. You had to make the grid of container boxes, fill them with images and then add the correct flickr URL to the key at the bottom. This was essentially cut-and-paste-template-page, followed by dropping in picked images and URLs. It was the easiest thing we did in the paper, but even this bit took around 20-30 minutes for one page. That's a lot time when deadline is approaching, and it doesn't include the time taken to do the picture editing work to pick out the pictures, and the time to generate and check the URLs (we were using short URLs which can only be obtained via an API call, or generated from a URL template and a base-conversion of the photo ID from base 10 to base 58).</p>

<p>The final element was the printing. We'd spoken with <a href="http://www.newsquestprinting.co.uk/">Newsquest Printing</a>, but had had to cancel our print slot with them because we hadn't been able to get the money together. I emailed them on Thursday, after they'd closed for the day, and hoped they would get my message first thing Friday and that there would be a print slot available. Lisa Carmel and David Denham at Newsquest were brilliant and we were able to negotiate our way into a print slot late on Sunday night at their plant in Oxford. David Cheetham from Newsquest's Oxford pre-press team talked me through the submission process and checked over our test pages, which was really helpful.</p>

<h2>Planning (that we ought to have done)</h2>

<p>I had originally planned to do a couple of days work on design prep for the paper, working up a grid, headline styles, text styles and various configurations of pages (different numbers of stories on a page, various size ad spaces, combinations thereof). I eventually spent all of Friday on this, followed by several hours tweaking over the weekend. I basically could have saved a work day during the festival, and produced a vastly better designed product, with good prep. We had a problem with equality of attribution, where stories got a byline and URL, but photos just got a URL, and a short URL at that. So, we managed to be unfair to the photographers by not mentioning their names anywhere. We could have avoided that with a solid design.</p>

<p>To avoid spending hours hunting for photos we used Flickr's interestingness as a measure, and because we were allowed we added Greenbelt's <a href="http://flickr.com/photos/greenbelt">official non-CC licensed photos</a> to the mix of <a href="http://flickr.com/tags/greenbelt09">Greenbelter-uploaded photos</a>. The fact that Greenbelt's own photos were being uploaded regularly through the festival meant that they had a lot longer to register on the interesting scale than Greenbelters' own. In hindsight, I'm not surprised that we didn't use anyone other than Greenbelt's photos -- the effort required to dig out CC licensed ones from the mass of interesting official ones (there were half a dozen official photographers' work being uploaded to the Greenbelt account) was prohibitive given our available time. I'm not sure exactly what we could have done to prevent that (or even whether we'd want to), but I would have liked to have been able to chew it over.</p>

<p>We wanted to do some infographics around festival statistics (size of the site, number of people), and we only managed a silly (but very effective) site size comparison diagram. We really should have planned what we were doing in advance so that producing the charts was a matter of adding the live statistic to the right set, rather than getting a live statistic and trying to figure how to represent it and what to compare it with.</p>

<p>A much more detailed page plan than the one we had (which essentially said that there were 16 pages, with a photo to go on the centre spread) would have allowed us to filter, or commission, content which reflected the range of the festival's content. Our content was very words-focussed, and we didn't really cover any of the other aspects: no music, no visual arts, no performing arts, no comedy, no childrens or youth stuff, and nothing about site setup and build... I would have liked the paper to be much more representative of the whole arc of the festival.</p>

<p>We hadn't finalised any plans for any of the mundane practical things we needed to do once the paper had been printed, and we ended up finalising a plan to collect the papers after they'd gone to press. I drove a car to Oxford, shoved the papers in the boot, and drove straight back. We also hadn't really thought through how to distribute the papers on site once we had them. <a href="http://www.greenbelt.org.uk/festival/2009/lineup/event/2053">Last Orders</a> came through for us and advertised it to their 1000+ plus audience on Sunday night, and James got the Venue Managers to agree to having papers in each of the talks, and some of the music, venues. Transport was a problem there too, and we ended up hiring a <a href="http://www.greenbelt.org.uk/volunteers/greenbelt-taxi-drivers">Greenbelt Taxi</a> to drive us and 4,000 papers round site to the various venues on Monday morning.</p>

<h2>Practicalities</h2>

<p>I think we'd forgotten that there would be work in converting things from HTML to InDesign, and I'd certainly forgotten exactly how long it takes to lay things out, even with a solid grid and stylesheets. We ended up being bottlenecked by the fact that we only had one Mac on which we could do layout (i.e. one which had a large enough screen to work with any speed on).</p>

<p>Because we were only using photos with appropriate licenses from Flickr, I was able to script indesign so I could generate a Flickr short url from a picture in <a href="http://www.adobe.com/products/indesign/scripting/">InDesign</a> (as long as it was a Flickr photo whose filename hadn't been mangled). That saved important thinking time, and made attributing photos take 5 seconds instead of 5 minutes, and massively reduced the chance for error. All of these are important when you have 5 minutes before your print deadline.</p>

<p>I also cooked up a tiny <a href="http://github.com/whymirror/hpricot/tree">Hpricot</a>-using script to take HTML, make the URLs for links in it into plain text on the page, and spit the HTML back out, which saved hours of digging around in view source, and typing and retyping URLs (which is always error-prone at the best of times).</p>

<p>I'll stick these both up on <a href="http://github.com/fidothe/">Github</a> when I've retrieved them from a backup.</p>

<p>The biggest practical triumph, and the biggest problem, we had was with the printing. The triumph was that the quality of the printing was superb. I last did newspaper stuff with the student newspaper at Reading University in the late '90s. The <a href="http://en.wikipedia.org/wiki/Printing_registration">registration</a> was often bad, and pictures often looked off-colour and, particularly when the registration was bad, muddy and horrid. Newsquest's printing was immaculate. The registration was perfect, the colour was great and the pictures looked amazing. I'm really, really, happy with that side of things. There was, however, a problem (and if you've seen it, you'll know about it).</p>

<p>The layout-to-printing-press part Newspaper printing these days is basically a human-free process. You upload some PDFs to a server, the system their puts them in order and makes plates from them. All the pre-press stuff happens before you start. We verified that we were making the right kind of PDFs on the Friday of Greenbelt. We sent files with images (always problematic) and text (fonts, always problematic), and everything was fine. So far, so good. However, if you've seen the final printed product you'll have noticed the enormous print problems on some of the pages. What happened was that we weren't told that if you leave white space at the edges of your PDFs, the computer system at the press will simply scale them so that there's no white space left. This would have been fine if we'd known about it. A simple line down one edge, or dots at the corners, would have solved it. Unfortunately our test pages had all had images to the very edges of the page, so this didn't show up when were dealing with the pre-press guys. The lesson: make sure your test pages are representative of your final output. </p>

<p>So, I think my top tips for doing this again:</p>

<ol>
<li>Arrive with a designed, tested, well thought out, and simple page grid already made.</li>
<li>Make sure you've ironed out any potential production bugs with the printer through a set of good test pages. You don't need proper articles and photos from the event, <em>Lorem Ipsum</em> and photos of your dog will do provided that you try out picture file formats, fonts, space on the page, full-bleed, special file names, that sort of stuff.</li>
<li>Have enough people working on it that you can have a picture editor (if pictures are important), someone to sub stories (to make links explicit, that sort of thing), and someone to chase down stories and/or authors.</li>
<li>Have more than one Mac, split your paper up into several files accordingly. (probably one per day, or one per spread)</li>
<li>Automate everything that can be automated. You will get tired and be unable to think: automation means you don't need to think as much. (Automate it beforehand though.)</li>
<li>If you want involvement from punters, make sure that you've advertised your existence before the festival, provide information about how you'll be aggregating stuff (tags, notification to an email address, whatever), and (if you want punters' photos to be used) provide somewhere they can upload photos for free. (If it's not free, they'll almost certainly wait until afterwards which is, annoyingly, too late.)</li>
<li>Have enough people involved that you can do shifts and thus everyone involved can actually see some of the festival...</li>
</ol>

<h2>Thanks and Acknowledgements</h2>

<p>First off, a big thanks to <a href="http://hp.com/">HP</a> for sponsoring the paper. They've stumped up the cash to pay for the whole thing, which is really what made it possible.</p>

<p>A big thanks to <a href="http://www.redmonk.com/jgovernor/">James Governor</a> for putting us in touch with HP.</p>

<p>Thanks to <a href="http://www.flickr.com/people/ush/">Ian Usher</a> and <a href="http://ratiotype.com/">Wilf Whitty</a> for their help with things photographic, and to all <a href="http://www.flickr.com/photos/greenbelt/">Greenbelt's official photographers</a> for allowing us access to their <a href="http://www.flickr.com/photos/greenbelt/sets/72157622159141488/">amazing stuff</a>.</p>

<p>Thanks to <a href="http://jennybee.net/">Jenny Brown</a> and the Media Capture team for providing us with the stills and descriptions from <a href="http://www.vimeo.com/greenbelt">their videos</a></p>

<p>Thanks to Lisa, the Davids, Mark Wackrill, and the printers at Newsquest for pulling everything through at the last minute and providing us with such high-quality printing.</p>

<p>A big shout to <a href="http://ketlai.co.uk/">James Stewart</a>, my long-suffering co-conspirator, and many thanks to Clare for putting up with my vanishing/overwork act at the festvial.</p>

<p>Most importantly, thanks to all our contributors:</p>

<ul>
<li><a href="http://www.mattburgess.co.uk/">Matt Burgess</a></li>
<li><a href="http://jamescary.blogspot.com/">James Cary</a></li>
<li><a href="http://elaineduigenan.wordpress.com/">Elaine Duigenan</a></li>
<li><a href="http://twitter.com/badlydrawnboyo">Simon Jones</a></li>
<li><a href="http://stevelawson.net/">Steve Lawson</a></li>
<li><a href="http://www.flickr.com/photos/greenbelt/tags/stefanmetzler/">Stefan Metzler</a></li>
<li><a href="http://artbizness.com/">Mike Radcliffe</a></li>
<li><a href="http://kari.anthropiccollective.org/">Kari Stewart</a></li>
<li><a href="http://www.greenbelt.org.uk/blog/2009/08/new-year-without-the-disappointment/">Andy Tate</a></li>
<li><a href="http://www.photoglow.co.uk/">Jonathon Watkins</a></li>
<li><a href="http://benjaminbrum.wordpress.com/">Ben Whitehouse</a></li>
</ul>

<p>The possibilities for this little slice of post-digitalia are enormous so, if you're at Greenbelt next year, look out. We may well have something MOAR AWESOME up our sleeves.</p>      </div>
    </content>
    <published>2009-09-14T14:52:55+01:00</published>
    <updated>2009-09-14T14:52:55+01:00</updated>
  </entry>
  <entry>
    <category term="greenbelt09" label="greenbelt09"/>
    <category term="greenbelt2009" label="greenbelt2009"/>
    <category term="greenbelt_festival" label="Greenbelt Festival"/>
    <category term="newspapers" label="newspapers"/>
    <category term="typography" label="typography"/>
    <category term="design" label="design"/>
    <category term="panic" label="panic"/>
    <id>tag:reprocessed.org,2009-08-30:making_a_newspaper</id>
    <title type="text">Making a Newspaper (the hard way)</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>A couple of months back, <a href="http://jystewart.net/">James</a> and <a href="http://jennybee.net/">Jenny</a> thought it would be a good idea to nick <a href="http://russelldavies.typepad.com/">Russell</a> &amp; <a href="http://noisydecentgraphics.typepad.com/">Ben</a>'s <a href="http://www.reallyinterestinggroup.com/tofhwoti.html">Things Our Friends Have Written On The Internet</a> for <a href="http://greenbelt.org.uk/">Greenbelt</a>. There's loads of people there, and some of them write things while they're there, went the thinking. So far so good.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/making_a_newspaper"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>A couple of months back, <a href="http://jystewart.net/">James</a> and <a href="http://jennybee.net/">Jenny</a> thought it would be a good idea to nick <a href="http://russelldavies.typepad.com/">Russell</a> &amp; <a href="http://noisydecentgraphics.typepad.com/">Ben</a>'s <a href="http://www.reallyinterestinggroup.com/tofhwoti.html">Things Our Friends Have Written On The Internet</a> for <a href="http://greenbelt.org.uk/">Greenbelt</a>. There's loads of people there, and some of them write things while they're there, went the thinking. So far so good.</p>

<p>One of the things Greenbelt has been thinking about for the last couple of years is how to communicate what happens at the festival beyond the festival, and how to give people at the festival a glimpse of the bigger picture - the stuff they haven't made it to, the vibe, what things looked like (we have a great team of photographers creating tons of great images over the festival, not to mention contributions on Flickr from a host of festivalgoers). So, the paper seemed like a good fit. We talked with Russell, Ben, and <a href="http://scraplab.net/">Tom</a> about them bringing their <a href="http://newspaperclub.co.uk/">Newspaper club</a> system to Greenbelt, but time, tide, and August got in the way. </p>

<p>We decided to do it ourselves, which is pretty much where I come in. We arranged printing with <a href="http://www.newsquestprinting.co.uk/">Newsquest</a> in Oxford, and we would fund with ad sales. Which was fine, except we were a bit late in the day and couldn't sell enough ads. So, that was that. Except it wasn't. We decided to try and hire a big A3 laser printer and do a four-page A4 news sheet, except we couldn't get a straight answer on hire charges and costs and it looked like that was going to fall through to. Then we had a brainwave. James and I share an office with <a href="http://www.redmonk.com/jgovernor/">James Governor</a> of <a href="http://redmonk.com/">RedMonk</a>, whose clients include <a href="http://hp.com/">HP</a>, who make printers. Maybe he could persuade them to lend us one?</p>

<p>It didn't look good, in fact, it looked like a dead idea. So, when I got a call from him on Thursday night (I arrived on site on Wednesday). There was no printer, he said, but Hewlett Packard would sponsor us. How did that sound? It sounded very good, actually. And when we found out what HP were prepared to offer as sponsorship we realised that actually, we could do the original newspaper! We were pretty stunned, particularly since we were on site and had given up all hope on the project. So big thanks are due to James Governor, and, of course, massive thanks to HP!</p>

<p>So, now, with none of the design preparation I'd originally planned to have done, without a printer, a ruler, or a layout pad, I'm holed up on site making a newspaper which is going to press tomorrow night, come hell or highwater. We'll be distributing it (for free) around site on Monday. I may not get much sleep, but it's going to be great. </p>      </div>
    </content>
    <published>2009-08-30T11:30:50+01:00</published>
    <updated>2009-08-30T11:30:50+01:00</updated>
  </entry>
  <entry>
    <category term="coop_to_ofx" label="Co-op to OFX"/>
    <category term="ruby" label="Ruby"/>
    <category term="ofx" label="OFX"/>
    <category term="data_portability" label="Data portability"/>
    <category term="screen_scraping" label="Screen scraping"/>
    <id>tag:reprocessed.org,2009-07-10:coop_to_ofx</id>
    <title type="text">Co-op online HTML bank statements to OFX</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Getting your statement data out of the <a href="http://www.co-operativebank.co.uk/">Co-operative Bank</a>'s online banking system in a usable form was pretty hard. You could save the HTML of a statement page, but that's about it. I use <a href="http://www.xero.com/">Xero</a> for my company, <a href="http://constituentparts.com/">Constituent Parts</a>. It will import <a href="http://www.ofx.net/">OFX</a> formatted files which some banks will export for you. To get Co-operative Bank data into Xero you either need to enter the data by hand,  or somehow convert it to OFX. <a href="http://lukeredpath.co.uk/">Luke Redpath</a> (who's great, by the way) wrote a Greasemonkey script to <a href="http://gist.github.com/76914">scrape Smile/Co-op HTML and generate OFX</a>. It works for Current Accounts, but doesn't work with Credit Card statements, which have a slightly (but significantly) different format. So, I've written a Ruby-based screen scraper which will work with Current Accounts and Credit Cards. You can find it over on GitHub: It's called <a href="http://github.com/fidothe/coop_to_ofx/tree/master">Co-op to OFX</a>.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/coop_to_ofx"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Getting your statement data out of the <a href="http://www.co-operativebank.co.uk/">Co-operative Bank</a>'s online banking system in a usable form was pretty hard. You could save the HTML of a statement page, but that's about it. I use <a href="http://www.xero.com/">Xero</a> for my company, <a href="http://constituentparts.com/">Constituent Parts</a>. It will import <a href="http://www.ofx.net/">OFX</a> formatted files which some banks will export for you. To get Co-operative Bank data into Xero you either need to enter the data by hand,  or somehow convert it to OFX. <a href="http://lukeredpath.co.uk/">Luke Redpath</a> (who's great, by the way) wrote a Greasemonkey script to <a href="http://gist.github.com/76914">crape Smile/Co-op HTML and generate OFX</a>. It works for Current Accounts, but doesn't work with Credit Card statements, which have a slightly (but significantly) different format. So, I've written a Ruby-based screen scraper which will work with Current Accounts and Credit Cards. You can find it over on GitHub: It's called <a href="http://github.com/fidothe/coop_to_ofx/tree/master">Co-op to OFX</a>.</p>

<p>Installing it's easy (if you have <a href="http://www.ruby-lang.org/">Ruby</a> and <a href="http://rubygems.org/">Rubygems</a> installed already): </p>

<pre><code># If you haven't already done this:
gem sources -a http://gems.github.com
sudo gem install fidothe-coop_to_ofx

# And if you don't want to add GitHub as a source permanently
sudo gem install fidothe-coop_to_ofx --source=http://gems.github.com
</code></pre>

<p>Using it's also easy:</p>

<p>First, download a statement (say a current account one) from the Co-op by going to a statement on their site in your browser and doing "Save as" to save it as HTML (HTML only, not a web archive or anything like that).</p>

<p>Then, from the command line, do:</p>

<pre><code>coop_to_ofx --current /path/to/statement.html
</code></pre>

<p>That's it. The script will generate an OFX file called <code>statement.ofx</code> in the same directory as the statement HTML. </p>

<p>If you want OFX 1 (some things won't accept the newer XML-based OFX 2) then:</p>

<pre><code>coop_to_ofx --ofx1 --current /path/to/statement.html
</code></pre>

<p>And, for Credit Card statements:</p>

<pre><code>coop_to_ofx /path/to/credit_card_statement.html
coop_to_ofx --ofx1 /path/to/credit_card_statement.html
</code></pre>

<p>The script works locally, on saved HTML, and doesn't ever access the web: It feels unnecessary, brittle, and more of a security risk to deal with the security on the site. On balance, I think it's much better all round to just get you to download the HTML yourself.</p>

<p>Anyway, I hope some of you find it useful.</p>      </div>
    </content>
    <published>2009-07-10T19:19:56+01:00</published>
    <updated>2009-07-10T19:19:56+01:00</updated>
  </entry>
  <entry>
    <category term="ruby" label="Ruby"/>
    <category term="rails" label="Rails"/>
    <category term="ruby_on_rails" label="Ruby on Rails"/>
    <category term="rspec" label="RSpec"/>
    <id>tag:reprocessed.org,2009-07-06:shared_templates_rspec_and_url_for</id>
    <title type="text">Shared templates, context-dependent url_for, and RSpec</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I have this Rails app which has a set of shared templates which are used by two actions in different controllers. Each action renders one of three shared templates, dependent on the context. This is all fine, except that I rely on the magic of <code>url_for</code> to generate URLs based on the current controller; and I rely on RSpec's view specs to keep things working and tidy.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/shared_templates_rspec_and_url_for"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I have this Rails app which has a set of shared templates which are used by two actions in different controllers. Each action renders one of three shared templates, dependent on the context. This is all fine, except that I rely on the magic of <code>url_for</code> to generate URLs based on the current controller; and I rely on RSpec's view specs to keep things working and tidy.</p>

<p>Because RSpec's view specs infer the controller and action name from the path to the template being specced a template like <code>shared/month_archive.html.haml</code> will generate a controller name of <code>shared</code> and an action name of <code>month_archive</code>. The problem was that in use the controller name would be <code>archives</code> and the action <code>by_date</code>. <code>url_for</code> was having kittens as a result.</p>

<p>The solution is to override RSpec's choice for controller and action with something which reflects the views' real use. It's really easy:</p>

<pre><code>describe "/shared/context_sensitive_view"
  def derived_controller_name(*args)
    "sensible_controller_name"
  end

  def derived_action_name(*args)
    "sensible_action_name"
  end

  it "should do something"
    ...
    render
  end
end
</code></pre>

<p>Then, when you call <code>url_for</code> it gets <code>:controller =&gt; 'sensible_controller_name', :action =&gt; 'sensible_action_name'</code> instead of <code>:controller =&gt; 'shared', :action =&gt; 'context_sensitive_view'</code> as part of the params, and it makes URLs instead of having Kittens.</p>

<p>If you need finer control of the params, perhaps because of <code>url_for</code> stuff, you can also do one of the following:</p>

<pre><code>describe "/shared/context_sensitive_view"
  # No need to override .derived_controller_name or .derived_action_name
  before(:each) do
    # With Mocha
    template.stubs(:params).returns(:controller =&gt; 'sensible', :action =&gt; 'also_sensible', :other_param =&gt; 'needed value')
    # Or, with RSpec's own mocking framework'
    template.stub!(:params).returns(:controller =&gt; 'sensible', :action =&gt; 'also_sensible', :other_param =&gt; 'needed value')
  end
end
</code></pre>

<p>Of course, stubbing the params can often bite you -- It is, after all, a <code>HashWithIndifferentAccess</code> so the stringiness or otherwise of your hash keys can cause hard to trace problems. YMMV.</p>      </div>
    </content>
    <published>2009-07-06T17:55:24+01:00</published>
    <updated>2009-07-06T17:55:24+01:00</updated>
  </entry>
  <entry>
    <category term="xen" label="Xen"/>
    <category term="ubuntu" label="Ubuntu"/>
    <category term="virtualisation" label="virtualisation"/>
    <id>tag:reprocessed.org,2009-05-05:ttysno</id>
    <title type="text">ttySno</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>If, like me, you run a server somewhere pretending to be lots of servers thanks to <a href="http://xensource.org/">Xen</a>, and your guest domains keep logging problems with <code>ttyS0</code> (like this, perhaps:)</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/ttysno"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>If, like me, you run a server somewhere pretending to be lots of servers thanks to <a href="http://xensource.org/">Xen</a>, and your guest domains keep logging problems with <code>ttyS0</code> (like this, perhaps:)</p>

<pre><code>May  5 06:30:10 my_guest init: ttyS0 main process (1391) terminated with status 1
May  5 06:30:10 my_guest init: ttyS0 main process ended, respawning
May  5 06:30:20 gamecity init: ttyS0 main process (1430) terminated with status 1
May  5 06:30:20 gamecity init: ttyS0 main process ended, respawning
</code></pre>

<p>That's right. TWO lines every 10 seconds. Grrr. Now, xen uses <code>hvc0</code> and not <code>ttyS0</code> for domU guests. So, I don't actually need <code>ttyS0</code> unless I need my guests to have access to the physical serial port on the server. I don't. So, the easy fix is to stop <code>ttyS0</code> from being created (ever). To do that, on my <a href="https://help.ubuntu.com/8.04/serverguide/C/index.html">Ubuntu 8.04</a> guest, simply remove <code>/etc/event.d/ttyS0</code>. Don't remove this from Dom0, because that almost certainly will need access to the real serial port.</p>      </div>
    </content>
    <published>2009-05-05T22:21:03+01:00</published>
    <updated>2009-05-05T22:21:03+01:00</updated>
  </entry>
  <entry>
    <category term="AdaLovelaceDay09" label="Ada Lovelace Day 2009"/>
    <category term="dtp" label="DTP"/>
    <category term="acorn" label="Acorn"/>
    <category term="acorn_archimedes" label="Acorn Archimedes"/>
    <category term="bbc" label="BBC"/>
    <category term="bbc_micro" label="BBC Micro"/>
    <category term="bbc_model_b" label="BBC Model B"/>
    <category term="stuart_bathurst" label="Stuart Bathurst"/>
    <category term="sister_celsus" label="Sister Celsus"/>
    <id>tag:reprocessed.org,2009-03-24:the_nun_and_the_archimedes</id>
    <title type="text">The Nun and the Archimedes</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p><em>This post is my contribution to <a href="http://findingada.com/">Ada Lovelace day</a></em></p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/the_nun_and_the_archimedes"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p><em>This post is my contribution to <a href="http://findingada.com/">Ada Lovelace day</a></em></p>

<p>When I started secondary school, in 1988, I went to <a href="http://www.stuart-bathurst.org.uk/">Stuart Bathurst</a> in Wednesbury (Right next to Ikea, can't miss it, though there was no Ikea back then). At my junior school there had been a couple of <a href="http://en.wikipedia.org/wiki/BBC_Micro">BBC Micro</a>s floating around, but at Stuart Bathurst, they had an entire lab of BBC Micros in a room at the top of the four-storey block.</p>

<p>I was amazed. An entire room of computers. I had a couple of friends who had Spectrums plugged into TVs, but I don't think I knew anyone who had a computer with a proper monitor, let alone a roomfull, and I'd certainly never spent much time in front of one.</p>

<p>The teacher in charge of the computer room was a formidable and elderly Irish Nun named Sister Celsus. She was one of those teachers who was slightly terrifying, and could turn it up to boot-quaking if she thought you were messing around. I pretty soon realised that computers were much more fun than just about anything else I could do, and I hung out in the computer room whenever I could learning the rudiments of <a href="http://en.wikipedia.org/wiki/BBC_BASIC">BBC Basic</a>, and pretty much anything else I could out about the Beebs we had.</p>

<p>Sister Celsus, for her part, actively encouraged those of us who wanted to learn and allowed us special access. Things I recall doing with Sister Celsus and others in that room include dialling up BBSes (I can't remember much except that they were a lot like <a href="http://en.wikipedia.org/wiki/Ceefax">Ceefax</a>), attempting to programme text adventures, learning about databases (Enform, I think, which not even Google can identify for me). In 1989 my parents bought a second-hand BBC 'B' from my friend Mark, which opened up a whole new world of possibilities. Albeit, mostly <a href="http://en.wikipedia.org/wiki/Elite_" title="video_game">Elite</a>, <a href="http://en.wikipedia.org/wiki/Repton_" title="video_game">Repton</a> and more footling about. (Mark also attempted to teach me more programming. He mostly managed to fry my brain, but something took. He, on the other hand, wrote a hybrid Machine-code / Basic WIMP-based gui on his BBC. End of digression)</p>

<p>Perhaps most remarkably, Sister Celsus let me help with installing and connecting up a bunch of new computers when they were delivered. There were micro-powerstrips, which took a custom tiny plug (I guess they were similar in size to US plugs), instead of conventional sockets throughout the room. This made plugging in a new computer a process of cutting the old plug off and wiring on one of these tiny plugs. I was allowed to do this. The school had <a href="http://en.wikipedia.org/wiki/Econet">Econet</a> hooking up all the Beebs to a machine with a <a href="http://en.wikipedia.org/wiki/Early_IBM_disk_storage#IBM_3340">Winchester</a> disk. Econet's a pretty delicate thing. When I wired the brown cable to Earth (seemed logical to 12-year-old me, I didn't know it was really the Live), the computer I wired wrongly was fine, but a large number of econet chips were blown by the resulting short circuit. I have no idea how much money that mistake of mine cost the school. There was a loud bang, and I knew whatever it was was my fault, I was mortified, but Sister Celsus didn't get angry with me (she got angry with plenty of other people). She seemed to regard it as another learning experience, but I didn't wire any more plugs that day.</p>

<p>When I joined the school there was a single <a href="http://en.wikipedia.org/wiki/Acorn_Archimedes">Acorn Archimedes</a>. I don't remember much about that, but it must have been running <a href="http://en.wikipedia.org/wiki/Arthur_" title="operating_system">Arthur</a>, because I never found anything that looked like it on later models I used. Sometime in 1989 more Archimedes were bought, including an <a href="http://acorn.chriswhy.co.uk/Computers/A400.html#A440">A440</a> (big and powerful for the time) (and later an <a href="http://acorn.chriswhy.co.uk/Computers/A540.html">A540</a>, which seemed absurdly powerful at the time), a PostScript laser printer, and a copy of <a href="http://acorn.chriswhy.co.uk/docs/Acorn/Brochures/Acorn_APP149_DesktopPublisher.pdf">Acorn Desktop Publisher</a>.</p>

<p>Acorn DTP was, predictably enough, not exactly competitive with PageMaker or Quark. It was my window into design though. Sister Celsus' policy was 'Only the smart ones can use the Archimedes', and I was the lucky recipient of pretty much all the time I wanted. I was doing DTP, with access to a PostScript printer, in 1989 or 1990. With hindsight, that was pretty remarkable: to have had regular access to thousands of pounds worth of equipment, and able to do pretty much what I wanted. It wasn't until the mid nineties that I really realised that there was such a thing as Graphic Design, and that I'd been playing at it for nearly ten years.</p>

<p>I'm incredibly lucky to have had that kind of privileged access. At university, I wound up doing a year of Cybernetics, before switching to do Typography. Without the start Sister Celsus provided me (and those other kids in the late-80s Black Country) I never would have made it there, or been able to make that significant a switch. After she left, the school began to switch away from Acorn computers to Windows PCs, and computing at school became less and less about actually wrangling the machines for their own sake: programming went away, to be replaced by word processing and the other kinds of useful activities which I'm sure helped a lot of pupils gain the kind of computer literacy they needed for the real world, but it wasn't the kind of computer literacy I needed. I needed the more abstract, joyful, engagement with computers that Sister Celsus provided, and which could only have been provided at the end of the 80s.</p>

<p>In short, I think that without the intervention of Sister Celsus, I probably wouldn't be here, doing this. I'm profoundly grateful to have been in the right place at the right time to have that kind of a computing experience, under the watchful eye of a remarkable woman.</p>      </div>
    </content>
    <published>2009-03-24T14:13:06+00:00</published>
    <updated>2009-03-24T14:13:06+00:00</updated>
  </entry>
  <entry>
    <category term="sysadmin" label="sysadmin"/>
    <category term="ruby" label="Ruby"/>
    <category term="rubygems" label="Rubygems"/>
    <category term="packaging" label="packaging"/>
    <category term="deployment" label="deployment"/>
    <category term="package_management" label="package management"/>
    <category term="configuration_management" label="configuration management"/>
    <category term="development" label="development"/>
    <category term="dpkg-tools" label="dpkg-tools"/>
    <category term="dpkg-gem" label="dpkg-gem"/>
    <id>tag:reprocessed.org,2009-01-13:dpkg-gem</id>
    <title type="text">dpkg-gem: Ubuntu and Debian package building for Rubygems</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Well, it's been a couple more weeks than I promised (that Christmas, it gets <em>everywhere</em>), but here's the first follow-up from my <a href="http://reprocessed.org/blog/dpkg-tools"><code>dpkg-tools</code></a> from December.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/dpkg-gem"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Well, it's been a couple more weeks than I promised (that Christmas, it gets <em>everywhere</em>), but here's the first follow-up from my <a href="http://reprocessed.org/blog/dpkg-tools"><code>dpkg-tools</code></a> from December.</p>

<p>My big problem with anything in deployment is the ease with which you can get it onto your application server, and the degree of confidence you have that it will work right, and work right first time. I've always liked <a href="http://packages.debian.org/">Debian packages</a> because setting up a system was made very easy: you could guarantee that the a given piece of packaged software would install trivially (the <code>apt-get install package-name</code> dance), <em>and</em> would work -- since <a href="http://www.debian.org/">Debian</a> packages know about their dependencies, attempting to install Apache's <code>mod_php</code> (for example) would make sure that Apache and PHP were also installed, and install them if they weren't.</p>

<p>After several years spent seeing the evidence of the difficulties manually installing and configuring software on a large (at least, larger-than-one) array of servers I started to think that we should just package everything as OS packages, because at least then you could properly test a from-scratch deployment before the fact, and get that all-important guarantee that not only would things install easily, but they'd actually work. My pet irritant here is that if you try to install the MySQL rubygem on a <a href="http://www.ubuntu.com/">Ubuntu</a> box without the MySQL <em>client</em> installed, it won't work, since it needs to be compiled against the <code>libmysqlclient</code> shared library. You also need a C compiler (and basically all the packages covered by Debian/Ubuntu's <code>build-essential</code> metapackage). If you can get that rubygem into a package, then you can just install it, and all the dependencies will come right along...</p>

<p>So, that's what <code>dpkg-gem</code> is for. It takes a rubygem and makes it into something which can be built as a <code>.deb</code> package using the standard <code>.deb</code> package building toolchain.</p>

<h1>The 10,000 foot overview</h1>

<p>The <code>.deb</code> package building process for non-native (by which is meant not-already-Debianed) software looks a little like this:</p>

<ol>
<li><p>Add the <code>.deb</code> package metadata to the software, which basically amounts to adding the <code>debian/</code> directory 
and its various files.</p></li>
<li><p>Make any changes you need to to bring the software into compliance with whatever Debian policy points are 
relevant and are needed to actually make it build. Add package metadata to <code>debian/</code>, like build and install
dependencies. Making it build may well involve changing the <code>debian/rules</code> file, which is a Makefile with 
specific targets for the various (<a href="http://www.debian.org/doc/debian-policy/ch-source.html#s-debianrules">defined in the Debian Policy Manual</a>) stages of package 
building (triggers for <code>make</code> and <code>make install</code> or their equivalents). There's some overlap with #3 here,
since you'll use package builders to test building works.</p></li>
<li><p>Actually build <code>.deb</code> and <code>.dsc</code> packages (reliably and repeatably). You do this using a tool like 
<code>dpkg-buildpackage</code> (Part of the <a href="http://packages.debian.org/etch/dpkg-dev"><code>dpkg-dev</code> package</a>), which performs all the build steps 
necessary and spits out a <code>.dsc</code> source package, a <code>.deb</code> binary package, or both at once. You can split 
the process in two, just generate source packages and gets those built using an automated builder, which 
is what Debian and Ubuntu do to generate all the packages in their distributions -- thousands of packages 
are too many to do by hand</p></li>
<li><p>Make the resulting binary packages available from an APT repository, which basically means putting things on 
a web server, along with some specially generated indexes for <code>apt-get</code>. There are a variety of tools for doing it.</p></li>
</ol>

<h1>How <code>dpkg-gem</code> fits into this</h1>

<p>The hard bits about turning a <code>.gem</code> into a <code>.deb</code> are numbers 1 and 2 above, and where <a href="http://dpkg-tools.rubyforge.org/"><code>dpkg-gem</code></a> comes in. Given that gems are themselves packages, there's an awful lot of redundancy if you create all the <code>.deb</code> metadata and build scripts by hand, not to mention plenty of scope for handwork introducing discrepancies. The solution I chose was to using Rubygems own classes to introspect a gem's own metadata to create the <code>.deb</code> metadata, and to use Rubygems itself during the build process. The resulting package would then be, essentially, the things that would have been added to your filesystem after you'd run <code>gem install</code>. The process looks something like:</p>

<ol>
<li><code>dpkg-gem</code> downloads the gem into a directory it creates named <code>gemname-rubygem-X.Y.Z</code></li>
<li>Next, we introspect the gem and create the <code>debian/</code> directory and the various metadata files: 
<code>debian/control</code>, <code>debian/changelog</code>, <code>debian/copyright</code>, and <code>debian/files</code>. </li>
<li>Now we copy the default <code>dpkg-gem</code> <code>debian/rules</code> script, which is actually a cheat. The script is really 
a Rakefile, so gets copied into the root of <code>gemname-rubygem-X.Y.Z</code> (as <code>Rakefile</code>). <code>debian/rules</code> is a 
one-line shell script that invokes <code>rake</code> and passes in all its arguments. This is to get around the fact 
that a 'normal' <code>debian/rules</code> file is actually a Makefile, with the shebang line <code>#!/usr/bin/make -f</code>. 
<code>make</code>'s quite clever and will act like a shell here, sucking in the rest of the file. <code>rake</code>'s not (yet) 
able to do that, so we need this little bit of indirection.</li>
</ol>

<p>Once we're there, the standard <code>.deb</code> toolchain will work just fine: All the metadata is there, and we have a Rakefile which behaves like a <code>debian/rules</code> file should. There is a caveat. Currently, you need to have Rubygems 0.9.4 to make all this work - because of certain limitations that were present in Rubygems (problems with choosing which version of a gem to grab, and problems putting <code>binary</code> scripts in the right place, primarily) I had to delve fairly deep into the internals in a couple of places, and it's broken in 0.9.5 and above. You also need my Rubygems package for Debian / Ubuntu, because the as-standard Rubygems package has some really quite nasty hacks in it, which would break system-installed (i.e. installed from packages) gems. You can <a href="http://rubyforge.org/frs/?group_id=5326&amp;release_id=30377">get the two <code>.deb</code>s from Rubyforge</a>. </p>

<p>On the assumption that you're on a Ubuntu box, here's an example which installs dpkg-tools and packages a simple gem with no dependencies (but with some C code in it, for a little spice).</p>

<pre><code># first let's install Rubygems and dpkg-tools
# assuming we've downloaded the Rubygems .debs
$ sudo aptitude update
$ sudo aptitude install build-essential
$ sudo dpkg -i librubygems-BLAH
$ sudo dpkg -i rubygems-BLAH

# nasty little first-time bootstrap coming up
$ sudo gem install rake dpkg-tools

# now for the first packaged gem, Rake. Then, dpkg-tools itself
$ dpkg-gem rake
$ dpkg-gem dpkg-tools

# note the -d option to dpkg-buildpackage. It turns off dependency checking
# You really don't want that usually...
$ cd dpkg-tools-rake-0.8.3; dpkg-buildpackage -d -rfakeroot; cd ../
$ sudo dpkg -i dpkg-tools-rubygem_0.8.3-1.all.deb
$ cd dpkg-tools-rubygem-0.3.5; dpkg-buildpackage -d -rfakeroot; cd ../
$ sudo dpkg -i dpkg-tools-rubygem_0.3.5-1.all.deb

# now we'll be able to satisfy gems' build dependency on dpkg-tools itself
# and build the RDiscount gem as a package
$ dpkg-gem rdiscount
$ cd rdiscount-rubygem-0.BLAH; dpkg-buildpackage -rfakeroot; cd ../
$ sudo dpkg -i rdiscount-rubygem.BLAH.deb
</code></pre>

<p>Setting up the build machine is the biggest bit (but even that only requires 8 commands).</p>

<p>If you were to package a gem with dependencies (like Rails), then <code>dpkg-gem</code> pulls all the dependencies down too, so you don't have to worry about missing anything.</p>

<h2>What about packages with native dependencies?</h2>

<p>This is the hardest part of any automated package generation. My approach so far has been to maintain a lookup table in <code>dpkg-gem</code> itself which matches gems with native dependencies to the package providing that dependency, so the MySQL gem gets its package control file generated with a build dependency on the <code>libmysqlclient-dev</code> package. (Embarassingly, I've just noticed a bug - we don't generate install dependencies. Oh well, a <a href="http://dpkg-tools.lighthouseapp.com/projects/12374-dpkg-tools/tickets/13">ticket has been filed</a>.) I'm quite unhappy with the lookup approach and am looking into other methods. Currently <code>apt-file</code> looks like the best approach, but to properly automate that at the moment needs some kind of lookup, but probably not such a brain dead one. Currently, <code>dpkg-gem</code> only knows about gems with native extension dependencies which I've been using and have told it about, which means the MySQL gem. If you want more in, then I'll be adding more entries to the lookup, and please <a href="http://dpkg-tools.lighthouseapp.com/projects/12374-dpkg-tools">file tickets</a> at the Lighthouse project.</p>

<h1>Package building and distribution</h1>

<p>It's one thing to be able to turn a gem into a package and install it locally, but unfortunately it's quite another to be able to install it using <code>aptitude</code> or <code>apt-get</code> on many machines. Steps three and four from the 10,000 foot overview are the industrial application of the packaging techniques, the bit which makes them most useful, and the bit which is the hardest to effectively manage.</p>

<p>Debian and Ubuntu have automated package build farms. There are packages like <a href="http://packages.debian.org/etch/pbuilder">pbuilder</a> and <a href="http://packages.debian.org/etch/sbuild">sbuild</a>, which automate satisfying build-dependencies and provide guaranteed-clean build environments through <code>chroot</code>ed minimal OS installs (and other techniques).</p>

<p>Distribution, at least as far as APT is concerned, is a matter of setting making a filesystem hierarchy which APT understands available, either locally or via a web server. There are a variety of ways to do this, from the 90% hand-rolled approach, through to more automated solutions. The end result is that you have a network-accessible package repository so you can easily deploy your packages to one or a number of machines. I use this, and have a dedicated repository with all my Gem related packages, as well as application deployment stuff, which makes setting up new machines (I use VMs, so tend to just spin up a new one if I want to test something out) a breeze.</p>

<p>If you want to hand-roll an APT repository, you can see this <a href="http://www.debian.org/doc/manuals/repository-howto/repository-howto.en.html#id2479944">Debian repository HOWTO</a>. If you want a more automated solution try <a href="http://mirrorer.alioth.debian.org/"><code>reprepro</code></a>. When I set up a <code>reprepro</code>-based APT repository, I found this <a href="http://www.jejik.com/articles/2006/09/setting_up_and_managing_an_apt_repository_with_reprepro/">Reprepro tutorial</a> really handy.</p>

<h1>Next steps</h1>

<p>There are a couple of obvious next steps around <code>dpkg-gem</code> itself, involving native extensions with native dependencies, and updating the code to work with current Rubygems itself, which hopefully now means less mucking with internals, and definitely more engagement with Rubygems folks (around API issues and to test out some ideas I have around native dependencies).</p>

<p>The other pressing issues (for me at least) are automated package building, which means writing a dependency checker and wiring it into <code>pbuilder</code> or <code>sbuild</code>, and making a public APT repository for gems available. This is something I've been talking about with a few people since early last year, so I guess I should get a shift on.</p>

<p>Further into the future, the next obvious thing to look at is to make <code>dpkg-gem</code> (and the whole <code>dpkg-tools</code>) suite package-format agnostic, and be able to produce packages <code>.rpm</code> and other package formats with the same toolchain.</p>

<h1>Phusion's DebGem</h1>

<p>In the time between starting and finishing this post, <a href="http://phusion.nl/">Phusion</a> have released their <a href="http://blog.phusion.nl/2009/01/06/announcing-debgem-beta-the-rubygem-to-apt-conversion-service/">DebGem</a> product. My first impressions are that it's great that someone else thought this was a problem worth solving, but I need to take a closer look. I'm interested that they haven't adopted a package suffix (like <code>dpkg-gem</code>'s <code>-rubygem</code> suffix) to prevent package name clashes (there are thousands of Debian packages, so clashes are inevitable). But it looks pretty good.</p>      </div>
    </content>
    <published>2009-01-13T12:37:16+00:00</published>
    <updated>2009-01-13T12:37:16+00:00</updated>
  </entry>
  <entry>
    <category term="sysadmin" label="sysadmin"/>
    <category term="ruby" label="Ruby"/>
    <category term="rubygems" label="Rubygems"/>
    <category term="packaging" label="packaging"/>
    <category term="deployment" label="deployment"/>
    <category term="package_management" label="package management"/>
    <category term="configuration_management" label="configuration management"/>
    <category term="development" label="development"/>
    <category term="dpkg-tools" label="dpkg-tools"/>
    <id>tag:reprocessed.org,2008-12-19:dpkg-tools</id>
    <title type="text">Introducing dpkg-tools: Ubuntu and Debian package building for Rubygems and more</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Something I found myself wrestling with a lot towards the end of my time at the BBC, and something I've been thinking a lot about since, is the deployment of entire servers, not just the deployment of software onto servers. I've spent nearly ten years working with Linux distributions and their OS package management systems, primarily <a href="http://www.redhat.com/">Red Hat</a> and <a href="http://www.debian.org/">Debian</a>-based systems (<a href="http://www.ubuntu.com/">Ubuntu</a>, lately). I've also spent a lot of time working with Python and Ruby's OS-independent packaging systems (<a href="http://docs.python.org/distutils/">Distutils</a>, a tiny bit of <a href="http://peak.telecommunity.com/DevCenter/setuptools">Setuptools</a>, and <a href="http://rubygems.org/">Rubygems</a>).</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/dpkg-tools"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>Something I found myself wrestling with a lot towards the end of my time at the BBC, and something I've been thinking a lot about since, is the deployment of entire servers, not just the deployment of software onto servers. I've spent nearly ten years working with Linux distributions and their OS package management systems, primarily <a href="http://www.redhat.com/">Red Hat</a> and <a href="http://www.debian.org/">Debian</a>-based systems (<a href="http://www.ubuntu.com/">Ubuntu</a>, lately). I've also spent a lot of time working with Python and Ruby's OS-independent packaging systems (<a href="http://docs.python.org/distutils/">Distutils</a>, a tiny bit of <a href="http://peak.telecommunity.com/DevCenter/setuptools">Setuptools</a>, and <a href="http://rubygems.org/">Rubygems</a>).</p>

<p>What I've been wanting to do is to tie down configuration management and deployment processes so that Rails apps, and the server they ran on, could be easily deployed as a Virtual Machine on a machine running the Xen virtualisation system. Basically to tie the server configuration management problem much more tightly to the application deployment problem.</p>

<p>Systems such as <a href="http://reductivelabs.com/trac/puppet">Puppet</a> tackle one aspect of the problem: the question of what to install, and the related question of how it should be configured. I'm interested in that, but mainly I've been interested in the question of how do you get things -- apps, supporting libraries, supporting software services -- onto a server in a sensible fashion, and how do you ensure that they're going to work with the base server's software and OS. Debian and Red Hat's answer to these questions has been OS packaging: <a href="http://www.rpm.org/"><code>rpm</code></a> and <a href="http://yum.baseurl.org/"><code>yum</code></a> for Red Hat and <a href="http://www.debian.org/doc/FAQ/ch-pkgtools.en.html"><code>dpkg</code></a> and <a href="http://wiki.debian.org/Apt"><code>apt</code></a> for Debian. With this you get pre-compiled binaries which are guaranteed to work because they were compiled against all the same libraries that you'll have installed, and you get dependency tracking and resolution. Dependency tracking means you can guarantee (assuming a quality package) that you've got everything installed that needs to be installed, and that everything's the right version to work with everything else. This is great, and is one of the things that's made Linux server distros so compelling - if you need an X (mail server, web server, whatever), there's a good chance you can get it installed and minimally working with a single command.</p>

<p>OS-independent packaging systems for languages, like Rubygems, solve a very similar problem. The difference is that they assume that you're able to sort out the underlying OS stuff yourself, making sure you've got the right C compiler, or supporting libraries, or whatever installed. What they give you is a cross-platform way of getting their language-specific stuff installed, often with dependency tracking, but just for other packages of the same kind, so Rubygems gives you dependency tracking which covers other Gems, but not the OS.</p>

<p>Which brings me back to Rails apps. The big problems with Rails apps and getting them installed and working is making sure that all the Ruby bits, and any supporting C stuff (like the MySQL bindings, or libxml2), are installed, and installed correctly. So, we have a mechanism for getting a Rails app onto a box -- application deployment -- in <a href="http://www.capify.org/">Capistrano</a>, a mechanism for installing and managing Ruby libraries in Rubygems, and a mechanism for installing and managing the underlying OS in <code>dpkg</code>/<code>apt</code> and <code>rpm</code>/<code>yum</code>. What we don't have is an easy mechanism for tying the OS layer to the Ruby layer in a meaningful way. With a tool like Puppet we can get the result we want, but we have to jump through more hoops: We need to figure out what OS stuff is required for the Ruby stuff we want to deploy, and then get Puppet to download (and often compile) the things we need. It's a bit brittle though: Where OS packages have their dependencies listed and baked in to the package, with a Puppet recipe that compiles up some arbitrary piece of software (the MySQL Gem, for argument's sake), you need to list any dependencies in your recipe. </p>

<p>The problem is pace layering. The OS packages are a different layer and move at a different speed to your Puppet recipe. So, a security update might force a change to the OS MySQL client libraries which means that your MySQL Gem no longer works. If you catch this beforehand and update your Puppet recipe, once the security update has been deployed you can recompile the MySQL Gem, for minimal downtime. If you don't catch it you have a machine where your App is suddenly no longer able to talk to the database, even though all the MySQL command line tools say that everything's fine.</p>

<p>My approach to this problem has been to bake the Ruby layers into OS packages, so that I'm using one dependency declaration and resolution system. This allows you to do several really cool things, not least simplifying the number of commands you need to use to get your app deployed. This blog is running on Ubuntu, and to install the entire system from bare OS (caveat: it's a VM on a Xen host and my image creation script added my private Apt repository to Apt's configuration) required one command:</p>

<pre><code>aptitude install reprocessed
</code></pre>

<p>Then I did a <code>cap deploy</code>, and hey presto, everything worked.</p>

<p>I don't see this as a replacement, or even as a competitor, for systems like Puppet. I think that instead, it allows you to be more declarative in your Puppet recipes. Instead of saying 'This machine should be an app server running X, so install Y package, download and compile Rubygem Z...' you can simply say 'This machine should be an app server running X'</p>

<p>I'm a big fan of the Ubuntu Linux distribution, which is Debian-based and so uses <code>.deb</code> packages and the <code>dpkg</code> and <code>apt</code> infrastructure. The set of tools I've built to work with these packages are called <code>dpkg-tools</code>. You can go and look at <a href="http://http://github.com/fidothe/dpkg-tools/tree/master"><code>dpkg-tools</code> on Github</a>, where you can get the source, and where most of the non-RDoc documentation will live. There's also the <a href="http://dpkg-tools.lighthouseapp.com/projects/12374-dpkg-tools/overview">Lighthouse page</a> and the <a href="http://dpkg-tools.rubyforge.org/">Rubyforge project</a>, which has all the RDoc. <code>dpkg-tools</code> is split into three main parts: <code>dpkg-gem</code>, which facilitates building <code>.deb</code>s from Gems; <code>dpkg-etc</code>, which makes it really easy to package up system configuration information; and <code>dpkg-rails</code>, which makes packages from Rails apps and handles declaring configuration for an Apache 2/Mongrel/<code>mod_proxy_balanacer</code> setup.</p>

<h2>A brief digression into motivations and potential political pitfalls</h2>

<p>It's worth noting that there's been a lot of controversy over Rubygems and Debian -- see Debian's <a href="http://pkg-ruby-extras.alioth.debian.org/rubygems.html"><code>pkg-ruby</code> activity's policy statement</a>, and Pelle Braendgaard's <a href="http://stakeventures.com/articles/2008/12/04/rubygem-is-from-mars-aptget-is-from-venus">RubyGem is from Mars, AptGet is from Venus</a> blog post. My personal opinion is that, while Rubygems has its fair share of issues, it's faced with a very different set of constraints from Debian's, and has to operate across wildly different operating systems. Because of this, I think that Debian's position is a little harsh, and perhaps misses the point. I also think that the major bone of contention, the FHS (<a href="http://www.pathname.com/fhs/">Filesystem Hierarchy Standard</a>) has some serious blindspots, particularly around dynamic languages and what happens when the line between library and directly-executable begins to get very blurry. Debian's Ruby maintainers group has seen fit to respond to this by making some very strange changes to the Rubygems library itself, and shipping this patched version as the official Debian Rubygems package.</p>

<p>My solution, therefore, is not something I'm proposing as an official solution to replace all the existing Debian Ruby packages, rather, it'a a more pragmatic solution that is firmly targetted at my needs. I provide what amounts to a 'normal' version of Rubygems-the-library, and then make <code>.deb</code> packages of Rubygems that put all the bits where the normal Rubygems expects to find them. While I'd love to see Debian-based distros and Rubygems play nicer together as standard, when I started this I didn't have the time to wait, and I didn't think I understood the issues well enough to make a considered contribution. Hopefully it'll prove useful to some people, and will at least provide a talking point for others...</p>

<h2>Back to the subject at hand</h2>

<p>I'll be covering each of the bits of <code>dpkg-tools</code> in future blog posts, starting with <code>dpkg-gem</code>, the Rubygem packaging part, early next week. In the meantime, please direct comments to the usual address (matt at this domain).</p>      </div>
    </content>
    <published>2008-12-19T17:00:24+00:00</published>
    <updated>2008-12-19T17:00:24+00:00</updated>
  </entry>
  <entry>
    <category term="ruby" label="Ruby"/>
    <category term="rails" label="Rails"/>
    <category term="ruby_on_rails" label="Ruby on Rails"/>
    <category term="rspec" label="RSpec"/>
    <category term="mocha" label="Mocha"/>
    <category term="mock_objects" label="Mock objects"/>
    <category term="testing" label="testing"/>
    <category term="development" label="development"/>
    <category term="model_mocker" label="ModelMocker"/>
    <category term="test_driven_development" label="Test-driven development"/>
    <category term="behaviour_driven_development" label="Behaviour-driven development"/>
    <id>tag:reprocessed.org,2008-12-12:introducing_model_mocker</id>
    <title type="text">Introducing ModelMocker</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>While writing Rails apps, I've written several variants on the 'give me an ActiveRecord instance that can't talk to the DB' theme over the last couple of years while writing tests or specs for an app. The basic pattern is a pretty good one - it guarantees you a certain degree of test isolation for your unit tests or specs, when you need it. And, because you're make specific instances isolated, you can get to the DB if you need to. </p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/introducing_model_mocker"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>While writing Rails apps, I've written several variants on the 'give me an ActiveRecord instance that can't talk to the DB' theme over the last couple of years while writing tests or specs for an app. The basic pattern is a pretty good one - it guarantees you a certain degree of test isolation for your unit tests or specs, when you need it. And, because you're make specific instances isolated, you can get to the DB if you need to. </p>

<p>I've done it enough times now that I wound up making a plugin to share the code between projects. As time has gone on, I've wanted something a bit more declarative too, so that I could make sensible statements about the intended validity or newness of the object, since I've often found myself using it in concert with mocking and stubbing. It's quite nice to be able to ask for an invalid instance without having to worry about setting or not setting the right fields to get a valid or invalid object. Often, it's enough to know that <code>.valid?</code> will fail. So, with my <em>ModelMocker</em> plugin, you can do things like this:</p>

<pre><code>&gt;&gt; mock_object = ModelClass.mock { |m| m.as_new_record }
&gt;&gt; mock_object.new_record?
=&gt; true
</code></pre>

<p>Or,</p>

<pre><code>&gt;&gt; mock_object = ModelClass.mock do |m|
?&gt;   m.as_new_record
?&gt;   m.invalid
?&gt; end
&gt;&gt; mock_object.new_record?
=&gt; true
&gt;&gt; mock_object.valid?
=&gt; false
</code></pre>

<p>And, in a slight twist:</p>

<pre><code>&gt;&gt; mock_object = ModelClass.mock(:id =&gt; 123, :other_attr =&gt; "value")
&gt;&gt; mock_object.new_record?
=&gt; false
&gt;&gt; mock_object.id
=&gt; 123
</code></pre>

<p>Being able to specify the <code>id</code> is very useful, and I always found myself wanting ActiveRecord objects with IDs to act like they were fetched from the DB, so I made setting this (mock) ID imply that the object should behave like a saved one. </p>

<p>The plugin is <a href="http://github.com/fidothe/model_mocker">available from GitHub</a>, and is installed (with a Rails that can install plugins from Git) with:</p>

<pre><code>./script/plugin install git://github.com/fidothe/model_mocker.git
</code></pre>

<p>The only setup you need to do is to <code>require model_mocker'</code> in your <code>spec_helper.rb</code> (or somewhere equivalent).</p>

<p>ModelMocker's <a href="http://reprocessed.org/rdoc/model_mocker">RDoc is on reprocessed.org</a>, as well as being installed with the plugin.</p>      </div>
    </content>
    <published>2008-12-12T19:58:26+00:00</published>
    <updated>2008-12-12T19:58:26+00:00</updated>
  </entry>
  <entry>
    <category term="reboot" label="Reboot"/>
    <category term="reboot10" label="Reboot 10"/>
    <category term="presentation" label="presentation"/>
    <category term="design" label="design"/>
    <category term="praxis" label="praxis"/>
    <category term="talk" label="talk"/>
    <category term="craft" label="craft"/>
    <category term="typography" label="typography"/>
    <category term="agile" label="agile"/>
    <category term="software" label="software"/>
    <category term="development" label="development"/>
    <id>tag:reprocessed.org,2008-09-25:craft_and_process</id>
    <title type="text">Craft &amp; Process</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I was lucky enough to be at <a href="http://reboot.dk/">Reboot 10</a>, back at the end of June. I gave a prototype talk working through some ideas I've been thinking about for a while (stuff that I started to work at with my <a href="http://reprocessed.org/blog/everything_i_know_about_programming_i_learnt_from_typography">Everything I know about Programming I learnt from Typography</a> talk at the first <a href="http://barcamp.org/BarCampLondonSep06">BarCamp London</a>). The talk was called <a href="http://www.reboot.dk/artefact-5641-en.html">Craft &amp; Process</a>, and was essentially a braindump and not a real talk - I had a bunch of sketchy notes for an overall structure and talked my way from the start of the notes tothe end...</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/craft_and_process"/>
    <link rel="enclosure" type="audio/mpeg" title="Craft &amp;amp; Process: Recorded at Reboot 10, Copenhagen, 27 June 2008" href="/downloads/presentations/craft_and_process.mp3" length="49959932"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>I was lucky enough to be at <a href="http://reboot.dk/">Reboot 10</a>, back at the end of June. I gave a prototype talk working through some ideas I've been thinking about for a while (stuff that I started to work at with my <a href="http://reprocessed.org/blog/everything_i_know_about_programming_i_learnt_from_typography">Everything I know about Programming I learnt from Typography</a> talk at the first <a href="http://barcamp.org/BarCampLondonSep06">BarCamp London</a>). The talk was called <a href="http://www.reboot.dk/artefact-5641-en.html">Craft &amp; Process</a>, and was essentially a braindump and not a real talk - I had a bunch of sketchy notes for an overall structure and talked my way from the start of the notes to the end...</p>

<p>The central idea I've been looking at is that one of the main ways we think about building software and, by extension, all the aspects of applications for the web, is wrong: building software and web apps as an essentially industrial process, managed as if it were mass manufacture, with an underlying assumption that the work involved is repeatable and well-defined. My assertion is that it's actually more like a craft process: that the work is generally unique, and heavily defined by context. </p>

<p>I recorded the audio of the talk. Unfortunately it's not the greatest since I was just using the built-in microphone on my MacBook, but it's listenable. You can grab the audio from the link below (and your newsreader should recognise it as an enclosure). </p>

<p>It's about an hour long, and one of the main things I've noticed is that I was trying to cover far too much ground. There're probably at least two decent talk ideas hiding in there, which I'm looking at developing into proper talks. Hopefully, you'll find it interesting. Please do email me (matt at this domain) if you've got comments or queries.</p>

<p>I made notes on what happens during it, with links out to things I mentioned, and which address areas where I didn't come across in the way I meant to.</p>

<h1>Notes</h1>

<ul>
<li><p><em>02:50 - Vertically separated stacks of people</em></p>

<p>Here I'm talking about highly-specialised people grouped by role who don't (or don't get) 
to talk much to people from other disciplines, the classic role silos in which. I'm not 
sure if I should have said 'horizontally-separated' instead, but hey.</p></li>
<li><p><em>07:48 - Michael Harvey</em></p>

<p>He's a type designer and letterer who, among other things, is a renowned carver of letters 
in stone. I was using him as an example of someone with great depth of skill drawn from 
long experience. Here's his <a href="http://www.fonts.com/AboutFonts/DesignerProfiles/MichaelHarvey.htm">bio on Fonts.com</a>.</p></li>
<li><p><em>09:10 - Limitations of craft</em></p>

<p>I really need a better example here: time for more research, I think.</p></li>
<li><p><em>10:26 - DTP</em></p>

<p>For more on this, see my dissertation: <a href="http://reprocessed.org/writings/essays/dissertation.html">Typography and electronic document specification: 
An investigation</a></p></li>
<li><p><em>14:26 - 'Academic surveys'</em></p>

<p>I was thinking particularly of this paper by Alison Black when I said that <a href="http://www.informaworld.com/smpp/content~content=a777713744~db=all~order=page">Visible planning on paper and on screen: The impact of working medium on decision-making by novice graphic designers</a></p></li>
<li><p><em>14:30 - Paul Stiff's paper</em> 'Instructing the printer: what specification tells 
about typographic designing'</p>

<p>This fantastic paper is in Typography Papers 1, from 1996. You can't buy it anymore, and 
all web references to it seem to have vanished, which is annoying. You might be able to 
track down a copy in a library. Its ISBN is 0 7049 1120 5. If you're in London and you ask 
nicely, I might be able to lend you my copy.</p>

<p>It's worth clarifying what I mean when I say that the chief product of the design process 
was not an object, but a specification. Before DTP, if you were designing for commercial 
print then you would submit a specification to the printer. If you were designing a book 
then you'd produce a series of layouts which showed the main features of the design. These 
layouts wouldn't amount to more than a few pages worth of material. The printer would use 
these to infer how a manuscript should be laid out, and in the ideal world the 
specification would cover enough variations that the printer could easily produce a printed 
object that conformed to the designer's idea.</p></li>
<li><p><em>15:29 - Grice's maxims</em></p>

<p><a href="http://en.wikipedia.org/wiki/Gricean_maxims">Grice's maxims of conversation</a>. These maxims get applied by Paul Stiff to typographic 
specification, positing the specification as a dialogue between typographer and printer: </p>

<blockquote>
    <p>Under the third category of 'relation' is the maxim: 'Be relevant.' In other words, 
    don't say unnecessary or inappropriate things; for example, don't specify trimmed 
    paper sizes or inks to the compositor, or word spaces to the press operator.</p>
</blockquote></li>
<li><p><em>23:25 - The Chicken Sexer</em></p>

<p>Oh, good grief, where do you start with the <a href="http://en.wikipedia.org/wiki/Chick_sexing">Chicken Sexer</a>? At dConstruct 2007, 
<a href="http://www.uie.com/brainsparks/">Jared Spool</a> presented. One of his arguments was about designers being unable to explain how they know what they know. Start at slide 11 of <a href="http://www.uie.com/brainsparks/2007/11/28/slides-with-audio-for-the-dawning-of-the-age-of-experience/">The Dawning of the Age of Experience</a>. I call this the savant fallacy. The main problem I have with it is the idea that designers (in this case) absorb knowledge and develop skill by some analogue of osmosis and <strong>cannot explain</strong> how they know what they know, or why they make the choices they make. I've encountered a lot of this in graphic design too, where this studied inarticulacy is often some kind of perverse badge of honour - almost as if you can't be a proper rock star designer if you're able to actually talk about how you work, rather than just presenting results.</p>

<p>This is a kind of gnosticism, which allows the designer to avoid justifying how and why they did what they did, and appeal to a kind of special revelation instead, which also serves to keep you separate from the people you're working for - both clients and users. I think that you can talk about your work. You can talk about a project, and what happened along the way: where the problems were, what did and didn't work, where the breakthroughs came. You can, in short, show your working.</p></li>
<li><p><em>24:30 - Literate Programming</em></p>

<p>Ah, Donald Knuth. <a href="http://en.wikipedia.org/wiki/Literate_programming">Wikipedia's Literate programming page</a> is a good place to start. Actually, I had TeX pinned as being earlier than it really was, but I don't think it matters particularly to what I was saying.</p></li>
<li><p><em>26:30 - <a href="http://www.hyphenpress.co.uk/authors/norman_potter">Norman Potter</a> &amp; <a href="http://www.hyphenpress.co.uk/authors/anthony_froshaug">Anthony Froshaug</a></em></p>

<p>Potter, especially, is a hero of mine, but they're both fantastic examples of engaged practitioners: designers who took control of the whole process of making, from design to manufacture: Potter with his furniture workshop in Wiltshire and Froshaug with his printing workshop in Cornwall. Both looked to see what evolving technology and experience could offer them, both in terms of how they worked and what they could make.</p></li>
<li><p><em>30:30 - Stitch 'n Bitch</em></p>

<p>The <a href="http://en.wikipedia.org/wiki/Stitch_'n_Bitch">Stitch 'n Bitch Wikipedia page</a> seems to be the best starting point. While the internet has helped radically change how social knitting groups form and meet, I don't think they've radically changed the practice and techniques of knitting. I guess you could argue about stuff like yarns made from plastic bags, but I think that their emphasis (as 'movements') has been the social aspects.</p></li>
<li><p><em>31:20 - Chief Programmer teams</em></p>

<p>I think I'd taken something I was reading in Fred Brooks' Mythical Man Month and read something slightly different into it: the Chief Programmer Team pages at <a href="http://everything2.com/index.pl?node_id=1292141">everything2</a> and <a href="http://forums.construx.com/blogs/stevemcc/archive/2008/03/31/chief-programmer-team-update.aspx">Construx</a>, but it's still interesting: small inter-disciplinary teams, with a single leader who manages and writes...</p></li>
<li><p><em>34.50 - Specialisation is for insects</em></p>

<p>It's a <a href="http://en.wikipedia.org/wiki/Robert_A._Heinlein">Heinlein</a> quote, taken from his 1973 novel <a href="http://www.amazon.co.uk/gp/product/0441810764?tag=reprocessedor-21">Time Enough For Love</a>. (Also, rendered <a href="http://www.nitrosyncretic.com/dfv_sifi.html">as an illuminated manuscript</a>.)</p>

<blockquote>
    <p>A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, 
    design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, 
    take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, 
    pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. 
    Specialization is for insects.</p>
</blockquote>

<p>I was being slightly facetious with this: I certainly don't think that people with specialized skills are pointless, and I certainly don't think that one person can be good at everything. What I've found is that encouraging specialisms with impermeable boundaries, so that someone isn't supposed to know about visual design and HTML/CSS, or HTML and programming, is a very dangerous place to go: it encourages the worst kinds of professional disrespect: the mutterings of 'oh, they're just an [insert profession here], they can't understand this problem...', and people in one silo requesting totally inappropriate things for people in other silos. It blinds you to the insights that working from a slightly different angle give you, and it prevents anyone having an accurate mental model of a system.</p>

<p>That's what I was complaining about, not the very existence of information architects, or web designers who can't work a database.</p></li>
<li><p><em>35.10 - In which I ask a bad rhetorical question as if it were a real question, and ask it badly</em></p>

<p>My point was that supposed to be that exciting new web products are almost never built by enormous discipline-siloed teams. They may well become something which is run and expanded by a very large organisation, but the best examples of new products come from small, multi-disciplinary, teams. I guess I could have just said that instead of posing a rhetorical question and expecting people to answer it, like a smug idiot. Sorry.</p></li>
</ul>      </div>
    </content>
    <published>2008-09-25T23:36:22+01:00</published>
    <updated>2008-09-25T23:36:22+01:00</updated>
  </entry>
  <entry>
    <category term="pitchspace" label="PitchSpace"/>
    <category term="pr" label="PR"/>
    <category term="journalism" label="journalism"/>
    <category term="startup" label="startup"/>
    <id>tag:reprocessed.org,2008-08-20:pitchspace</id>
    <title type="text">One of the reasons things have been quiet round here</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>There's lots of stuff happening round here, and of the big ones is that I've become the Technical Director (think CTO) for a startup called <a href="http://pitchspace.com/">PitchSpace</a>. You can hear our MD, the lovely <a href="http://imaj.es/">James Cox</a>, on today's <a href="http://www.guardian.co.uk/technology/audio/2008/aug/19/tech.weekly.podcast">Guardian Tech Weekly Podcast</a>. The Guardian's Jemima Kiss also has <a href="http://blogs.guardian.co.uk/digitalcontent/2008/08/can_pitchspace_fix_pr.html">an article about us</a> up on the PDA blog about us. I'll be talking about what we're up to here and on the <a href="http://pitchspace.wordpress.com/">PitchSpace blog</a>. It's going to be an interesting ride.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/pitchspace"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>There's lots of stuff happening round here, and of the big ones is that I've become the Technical Director (think CTO) for a startup called <a href="http://pitchspace.com/">PitchSpace</a>. You can hear our MD, the lovely <a href="http://imaj.es/">James Cox</a>, on today's <a href="http://www.guardian.co.uk/technology/audio/2008/aug/19/tech.weekly.podcast">Guardian Tech Weekly Podcast</a>. The Guardian's Jemima Kiss also has <a href="http://blogs.guardian.co.uk/digitalcontent/2008/08/can_pitchspace_fix_pr.html">an article about us</a> up on the PDA blog about us. I'll be talking about what we're up to here and on the <a href="http://pitchspace.wordpress.com/">PitchSpace blog</a>. It's going to be an interesting ride.</p>      </div>
    </content>
    <published>2008-08-20T11:51:52+01:00</published>
    <updated>2008-08-20T11:51:52+01:00</updated>
  </entry>
  <entry>
    <category term="sysadmin" label="sysadmin"/>
    <category term="maintenance" label="maintenance"/>
    <category term="mod_rewrite" label="mod_rewrite"/>
    <category term="apache" label="Apache"/>
    <id>tag:reprocessed.org,2008-07-29:feeds_moved</id>
    <title type="text">Apparently I need to tell you that the feeds moved after all</title>
    <summary type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>For those of you who subscribe to the feeds...</p>

<p>It looks like a lot of feed readers don't follow permanent redirects sent by servers, and I changed the location of my feeds and used permanent redirects to tell your feed readers about the change, which I thought would make the transition seamless, and I would be able to bask in the glory of having done something right for a change...</p>

<p>Alas, this doesn't seem to be the case. Please update your feed readers. They should be able to automatically find the correct address if you visit <a href="http://reprocessed.org/">http://reprocessed.org/</a>. If not, then the new feed is at <a href="http://feeds.feedburner.com/reprocessed">http://feeds.feedburner.com/reprocessed</a>.</p>

<p>Thanks, and sorry for the hassle.</p>      </div>
    </summary>
    <link rel="alternate" type="text/html" href="http://reprocessed.org/blog/feeds_moved"/>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
<p>For those of you who subscribe to the feeds...</p>

<p>It looks like a lot of feed readers don't follow permanent redirects sent by servers, and I changed the location of my feeds and used permanent redirects to tell your feed readers about the change, which I thought would make the transition seamless, and I would be able to bask in the glory of having done something right for a change...</p>

<p>Alas, this doesn't seem to be the case. Please update your feed readers. They should be able to automatically find the correct address if you visit <a href="http://reprocessed.org/">http://reprocessed.org/</a>. If not, then the new feed is at <a href="http://feeds.feedburner.com/reprocessed">http://feeds.feedburner.com/reprocessed</a>.</p>

<p>Thanks, and sorry for the hassle.</p>      </div>
    </content>
    <published>2008-07-29T12:37:42+01:00</published>
    <updated>2008-07-29T12:37:42+01:00</updated>
  </entry>
</feed>
