imedo Development Blog

there is no charge for awesomeness

Author Archive

CruiseControl.rb and changing SVN paths

without comments

When you move around some code in your SVN repository or like change the repository URL, CC.rb will start to complain because it isn’t able to find your code where it used to be. The message will be something like this:

svn: Cannot replace a directory from within

To fix this you can use

svn switch file:///this/is/the/path/to/my/new/svn/repo

But CC.rb will still complain and won’t build your project. In order to fix this, you have to commit once and CC.rb will pick up the changes and start building your project again.

We had this exact problem recently and it took some time to figure out how to solve it. So maybe this post will save someone some time.

Popularity: 1% [?]

Written by hvolkmer

August 28th, 2008 at 9:38 am

Es ist immer der Gärtner

without comments

Neulich beim Coden:

Hendrik: Ich hab da ein Problem mit XYZ… Hast ‘ne Idee, woran es liegen könnte?

Thomas: Lies den Sourcecode! Ich mache es auch. Ich lese gerade ActiveRecord::Base

Hendrik: Und? Ist es spannend?

Thomas: Ja. Ich glaube es war der Gärtner.

Popularity: 1% [?]

Written by hvolkmer

August 27th, 2008 at 2:58 pm

Posted in Misc

Tagged with , ,

Overriding rake tasks and db:test:prepare strangeness

without comments

Some time ago our CC.rb build started to fail with errors like this:

Mysql::Error: Can't create table './cc_test/#sql-8e7_5bab.frm' (errno: 150): ALTER TABLE questions ADD CONSTRAINT questions_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE

We’re using the foreign key migrations plugin which automatically generates foreign keys for mysq. It works fine but somehow the db:test:prepare rake task started to fail – everytime at a different key and only on the build server.

After hours of hunting down the problem I finally gave up and did what you always can do if you can’t solve a problem: cheat. So I just created a new db:test:prepare task which calls the mysql commands and basically does the same as the rake task. It’s not as portable as the default one, of course, but it has one property that the default one had lost: It works.

Rake doesn’t allow redefining task by default. So to override a rake task you have to delete the task and then define the new one. I opted for the manual remove task and redefine option.

Here’s my task in case anyone experiences similar problems:

We call rake using “rake -I /path/to/override.rb” in our build scripts and it works fine now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Rake::TaskManager.class_eval do
  def remove_task(task_name)
    @tasks.delete(task_name.to_s)
  end
end

def remove_task(task_name)
  Rake.application.remove_task(task_name)
end

namespace :db do
  namespace :test do
    remove_task :"db:test:prepare"
    desc 'prepares the db - mysql style'
    task :prepare do
    
      require 'yaml'

      config = YAML::load(File.read('config/database.yml'))

      devdb = config['development']['database']
      devpass = config['development']['password']
      devuser = config['development']['username']
      testdb = config['test']['database']
      testpass = config['test']['password']
      testuser = config['test']['username']

      puts "dumping development schema"
      puts %x{mysqldump -u #{devuser} --password=#{devpass} -d #{devdb} > dev.sql}
      puts "dropping test db"
      puts %x{mysqladmin -u #{testuser} --password=#{testpass} -f drop #{testdb}}
      puts "recreating testdb"
      puts %x{mysqladmin -u #{testuser} --password=#{testpass} create #{testdb}}
      puts "loading development schema into test db"
      puts %x{mysql -u #{testuser} --password=#{testpass} #{testdb} < dev.sql}

    end
  end
end

Popularity: 1% [?]

Written by hvolkmer

August 18th, 2008 at 12:58 pm

Posted in Deployment

Tagged with , , ,

Stay on target

without comments

The guys at pivotallabs post very intersting and useful bits of information in their daily standup posts. We actually were able to find a problem faster thanks to their current daily standup post about the target method

If you have a “target” method on your model, things will get a bit weird when you try to access this method through an association. Since associations have their own “target” method, you actually need to call assocation.target.target, or probably better, don’t create methods called “target”.

We supected something like that but haven’t tracked it down yet. Thank you :)

Popularity: 1% [?]

Written by hvolkmer

August 11th, 2008 at 5:40 pm

Posted in Development

Tagged with ,

Limiting mongrel to one request at a time with haproxy

without comments

I don’t know why we didn’t try that earlier, but haproxy is a far better proxy solution then all the others we tried. Ok, we didn’t try that many but the most common ones on the Rails deployment landscape:

So why is haproxy so much better? It is better because it actually can limit the requests per mongrel to one at a time. This important because otherwise you get behavour like this: One mongrel has a long running request and through round-robin, gets another request while other mongrels are idleing. Also mongrels with a request queue bigger then one start to eat memory like hell.

The same thing is possible with Apache’s mod_proxy_balancer. We tried and failed to get it working. And it seems as if we are not alone with that problem

The plain nginx balancer has the same problem. This is where the fair proxy module comes in. It’s supposed to send requests only to idleing mongrels. But we had the same “mongrels with many requests while others are ideling” problem again.

We finally tried haproxy which is in use for Rails deployments for quite some time but got a lot of buzz recently. Ilya Grigorik wrote a nice article about load balancing QoS with haproxy and Alexander Staubo posted a performance comparison of nginx and haproxy which got the attention of William Tarreau (the haproxy author). They found some haproxy bugs which got fixed and resulted in an even better performance. Details can be found in the second comparison of haproxy and nginx

So we are quite happy with haproxy at the moment and hope it stays this way.

Popularity: 1% [?]

Written by hvolkmer

August 8th, 2008 at 9:58 am

Posted in Deployment

Tagged with , , , ,

Strange web requests

with one comment

Ever seen requests for files like this in your webserver logfile?

/_vti_bin/owssvr.dll
/MSOffice/cltreq.asp

According to this forum post it’s some kind of “Microsoft Office gone wild” thing:

“This file is part of Microsoft Office Server Extensions (OSE) and your host has installed them on your server. This file gets accessed when someone visiting your site has Microsoft Office and Internet Explorer installed and has enabled the “Discuss” toolbar in his/her browser. When the toolbar is enabled, the browser will automatically query the file when visiting your site to determine if the OSE extensions are installed.”

It’s almost as annoying as Firefox’s favicon requests.

Popularity: 1% [?]

Written by hvolkmer

July 10th, 2008 at 3:17 pm

Posted in Deployment

Tagged with ,

dry_plugin_test_helper gem released

without comments

For the impatient

What is it?

Imagine you have some fancy acts_as_something plugin and, of course, you want to test it. How do you do it? In the Rails app you are developing it for? This could lead to longer environment load times and this is hardly testing in isolation. Creating a rails app just for testing the plugin? That’s better but creating a rails app for every new plugin – that’s so un-DRY! And you cannot test the plugin on its own. You could ship the bare rails app with your plugin but again: not DRY and lots of code you don’t really need for your plugin.

dry_plugin_test_helper to the rescue!

What it does

The gem sets up the test environment which means you have a stub rails app with your plugin and the following models:

  • Article: belongs_to :author, has_many :comments
  • Author: has_many :articles
  • Comment: belongs_to :articles, belongs_to :user
  • User: has_many :comments

The models will be added to a sqlite in memory database for fast testing.

To use the gem enter the following lines in your test_helper.rb or abstract_unit.rb (or however you may call it):

1
2
3
4
require 'rubygems'
require 'dry_plugin_test_helper'

PluginTestEnvironment.initialize_environment(File.dirname(__FILE__))

You can add your own test models using a migration in your test directory like
this:

1
2
3
4
5
6
7
8
 PluginTestEnvironment::Migration.setup do 

   create_table "animals", :force => true do |t|
     t.column "name", :string
     t.column "age",  :integer
   end

 end

If you don’t want the standard models you can initialize the test environment
like this:


PluginTestEnvironment.initialize_environment(File.dirname(__FILE__), :use_standard_migration => false)

How it works

The gem contains a stripped down rails directory structure and boots up this rails environment and then adds the plugin under test to this environment. It uses the sqlite3 in memory db for faster testing.

Caveats

You can really only test the plugin that you are testing. If your plugin has some dependencies to other plugins (why should it?) you cannot test it using this gem out of he box. You’d have to mess with the load path yourself (I haven’t tried it)

Todo

  • support for RSpec and other testing frameworks (might already work – haven’t tried it)
  • Automatic Rails version discovery
  • Clean up / strip down rails env to bare minimum (It’s not completly clean yet)

Dependencies

The dry_plugin_test_helper gem depends on Rails and sqlite3-ruby

Getting it, License and Patches

Get the complete source code through Github. License is MIT. That means that you can do whatever you want with the software, as long as the copyright statement stays intact. Please be a kind open source citizen, and give back your patches and extensions. Just fork the code on Github, and after you’re done, send us a pull request. Thanks for your help!

Popularity: 1% [?]

Written by hvolkmer

July 7th, 2008 at 7:13 pm

Posted in Open Source Releases

Tagged with , ,

Arbeiten im imedo Entwicklungsteam

without comments

Although we blog in English to reach a larger audience we speak German at work (most of the time). As the following text is intended for people who are interested in working with us, this page is in German.

Wir bieten Dir eine Arbeitsumgebung, in der die Arbeit jeden Tag auf’s Neue Spaß macht:

  • Junges, energisches, agiles Team
  • Keine Krawattenpflicht
  • Helles Büro mit tollem Ausblick
  • Auch wenn unsere Plattform mit Gesundheit ein ernstes Thema behandelt, darf man bei der Arbeit dennoch Spaß haben und es muss nicht todernst zugehen
  • Jeder Entwickler bekommt die beste Hardware und große LCD-Monitore, damit hohe Produktivität leicht fällt
  • Da wir selbst viel Open Source Software nutzen, releasen wir Teile unserer Software, die für andere sinnvoll sind ebenfalls als Open Source
  • Wir entwickeln agil: Dinge wie Continuous Integration, Scrum, TDD gehören zur täglichen Arbeit
  • Wir entwickeln mit Ruby und Rails, sowie Subversion und git
  • Wir arbeiten mit allen imedo Mitarbeitern eng zusammen und nutzen dafür moderne Tools, die die Arbeit erleichtern, wie z.B. unser Wiki oder unser Ticketsystem

Wir suchen jederzeit interessierte Entwickler, auch wenn gerade keine Jobausschreibung aktiv ist. Für Aktuelle Jobausschreibungen bitte auf unserer Jobseite nachschauen oder direkt an jobs [at] imedo.de bewerben.

Popularity: 1% [?]

Written by hvolkmer

July 7th, 2008 at 2:42 pm

Posted in Uncategorized

Tagged with , , ,

Useful process info for mongrel and thin

without comments

Ilya Grigorik wrote about mongrel proctitle plugin which is indeed very useful. We discovered the mongrel plugin about two months ago and use it in production without problems. It has helped us to debug several problems.

We run more than one Rails app per server and so it hurts to install the plugin for every app again (oh that painful DRY nerve ;-) )

The solution of course is to just create a gem and install it. Luckily there is already such a thing: rtomayko’s mongrel proctitle github repository

There’s also a proctitle plugin (actually a rackup file) for thin: thin proctitle git repository – no gem yet, though.

Popularity: 1% [?]

Written by hvolkmer

June 30th, 2008 at 3:23 pm

Posted in Deployment

Tagged with , ,

WordPress Deployment with Capistrano 2 and git

with 3 comments

I know: PHP deployment is really easy. You just copy the files to the server and you’re good to go. Why bother with something like Capistrano for WordPress deployment? Well, we’re using Rails and we’re spoiled children, and because we can. That’s why. Ok, to be honest: I don’t like the copy/checkout the files and upload them deployment.

There already is a good tutorial for WordPress deployment with capistrano but it’s for Capistrano 1 and SVN. I’ll show you the neccessary modifications to use cap 2 and git. It’s easy, really.

Ok, then let’s go:

Local directory structure:

base_dir
 - .git (Git Repository)
 - Capfile
 - config
    - deploy.rb
 - public
   - *.php (etc...)

Server side Capistrano structure:

app-dir
  - current => link to releases/2008....
  - shared
    - wp-config.php
    - uploads (wp-uploads-folder)
  - releases
    - 2008.....
       - public/ (wordpress goes here)

So you have to configure your Apache (or lighty or whatever) to use app-dir/current/public as Docroot.

My deploy.rb file looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
set :application, "mywordpress-blog"

set :deploy_to, "/var/www/apps/#{application}"
set :deploy_via,    :copy
set :copy_strategy, :checkout
set :user,          'deploy'
set :use_sudo, false
set :keep_releases, 3

set :scm, :git
set :repository, "/Users/hvolkmer/Projects/mywordpress-blog/"
set :branch, "master"

role :app, "blog.example.com"
role :web, "blog.example.com"
role :db,  "blog.example.com", :primary => true

desc "This is here to overide the original :restart"
deploy.task :restart, :roles => :app do
  # do nothing but overide the default
end

desc 'Link to upload folder, cache and config'
task :after_symlink do
  run "cp #{deploy_to}/#{shared_dir}/wp-config.php #{deploy_to}/#{current_dir}/public/wp-config.php"
  run "ln -nfs #{deploy_to}/#{shared_dir}/uploads/ #{deploy_to}/#{current_dir}/public/wp-content/uploads"
end

Notice that I symlink the uploads folder but copy the wp-config.php file. That’s ugly but neccessary, because php resolves the basepath of the target file and not the symlink when it tries to include other files. (So it would end up trying to include files from the shared directory). I’m told that in the latest PHP that bevaiour is fixed.

Using the deploy_via “copy” model doesn’t require to install git on the target system.

I was thinking about using vlad the deployer for that task because it is supposed to be simpler and leaner and all that. But as it is currently lacking the copy-deployment model and required git on the server side, I just stayed with capistrano which turned out to be the simpler solution for for us in this case.

So always remember: Pick the right tool (for you and) for the job and be happy with it.

Popularity: 20% [?]

Written by hvolkmer

June 23rd, 2008 at 6:51 am

Posted in Deployment

Tagged with , , ,