Tuesday, October 28, 2008

ELC gets a makeover. Pew pew pew...

Alright--big disclaimer--ELC Technologies is a Ruby on Rails firm. I'm the founder and a proud team member. In fact, I couldn't be prouder than seeing the launch of our new team-focused website. It's from the brains of one of our ultra-talented interaction artists--Cary Dunn.

What's so cool? Besides being a Rails app that leverages our internal CORE codebase, the site adds some whimsy powered by a tongue-twister of cutting-edge technologies. From XMPP to Jabber to Pixel Bender. You never know who you might run into...

Sunday, October 26, 2008

[HOWTO]: Trac to Unfuddle migration...

We're testing a number of project management tools. One of the biggest hurdles in changing toolsets is data migration. For our needs, this means: milestones, tickets, wiki/notebook, SCM (SVN/GIT) and users.

Trac as we're using it includes SVN support. We'll be using GIT with Unfuddle.

Now the steps for migration:

  1. Firstly--you'll need git-svn and Ruby on your machine. If you need help getting here leave a specific comment below.
  2. On the input (migrating FROM) side, you'll need a copy of your trac directory (access to the sqlite3 db powering trac) and the credentials for the source SVN server.
  3. On the target (migrating TO) side, you'll need to have your unfuddle subdomain name, credentials and your git ssh keypair organized. Note: Don't create any Unfuddle projects by hand. One of our helper tools requires a clean slate.
  4. We move the trac info before the repository. The trac migration script is restrictive of being the first to create your project, so we're stuck in this order. Get unfuddle's trac2unfuddle.rb helper script. Crack it open and edit the fields for your target unfuddle project name (remember this should be the info for the project you want to create new, NOT an existing one). You'll also need to have the Trac sqlite file handy and fill in its location in trac2unfuddle.rb.
  5. UPDATE We've seen that non-URL friendly characters get URL-encoded on the filenames produced by Trac, but not consistently for the filenames stored in the the Trac db. To fix, we had to add these lines to the trac2unfuddle.rb file after the similar looking line handling spaces:
       path = path.gsub('*', '%2A') unless File.exists?(path)
       path = path.gsub('(', '%28') unless File.exists?(path)
       path = path.gsub(')', '%29') unless File.exists?(path)
    
  6. Run ruby trac2unfuddle.rb and grab a beer TUAW.com rutabaga.
  7. When you return, you'll see an error which should be relatively self-explanatory (you didn't have ruby-sqlite installed and friends) OR you'll now have a fully transitioned set of milestones, tasks, and notebook (the trac wiki). Log into Unfuddle and confirm.
  8. Before you complain--the wiki formatting totally, absolutely sucks. You lose most of the love you put into Trac--even the easy stuff. Somebody please hack a fix to the trac2unfuddle.rb script and send me link to it.
  9. Next up is the repository. You'll need a users.txt to map your svn users (user names) to git users (full names and emails). Read up on it here. You'll want to use the project you just created above to layer the repository onto the project management data in the same project. Log into Unfuddle and navigate to the project you've just created and create a new repository for it using their web interface. Then execute a command set like:
    mkdir svn-source-initial
    cd svn-source-initial
    git-svn init http://the-path-to-the-source-svn-repository/trunk/ --no-metadata
    git config svn.authorsfile users.txt
    git-svn fetch # Go get another tuber time. Entire SVN history coming to you.
    cd ..
    git clone svn-source-initial git-cloned-cleanly
    cd git-cloned-cleanly
    git remote add unfuddle git@subdomain.unfuddle.com:subdomain/projectname.git
    git config remote.unfuddle.push refs/heads/master:refs/heads/master
    git push unfuddle master
    
  10. You'll likely get errors at git-svn fetch because you forgot a username or two. Just add them to the users.txt and restart the fetch command. All that's left is logging into Unfuddle and checking the repository tab.
  11. Success! Congratulations--you have finished your migration. Set your SVN/Trac to readonly for a few days then put it up in S3 and on a DVD and savor your migration to the latest trendy toolsets.

[Fixed] ubuntu: sudo gem install sqlite3-ruby gives no rule to make target `ruby.h', needed by `sqlite3_api_wrap.o'

Fixed with sudo apt-get install libsqlite3-dev

> sudo apt-get install libsqlite3-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  sqlite3-doc
The following NEW packages will be installed:
  libsqlite3-dev
0 upgraded, 1 newly installed, 0 to remove and 41 not upgraded.
Need to get 237kB of archives.
After unpacking 639kB of additional disk space will be used.
Get:1 http://mirrors.kernel.org feisty/main libsqlite3-dev 3.3.13-0ubuntu1 [237kB]
Fetched 237kB in 1s (130kB/s)                       
Selecting previously deselected package libsqlite3-dev.
(Reading database ... 18363 files and directories currently installed.)
Unpacking libsqlite3-dev (from .../libsqlite3-dev_3.3.13-0ubuntu1_i386.deb) ...
Setting up libsqlite3-dev (3.3.13-0ubuntu1) ...

> sudo gem install sqlite3-ruby
Building native extensions.  This could take a while...
Successfully installed sqlite3-ruby-1.2.4
1 gem installed
Installing ri documentation for sqlite3-ruby-1.2.4...
Installing RDoc documentation for sqlite3-ruby-1.2.4...

Heroku Migration with ruport gem

Deploying an existing *and elderly* Rails app to heroku.

After adding the remote git location for our heroku app, we run git push -f heroku and get:

The authenticity of host 'heroku.com (75.101.137.180)' can't be established.
RSA key fingerprint is ...
Are you sure you want to continue connecting (yes/no)? yes 
Warning: Permanently added 'heroku.com,75.101.137.180' (RSA) to the list of known hosts.
Warning: Permanently added '10.252.42.127' (RSA) to the list of known hosts.
updating 'refs/heads/master'
  from d07a31b1559243f057f382775e1059cb4e32587c
  to   38f410a1e0d24386f96d4f33ae66d88eb541c311
 Also local refs/remotes/heroku/master
Generating pack...
Done counting 7248 objects.
Deltifying 7248 objects...
 100% (7248/7248) done
Writing 7248 objects...
 100% (7248/7248) done
Total 7248 (delta 3775), reused 7238 (delta 3771)
refs/heads/master: d07a31b1559243f057f382775e1059cb4e32587c -> 38f410a1e0d24386f96d4f33ae66d88eb541c311
HEAD is now at 38f410a... Readying for heroku.
Running migrations...
rake aborted!
no such file to load -- rcov/rcovtask
/mnt/home/userapps/38568/Rakefile:17
(See full trace by running task with --trace)
(in /mnt/home/userapps/38568)
App restarting...
######################################################################## 100.0%
 
Deployed to http://xxx.heroku.com

This issue is being cause by either our customer lib/tasks/coverage.rake task which modifies the default code selection done by RCOV. Or it's the vendor/rails/rails_rcov plugin. Going to Heroku.com => the project => the editor => Vendor/ => Gem/Plugin Manager, we see that rails_rcov is already installed. Oh well, let's remove the lib... doesn't help. And now the plugin... OK--we're on to the next issue (and adding this one to follow-up.)

refs/heads/master: 71ec54fd860c6608f3bad1367e41868753e37276 -> 7aebb29cfb4160624bd8d9a00adb8457dd35dcd1
HEAD is now at 7aebb29... Moved rcov task to see if heroku will run now.
Running migrations...
Your config/boot.rb is outdated: Run "rake rails:update".
(in /mnt/home/userapps/38568)

This time we get a notice about our aged Rails version scripts. These are updated with rake rails:update and we're on to the next err:

rake aborted!
no such file to load -- ruport

(See full trace by running task with --trace)

Again--check the Plugins/Gem section and... woah! The interface wants a URL, not the name of our gem. Looking at the Ruport gem website isn't immediately encouraging. Let's freeze the ruport gem into our project vendor directory. First edited config/environment.rb and made sure config.gem 'ruport' was existing and uncommented. Then running rake gems:unpack creates the ruport files in vendor/gems. Now another deploy and we're live!

Sunday, October 12, 2008

Heroku database.yml and no such file to load -- sqlite3

Heroku has a little gotcha when running Rails frozen into vendor/rails. See the thread for more details. The summary is, don't do it, it's not supported.

The slightly longer answer is that Heroku loads a customized version of Rails to support their special features. This means that you must reference a version they have installed and never, ever freeze rails (you know--in vendor/rails). Currently, Heroku support 2.0.x and Rails 2.1, but can't run other versions such as edge or Rails 2.1.1. :-)

The gotcha is that instead of an error saying you've frozen Rails--don't do it! you get a number of seemingly odd errors centered around database.yml. Now Heroku generally ignores your config/database.yml file completely and deploys internally on PostgreSQL. But, in this error state, Heroku appears to be trying to run your committed database.yml file (or complain if none exists). Moreover, referencing a mysql database gives you a no socket error. Below find the full text of the stack dump for future searchers.

MissingSourceFile in DashboardsController#index

no such file to load -- sqlite3
RAILS_ROOT: /mnt/home/userapps/xxx

Application Trace | Framework Trace | Full Trace
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:148:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:507:in `new_constants_in'
vendor/rails/activesupport/lib/active_support/dependencies.rb:148:in `require'
vendor/rails/activesupport/lib/active_support/core_ext/kernel/requires.rb:7:in `require_library_or_gem'
vendor/rails/activesupport/lib/active_support/core_ext/kernel/reporting.rb:11:in `silence_warnings'
vendor/rails/activesupport/lib/active_support/core_ext/kernel/requires.rb:5:in `require_library_or_gem'
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb:10:in `sqlite3_connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:215:in `send'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:215:in `new_connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:237:in `checkout_new_connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:180:in `checkout'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:176:in `loop'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:176:in `checkout'
/usr/lib/ruby/1.8/monitor.rb:238:in `synchronize'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:175:in `checkout'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:90:in `connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:321:in `retrieve_connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb:121:in `retrieve_connection'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb:113:in `connection'
vendor/rails/activerecord/lib/active_record/query_cache.rb:8:in `cache'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:12:in `perform_action'
vendor/rails/actionpack/lib/action_controller/base.rb:533:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:533:in `process_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:606:in `process_without_session_management_support'
vendor/rails/actionpack/lib/action_controller/session_management.rb:134:in `process'
vendor/rails/actionpack/lib/action_controller/base.rb:401:in `process'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:179:in `handle_request'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:107:in `dispatch_unlocked'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:120:in `dispatch'
/usr/lib/ruby/1.8/thread.rb:135:in `synchronize'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:119:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:129:in `dispatch_cgi'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:36:in `dispatch'
/usr/lib/ruby/gems/1.8/gems/thin-0.8.2/lib/rack/adapter/rails.rb:54:in `serve_rails'
/usr/lib/ruby/gems/1.8/gems/thin-0.8.2/lib/rack/adapter/rails.rb:74:in `call'
/home/heroku_rack/lib/toolbar.rb:16:in `call'
/usr/bin/thin:19:in `load'
/usr/bin/thin:19
This error occurred while loading the following files:
   sqlite3
Request

Parameters:

None
Show session dump

Response

Headers:

{"cookie"=>[],
 "Content-Type"=>"",
 "Cache-Control"=>"no-cache"}