Redline Software Inc. - Winnipeg's Leader in Ruby on Rails Development

Skittles and Bowling Now in Redzone

I thought it was just candy, but it turns out Skittles is also a sport. You can now create Skittles leagues in Redzone, and because Bowling is a descendent of it we added that as well.

Got a sport that you need league software for? Let us know!

Dodgeball Added to Redzone

We’ve added Dodgeball support to Redzone today.

There are tons of variations of Dodgeball, so we tried to keep it simple with the statistics. If you have a variation that you’d like us to support drop us a line and let us know!

Kickball (Soccer Baseball) Support

Redzone Leagues has recently added kickball as a supported sport. The stats currently configured are basically the same as those used for softball, but if you don’t want to use any of them, you can use the “Statistics Management” feature and turn them all off or select just the ones you want to use.

Using God to Automatically Monitor Mongrels

Here is a sample god configuration file for monitoring all the mongrels on your system. This script assumes that your mongrel configs are all in /etc/mongrel_cluster and that your pid_file attribute in your config files point to an absolute path. I lifted the majority of this script from the example in thin. (Thin is awesome FYI)

I have a few mongrel config files in /etc/mongrel_cluster that look similar to:

1
2
3
4
5
6
7
8
9
---
user: deploy
group: www-data
cwd: /var/www/apps/sampleapp/current
port: "8200"
environment: production
address: 127.0.0.1
pid_file: /var/www/apps/sampleapp/shared/pids/mongrel.pid
servers: 2

When I want to deploy another application on the same machine, I add the config file there and then restart god. It will then begin automatically monitoring the new application.

My /etc/god.conf:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
require 'yaml'
config_path = "/etc/mongrel_cluster"

Dir[config_path + "/*.yml"].each do |file|
  config = YAML.load_file(file)
  num_servers = config["servers"] ||= 1

  (0..num_servers-1).each do |i|
    number = config['port'].to_i + i

    God.watch do |w|
      w.group = "mongrel-" + File.basename(file, ".yml")
      w.name = w.group + "-#{number}"
      w.interval = 30.seconds

      w.uid = config["user"]
      w.gid = config["group"]

      w.start = "mongrel_rails cluster::start -C #{file} --only #{number}"
      w.start_grace = 10.seconds
      w.stop = "mongrel_rails cluster::stop -C #{file} --only #{number}"
      w.stop_grace = 10.seconds
      w.restart = "mongrel_rails cluster::restart -C #{file} --only #{number}"

      # assemble the pid file, pid files look like mongrel.8000.pid, mongrel.8001.pid etc
      pid_path = config["pid_file"]
      ext = File.extname(pid_path)
      w.pid_file = pid_path.gsub(/#{ext}$/, ".#{number}#{ext}")
      w.behavior(:clean_pid_file)

      w.start_if do |start|
        start.condition(:process_running) do |c|
          c.interval = 5.seconds
          c.running = false
          c.notify = 'team'
        end
      end

      w.restart_if do |restart|
        restart.condition(:memory_usage) do |c|
          c.above = 150.megabytes
          c.times = [3, 5] # 3 out of 5 intervals
          c.notify = 'team'
        end

        restart.condition(:cpu_usage) do |c|
          c.above = 50.percent
          c.times = 5
          c.notify = 'team'
        end
      end

      # lifecycle
      w.lifecycle do |on|
        on.condition(:flapping) do |c|
          c.to_state = [:start, :restart]
          c.times = 5
          c.within = 5.minute
          c.transition = :unmonitored
          c.retry_in = 10.minutes
          c.retry_times = 5
          c.retry_within = 2.hours
          c.notify = 'team'
        end
      end
    end

  end
end

God::Contacts::Email.message_settings = {
  :from => 'god@example.com'
}

God::Contacts::Email.server_settings = {
  :address => "localhost",
  :port => 25,
  :domain => "example.com"
}

God.contact(:email) do |c|
  c.name = 'team'
  c.email = 'team@example.com'
end

One thing that the god install doesn’t do is create a nice init.d script, but you can find one here which I found from this post about using God.

The God website has an example with explanations of what each of those sections mean. Check it out.

Looking for Mephisto 0.8?

I was too, so I popped into the #mephisto channel on freenode and technoweenie set me straight. The subversion trunk in mephisto will be the latest stable release (in this case 0.8) of his github repo.

But for an easy way to just download the 0.8 release, go here and then click on download and you’ll get a nice shiny tarball.

Thanks to the Mepisto team for making a great blogging app!

Ultimate (Frisbee) Support

Redzone Leagues has recently added Ultimate as a supported sport. Currently by default, no stats are tracked, but if you have an Ultimate league that does track some stats, let us know and we can add those to the site for you to use.

Statistics Management Feature

We’ve recently added the ability to customize the stats you use in your league.

Not every league tracks the same stats, so instead of cluttering up the interface with stats your league doesn’t use, you can now remove them. Or if you would like to add some additional stats to the defaults provided, you can add stats from any of the predefined stats that are available.

To add or remove stats, click on the “Manage Statistics” link from the admin dashboard.

If there are some stats missing that you would like to add to your league, simply contact us via the support link and we’ll do our best to add them.

Converting Subversion Repositories to Git

Remote setup

I’m going to keep this post mostly about converting your SVN repository into a Git one. As far as setting up your remote server goes, we can get to that in another article. I basically stick with a simple setup. Create a Git user, set the shell to git-shell and use Git via SSH. You’ll likely want to play around with Git first before worrying about converting old SVN repositories into it.

Local setup

I create myself a file called gitauthors which is just a text file which maps SVN user names to Git user names. For example my gitauthors file looks like:

1
2
marc = Marc Jeanson <marc@redlinesoftware.com>
andrew = Andrew Kaspick <andrew@redlinesoftware.com>

In this example, “marc” and “andrew” were the SVN users and the email address style is the Git user names. We’ll be using this mapping when we convert the SVN repo into Git so that we can keep the history of who checked in what.

git-svnimport

Lets create the new local Git repository. In this example replace projname with your project’s name and replace https://your-repo-host.com/projname with your Subversion url (note this can take a while if your repo has lots of revisions):

1
git-svnimport -C projname -r -v -A authors https://your-repo-host.com/projname

Bare essentials

Now you’ll have a local Git repository called projname. For your “central” repository you won’t want to have a local checkout in that repo so I do the following:

1
git clone --bare projname projname.git

The projname.git will be the repository that you’ll want to upload to your remote server. The —bare option here creates a repository without a local checkout. You might want to look into the —shared option depending on how you setup your remote server and permissions. After uploading it you can nuke the projname.git repository on your local machine.

Hooking up the remote

Since your projname directory is still there and has a nice working version already in it, you can edit the .git/config file and append the following:

1
2
3
4
5
6
[remote "origin"]
  url = git@your-git-remote-server:/home/git/projname.git
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
  remote = origin
  merge = refs/heads/master

I’m assuming that your repository is in the /home/git directory on your server. You’ll want to change that to wherever you put your repositories.

But my git-svn and git-svnimport are busted!

You might experience some errors when using git-svn. Usually this is caused by not having the correct Perl bindings needed for the git-svn hookup. If you’re on a Mac and you installed Git using Macports, try doing this:

1
2
sudo port deactivate git-core
sudo port install git-core +svn

If you’re on another platform, try running cpan and installing the Perl libraries that you need. For example if you have an error like “Can’t locate Blah.pm in @INC” then you need to install the Blah Perl library.

Processing Email With OmniFocus Screencast

Integrating OmniFocus and Mail.app makes a much better email experience. By using smart folders along with OmniFocus’s “clippings” I can accomplish Inbox Zero most of the time.

I’ve shared my email work flow with a few people already and they also seem to like it, so I decided to make a short screencast demoing what I do. Like I mention in the screencast, most of my workflow is totally ripped off from people like Merlin Mann so check out that site for more email ninja goodness.

DOWNLOAD SCREENCAST (4.8M, 4:16)

Here’s some links related to the screencast:
[OmniFocus]
[Mail.app]
[iGTD]
[MailTags]

Reverse DNS and Email

So you’ve setup your SPF records and your web app isn’t sending emails that contain any of the following words “FREE, enlarge, penis” etc, but email still isn’t reaching its destination?

RTFL! (where L is logs in this case)

/var/log/mail.log (or wherever your logs might be) might show something like:

1
2
3
4
5
Feb  4 06:42:49 yourhost postfix/smtp[5381]: 738F212E41A9: host mailin-04.mx.aol.com[64.12.138.88] said: 421-:  (DNS:NR)  http://postmaster.info.aol.com/errors/421dnsnr.html 421 SERVIC
E NOT AVAILABLE (in reply to end of DATA command)
Feb  4 06:42:49 yourhost postfix/smtp[5381]: connect to mailin-02.mx.aol.com[64.12.137.168]: server dropped connection without sending the initial SMTP greeting (port 25)
Feb  4 06:42:51 yourhost postfix/smtp[5381]: 738F212E41A9: to=<somerandomdude2939338829@aol.com>, relay=mailin-04.mx.aol.com[64.12.138.57], delay=1780, status=deferred (host mailin-04.mx.aol.com
[64.12.138.57] said: 421-:  (DNS:NR)  http://postmaster.info.aol.com/errors/421dnsnr.html 421 SERVICE NOT AVAILABLE (in reply to end of DATA command))

So you load up http://postmaster.info.aol.com/info/rdns.html and find out that your server is missing a reverse DNS entry. Great now what?

Well if you don’t know what a reverse DNS entry is, it’s really not a hard concept. On a normal DNS lookup you’re usually asking for an IP address for a given domain name. A reverse entry is asking what domain is assigned to a particular IP address. This is useful in the battle against spammers.

First lets use dig to see if you really don’t have a reverse entry. Let’s pretend your email server is example.com and your IP address for that mail server is 208.77.188.166.

1
dig -x example.com +short

The -x in the dig command will reverse that domain for you and the +short will cut straight to the answer for you. You should hopefully see something like:

1
2
dig -x 208.77.188.166 +short
  www.example.com.

Give it a try with your IP, and if you get nothing back then you have no reverse pointer. To get one, you’ll likely have to request that your ISP add the record for you. If you’re on a VPS or something similar, put in a request to their support team to do this. Many of these companies have a form you can fill out online to do so.

Once they add it, give the above command a try again and you should be 1 step closer to being able to send legitimate email. Unfortunately there’s always more steps, but remember the logs are your friends…hopefully not your only friends though.