Baldowl

my nest somewhere in GitHub's forest

Using Chef And Bundler Together

An old friend of mine recently needed to start using Bundler in a scenario managed by Chef via chef-solo.

Up to now, the gems in that setup had been managed semi-manually (a simple list of gems to be installed used by Chef’s gem_package resource) and the Chef’s standard deploy resource does not support using Bundler right out of the box. Fortunately, the hooks provided via the four callbacks are more than enough.

So, my homemade solution was to use the before_migrate callback:

Nesting a script resource inside the deploy resource forced me to “extract” some things from new_resource (the deploy resource) and store all in local variables, but at the end of the day the code is clear and tidy, the intent is evident and everything works perfectly.

Pinging Google With A Service Hook

Recently I added a sitemap to this site; Jekyll facilitated the creation act, so what was left to do? Pinging Google, just to say a name, automatically.

First of all, I thought about using something like the post-merge Git hook, but, assuming it worked, it would force a strict workflow (always work in a topic branch and merge on master only when you have a working connection). Another option could be to wrap everything in a micro-script to call manually after receiving Github’s notification of a successful rebuild. Then a “crazy” idea started to elbow its way toward my cortex… but first, a bit of background (for myself, actually, so that I can remember why I did things in a given way).

Let’s take Google’s instructions:

  • identify sitemap’s URL (say, http://www.example.com/sitemap.xml);
  • escape it (http%3A%2F%2Fwww.example.com%2Fsitemap.xml);
  • use it to build the complete ping URL (http://www.google.com/webmasters/tools/ping?sitemap=http%3A%2F%2Fwww.example.com%2Fsitemap.xml);
  • then “ping” that last URL with wget or curl; if you get a 200 response, then you’re done.

N.B.: A simple use of wget or curl will generate a GET request.

Let’s turn to Github. In the administrative section of every repository there’s a long list of service hooks; the official Github’s guide is The Source of information about them, but let me note here that service hooks are POST requests with a given payload.

So, GET vs. POST? Can we POST to Google to report an updated sitemap? Maybe… if Google does not adhere to the REST credo.

As of today, in response to the preceding command Google returns a 200 response, i.e., it seems we can “ping” Google with a POST request and even extra data. Will it hold? Time will tell.

Back again to Github: the general post-receive service hook is the way to go because (at least at the moment) there’s no more specific hook. Let’s add the complete URL (that one with the escaped sitemap URL at the end) to the list and then test it: if it works we’re done.

If everything holds, when we push to the on-line repository Github will notify Google about the updated sitemap and rebuild the site. Maybe, occasionally, Github’s queue could be a bit clogged and Google could have some spare resources to re-read the sitemap before the refresh… in that case a manual (!) “ping” will fix the problem.

Subversion Must Live

This is partially a rant; you have been warned!

I do not hate ignorance: there are simply too many things in the world to not be ignorant of something. I cannot stand ignorance and pertinaciousness together.

It happend to me to work with people who sold themself like stellar programmers, yet they had never used a VCS. Being told to study the available documentation about a given VCS, they started to work on the assigned projects right away, trusting in their ego and the help of their preferred IDE, only to fail miserably after having committed log and temporary files, assets generated and maipulated at runtime by the application, their personal IDE’s project settings and having reached a point where the VCS itself could not tell apart a working directory from the recycle bin and the repository did not work properly. I have never been able to reproduce that mess and still do not know how they could achive those “wonderful” results. Being tasked with fixing corrupted working directories and wrecked repositories is not really funny, but it is definitely too much when you know everything could have been avoided just by spending a couple of hours studying some very basic docs.

The given VCS was Subversion. Many years ago, switching from CVS to Subversion I felt at ease in a very short time and I still think Subversion is a simple but good VCS. Then came Git.

My first contact with Git was a bit more traumatic: I do not remember what I started reading, but I thought “What the heck is all this?!?”. I threw everything away but returned to it after a while, only to be shocked again; the story repeated itself a couple of time before I saw the “light”. Now I use Git everywhere for everything and also installed and maitained an instance of Gitosis to watch over a couple of Git repositories at work for a while; then I realized that if Subversion had not been understood well enough to use it in a basic, straitforward way, Git would have caused way too many troubles.

Others have written about why Subversion should stay alive, but I do not care too much about things like enterprise penetration; Git and the other DVCSs are so flexible, provide sofisticated ways to handle and rearrange source code and add the complexity of decentralization on top of it. My experience tells me some people just cannot start to use Git as their first VCS (and some should not use it at all), but I do not think it to be Git’s fault: when people do not want to learn, you cannot give them enough rope to hang themself without seeing them strung up after a short while.

For this single, simple, selfish reason, I say that Subversion must live and prosper.

Automation Everywhere

Summertime has hit too heavily for my taste and everything else beyond work is coming to a grinding halt. Some nights ago, unable to fall asleep, my mind started wandering, so I found myself thinking about automation and some of the things I automated over time. Mechanical gears

Years ago, when I bought my first laptop, I set up the only network adapter, an Ethernet card, with static IP address: I was in charge of administering the only network my laptop could join, so that strict approach did not seem too cumbersome. Some years later I switched to DHCP even for my old laptop and now, with Wi-Fi, Ethernet, Bluetooth and FireWire I really cannot think about going back.

When I was younger, I devised a “clever” naming scheme for the network equipments, so I always knew what a given machine or printer should be called and with my then favorite printing system I could manually set up a local printing queue in no time. Then I switched to CUPS and later threw in zero-conf; now I cannot stand vendors that try to shove down your throat network printers without even a minimal implementation of zero-conf or which cannot use PPDs.

When I was younger and bolder I wrote my own backup solution for my home computer and my laptop; it was a bit awkward to run and the prospective restore would have been tricky. Then I switched to Bacula, which I still happily use at work. When I bought my current MacBook Pro, I attached an external hard disc, let Time Machine do its job and forgot about everything else.

I used to spend a lot of time browsing the Net, mainly reading Slashdot, Dilbert, User Friendly and so on. A summer I was disconnected for a rather long period and so lost track of many, many things. Before that accident, I was not a fan of feeds and aggregators, but now I rely on a newsreader and cannot think about turning back.

Until recently, I always performed server provisioning by hand; then I decided to help a friend to migrate a small/medium size structure to a cloud computing environment and I had to change my mind… now, at my daily work, where I cannot change everything right away, I sorely miss the automation achieved using Chef.

We are in a service economy, computer-wise at least, where almost anything can be purchased as a disposable service, without too much immediate funding, so I think there will be many more things to be automated but I cannot easily foresee what will be the next one (otherwise I’d start a company of my own :-D).

Using Bundler08 Instead Of Standaloneify

These days I need something to do in the evening instead of watching bad football/soccer matches (Germany played a good one…), so I started to play more seriously with RubyCocoa.

While my mind was wandering around, partially distracted by noises produced by TV in the living room, a question arose: if an application written with RubyCocoa uses one or more libraries distributed as gems, what can I do to ensure that the application can be used on a prospective user’s system without hassles?

Obviously, the libraries must be “vendored” in some way, so what I needed was a robust solution to help me storing the gems inside the application, managing the load paths correctly and possibly cutting off access to the system’s libraries (more on this below). A possibility is the standaloneify.rb script, buried inside the RubyCocoa’s directory, but I got an error trying to use it to “bundle” ActiveSupport

Enters Bundler08.

This gem is a “spin-off” of Bundler, the gem/tool developed by the Ruby on Rails core team to manage the dependencies of a Ruby on Rails application (and more generally of whatever you want). Around version 0.9, the tool was modified to store the managed dependencies in a “repository” inside the user’s home directory by default and to generate an environment.rb file which uses absolute paths to point to the libraries, but it’s not always been this way…

Bundler08 is a version of Bundler which still stores libraries inside the “root” directory of your project and the generated environment.rb file uses relative paths to point to the libraries, so that the net result is a relocatable application.

So, here what I did to add a gem to a toy app using Bundler08:

  1. installed the bundler08 gem in the usual way;
  2. moved to the app’s “root” directory and generated a Gemfile running gem bundle –init (the content is a simple introduction to Bundler08);
  3. replaced the Gemfile’s content with the following lines:
  4. ran gem bundle, which downloaded the listed gem and installed it into vendor;
  5. added the following lines at the beginning of the standard rb_main.rb:
  6. added both Gemfile (normal way) and vendor (as a directory reference) to the Xcode project;
  7. added both Gemfile and vendor to the Git repository (I think there’s no need to ignore some of vendor’s contents).

What I ended up with? A toy app which knew how to pluralize words, among other funny things, which did not use any of my system’s gems and could be moved around without problems.

I disabled explicitly the system’s gems because what’s on a user’s system cannot be safely predicted, even if it’s the content of /System (I, for example, have upgraded most of the system’s gems and removed the old versions).

A good evening indeed.

Keep-alive vs. Mongrel; saved by Thin

Just yesterday I had to fight a battle reminiscent of Don Quixote…

To keep it technical: a very long running request in a Ruby on Rails application, served by the dynamic duo Apache HTTPd and Mongrel, kept returning an error message to the haples users. Scouring the net for that particular error message generated by the web server led me to a very old Apache bug report, filled up with accounts of what seemed to be the same behaviour I was experiencing. Buried under tens of messages there was a workaround, namely to set a couple of environment variables via SetEnv directive, which did not work (the classical proof of Murphy’s Law).

Time was ticking away and windmills were winning the day…

The problem really seemed to be related to the interaction of Keep-Alive, mod_proxy and an unresponsive Mongrel, too busy with the very long running request… Keep-Alive, where did I hear/read about it? Eureka! Thin to the rescue!

Testing this solution was just a matter of stopping the cluster of Mongrels and starting a couple of Thin instances. Voilà! Everything was working.

What was left to do? Oh, yeah, replace Mongrel in the Capistrano’s recipes too. Nothing much to do here: remove the Mongrel cluster’s recipe and add these few lines:

To be sure that a potential reboot will not leave the web server without its new companions, an “installation” of Thin and an update of Debian’s rc.d was in order.

Simple, short, fast.

Granted, this is just another workaround and the real, right solution is to move that very long running request to a background job; that’s why it’s been put on top of the to-do list.

Setting up Git for Xcode

Even if I don’t particularly like Objective-C, given the recent release of Cocoa Programming I’ve started to play a bit with Xcode; after the big upgrade to Xcode 3.2.2 and a huge backup I created a new project and put together a really nasty interface, crammed with controls, just to “taste” Interface Builder.

But that’s not the point of this story.

After playing around for a while with the many windows, I thought about SCM: what do “pros” do? They probably use what’s already there… As Steinberg wrote, nobody likes whiners, so I’m not going to complain about Xcode lacking support for Git or the fact that it seems to constantly rewrite the project’s setting files even if nothing changed; yet, I prefer not to use CVS or Subversion and Terminal is always the first window that pops up on my desktop, so that’s not a problem.

The real issue is: what should be left out and what must be included in a repository, irrespective of the used VCS? Well, Cocoa Programming is silent on this side and the Apple’s official documentation does not seem to include a simple list “In/Out”, but after perusing documents about project structure and source code management with Xcode, I think to have a basic, starting list of things to ignore, so here it is, according to the Git parlance:

Apple writes that you should include the .pbxuser files because they store user settings; I’m not so sure it be a good idea or not, but I’ve just started to play with Xcode :-)

Given that Apple itself writes that there’s no value in comparing and merging XML files, it’s better to tweak Git (I’m so bold as to include in the following list also the XML Nib files):

I know, there are other lists circulating on the net; what’s above it’s just my “two cents”, nothing more.