Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Andrew Bruce

Fighting test pollution with an RSpec custom ordering strategy

Andrew Bruce
Thursday, April 25, 2013

Test pollution manifests itself as seemingly false negatives or false positives in a test suite. It occurs when some shared state is unintentionally modified, or unintentionally read and used in a test.

When test pollution builds up, it can mean that a project’s build fails unpredictably, which can stop a whole team from shipping code regularly. This is an expensive way to not build software.
Continue reading →

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

What happened to stdout on CI?

Mark Rushakoff
Thursday, February 14, 2013

We were struggling for a bit yesterday trying to figure out why the few puts statements in our tests weren’t being displayed in Jenkins’ console output.

It turns out the ci_reporter gem that we were using (so that Jenkins could parse our test results) swallows stdout and stderr by default — unless you set the CI_CAPTURE environment variable to the string "off", like it tells you to do in the readme.

That was a confusing default setting. Since my pair and I weren’t involved in setting up Jenkins, and we didn’t install the ci_reporter gem, we assumed something was misconfigured in Jenkins before we started digging through the code.

Hopefully this saves someone else some time!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

Using Jasmine on tddium

Robbie Clutton
Tuesday, November 27, 2012

With thanks to Ben we discovered a nice way to get Jasmine tests to work on Tddium today. We had a number of issues with the jasmine-headless-webkit dependency Tddium said we had to use. Issues around requiring a file that required erb to compile; not finding the source files; getting to work in the browser but not the command line and maybe a few others.

Ben pointed out some undocumented configuration for Tddium which outlined ‘custom’ build steps wherein you could call the jasmine:ci rake task. This cleared everything up. Although I’m not sure how as Tddium said it could only cope with a headless browser environment.

Here’s the gist I hope it saves you as much time as it did me.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ian Zabel

Level up your development workflow with GitHub & Pivotal Tracker

Ian Zabel
Saturday, November 3, 2012

I’ve been working with my client, Unpakt, for a while now. One of their core values is making people’s lives easier. They’re specifically focused on making it easy for people moving to a new home or office to find a mover, compare prices and book their move online.

As a development team, we’ve taken that same core value of making things easier and applied it to our software development & deployment workflow. Over time, we’ve progressively improved our process. We’re now at the point where we’re happy with it, and I wanted to share what we’ve been up to.

The Typical Flow

Let’s assume I’m using GitHub and Pivotal Tracker and I’ve just completed a story. What’s next? Push my changes up to GitHub, click Finish on my story, wait for the build to go green, deploy to staging. Then, click Deliver on all the stories that have just been deployed. Other stories were most likely ready to be delivered as well, so I’ll check that they were actually included in the deployment, and then Deliver them in Tracker.

The typical flow goes like this:

  1. Commit the changes to my story
  2. Push to GitHub
  3. Click Finish on story in tracker
  4. Wait for green build
  5. Deploy to staging
  6. Click Deliver in Tracker

That’s not really that bad. I’m lazy though. If something can be automated, I want it to be automated. For instance, the deployment process should be automatically handled by my Continuous Integration server.

If we take this to the next step and automate our build and deployments as described in Robbie Clutton’s Building Confidence post, we can reduce that flow to this:

  1. Commit the changes to my story
  2. Push to GitHub
  3. Click Finish on story in tracker
  4. Wait for green build
  5. Click Deliver in Tracker

Let’s assume we’ve done that. That’s a nice improvement, as deploys will happen automatically whenever there’s a green build. That in itself is amazing.

But, what if we could reduce the steps in my everyday flow to this?

  1. Commit the changes to my story
  2. Push to GitHub

I want that!

A Streamlined Flow

Here’s the basic idea: tie the commit message to the Tracker Story ID. This enables all kinds of functionality that will get us down to that two step process.

GitHub & Pivotal Tracker Integration

GitHub supports integration with Pivotal Tracker. Dan Podsedly blogged about this back in 2010. You just tag your commits with Tracker Story IDs, and GitHub automatically comments on your story with the commit message. And, most importantly, it will click Finish on the story for you.

First, configure the Pivotal Tracker service hook on GitHub.

Once this is enabled, you can start tagging your commits to use the hook. The syntax for your commit message is pretty simple. Add the following at the end of your commit message:

[(Finishes|Fixes|Delivers) #TRACKER_STORY_ID]

So, if you just fixed a CSS bug for story #35192613:

When you push to GitHub, the post-receive hook will then call back to Tracker and put a comment on the story with a link to the commit on GitHub:

At this point, we’ve eliminated step 3 from above. Now our workflow looks like this:

  1. Commit the changes to my story
  2. Push to GitHub
  3. Wait for green build
  4. Click Deliver in Tracker

Honestly, that’s a pretty nice workflow. If I’m diligent about tagging each commit with the Tracker Story ID, GitHub will handle Finishing the story for me. It’ll also add a comment to the story, so others can take a look at the commit related to the story. Technical PMs especially appreciate this, since their curiousity about what changed is easily satisfied by just clicking on the comment in the story.

But I want more. I want to automate steps 3 and 4.

Deliver Stories Automatically

Pivotal Tracker has an API hook to deliver all finished stories. However, it’s not what we’re looking for. If our CI server calls that API hook after a green build, it’s possible for other stories to have been finished in the meantime that will not be included in the deploy. So, calling this API endpoint will just cause false positives.

A side-effect of tagging all your commits with Tracker Story IDs is that the git log now contains a nice little list of stories that have been finished. This makes it trivial to automate delivery of only the stories that have been deployed.

Unpakt was keen to share the script that makes this happen. They’ve thrown it up as a gist:

#!/usr/bin/env ruby

# gem 'pivotal-tracker'
require 'pivotal-tracker'

TRACKER_TOKEN = "..."
TRACKER_PROJECT_ID = "..."

PivotalTracker::Client.token = TRACKER_TOKEN
PivotalTracker::Client.use_ssl = true

unpakt_project = PivotalTracker::Project.find(TRACKER_PROJECT_ID)
stories = unpakt_project.stories.all(:state => "finished", :story_type => ['bug', 'feature'])

staging_deploy_tag = `git tag | grep staging | tail -n1`

stories.each do | story |
  puts "Searching for #{story.id} in local git repo."
  search_result = `git log --grep #{story.id} #{staging_deploy_tag}`
  if search_result.length > 0
    puts "Found #{story.id}, marking as delivered."
    story.notes.create(:text => "Delivered by staging deploy script.")
    story.update({"current_state" => "delivered"})
  else
    puts "Coult not find #{story.id} in git repo."
  end
end

Using the pivotal-tracker gem, the script finds all Finished stories in your Tracker project, and looks for a commit in the git log with that Story ID. If it finds one, it marks the story as Delivered.

It also adds a note to the story:

Our New Development Workflow

So, here’s what our development workflow now looks like:

  1. Commit the changes to my story (including the Tracker Story ID in the commit message)
  2. Push to GitHub

GitHub will mark my story as finished, and add a comment. CI will then run. If there’s a green build, it will deploy to staging. The deploy script will then run the deliver_stories script shown above, and all stories that have been deployed will be marked as delivered.

This is really, really nice. Having this much of the process automated for me just makes my life easier. It also gives our PM much quicker feedback about what’s happening. It’s very easy to forget to click Finish on a story, or deliver stories that weren’t deployed, or forget to click deliver on stories that were. This workflow eliminates these concerns.

Caveat

For this to work properly, the script that deploys to staging must checkout the same SHA as the green build from CI. If the git log shows commits from after the green build, some stories may be marked as Delivered when they haven’t actually made it through a green build and been deployed.

Caution

This workflow is not for every team. For example, it may be that your team functions better with developers verifying that each story is actually available and working on the staging environment before clicking Deliver in Tracker. No Product Manager wants to try to accept a story only to find that it’s not actually available on the staging environment. It may also be that on your project “Deployed” is not the same as “Delivered”.

You should only consider adopting a flow like this if your project is of a nature where deploys are easy, everyone on the team is playing along, and you can agree that “Deployed” and “Delivered” are one and the same.

The workflow described in this post has been working perfectly for months at Unpakt. We initially ran into the problem described above in the Caveat section, because our CI server running our deploy script while HEAD was checked out instead of the green build’s SHA. We haven’t had any stories accidentally marked as Delivered since we resolved that with TeamCity’s Snapshot Dependency feature.

Unpakt is hiring!

Unpakt is a small team with solid financial backing, led by a highly successful entrepreneur. They are creating an intense but fun and respectful culture and are looking for talented people to join their team. Check out their job listings!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

Building Confidence

Robbie Clutton
Wednesday, October 31, 2012

A build script and associated process of continuous integration (CI) combined are the heartbeat of an application. The build script provides a repeatable way of proving confidence in an application and the continuous integration maintains that confidence over time. The continuous and repeatable nature of these two essential practices enable a highly sought after skill for a software developer: laziness.

Over time the duration of a build script increases as more tests are added or validations are run over the source code. When this happens although a build can have run successfully confidence can be diminished through sidestepping the build. Here I will describe some practices I have found to work for projects I’ve been involved in.

In the following sections, each build is triggered by a successful build of the previous in order to create a pipeline.

Kicking things off

A CI server will usually poll a source control management (SCM) application to see if there are any changes on it and then retrieve the latest code and than run a build script. Some new CI servers can receive a web hook from the SCM to be notified when a repository has changed. The affect is the same in that both should trigger the first build.

Notifications and stopping the line

The strength of CI is enhanced if the team know when something has gone wrong. There are many forms of notifications including email, RSS, custom desktop applications and information radiators like Project Monitor. Whatever you choose, make sure it’s sufficiently annoying as your team should know when something has broken the build. If the team have a ‘stop the line’ mentality, this will also help keep the build going strong and giving confidence back to the team.

The Data Validation build

Applications generally allow validations to be placed within a database or within code, and when the occasion arises when data is changed without going through those validations, the data can be left in an invalid state, e.g. if a migration were run that didn’t go through the validation layer. The data validation build can take a copy of a production dataset (usually cleaned of sensitive data) and for each validation that it cares about, can run that against the dataset. This will show where a fracture has occurred between what the application thinks the data looks like and what the data actually is.

Tests and validations

Source code validations such as code quality metrics and static code analysis usually are quick to run and can be run alongside the tests which generally are hopefully also quick to run. Depending on the size of a test suite, a separate build may be considered for the journey tests. These are the ones that open a browser and generally test drive an application from the very outside of its edges. Everything that runs here should be green all the time, there should be no flakey/flickering tests here. These tests can pollute the confidence of a build by introducing too much noise into the signal that the CI servers are there to give to their teams.

Flakey tests

Flakey tests should be quarantined. These tests are noisy and if left in the main pipeline can diminish the confidence of the build. On a recent project the build took over an hour and would regularly fail due to one or two tests that had issues that we difficult to replicate on our developer machines. These tests would fail the whole build and it got to the point where someone would just trigger a build, or run multiple builds against the same revision to get at least one good build. This was not the intention of the of build. By separating those tests out the majority of the build would go through and then trigger the quarantined tests build. This build had an additional trigger where it would rebuild itself if it failed. This build took minutes instead of an hour to run, so would repeat a few times and then go green. This restored confidence in our build and enabled us to progress quicker.

Having a quarantined test build does not mean these tests are ignored. They are still part of the build pipeline and the final step in the pipeline will not be triggered until this build has gone green. Ultimately, this should not become a dumping ground and a team might even consider some trigger to fail the build automatically if there were over a given number of flakey tests within a run. This could enforce fixing, rewriting or finally deleting these tests if they are truly not giving the project any value.

Deployment

The final steps in the build pipeline is deployment to a staging server and the subject of automation is divided ground. With automation, deploy scripts become hardened and robust as they are tested again and again. Those deploy scripts may also include some sanity checks like loading the homepage and logging into the application to further enhance the feeling that when this build is green, things are good. However, with automation, there is no pair of eyes to make sure it looks good and to ensure that the small part of the application that has been changed is working as expected.

I believe the more automation the better. I want to know that when I make a checkin and that goes all the way through, then I want confidence that it’s done and ready to roll out.

Extra builds for extra confidence

[This section added November 1st, 2012]

The sections above describe a workflow triggered by a change in an applications source code but many applications depend on infrastructure or third party services. An application my be deployed on a given hardware infrastructure which itself is backed by a SCM for it’s configuration. The build pipeline could be triggered when the environment changes to make sure it’s still valid against the changes. It is also likely that at some point the code will change less frequently but still rely on integrations. This is why it is also important to consider having a ‘nightly build’ which tests these integrations. These will ensure the application behaves as expected against software as a service integrations. This build would be triggered at the same time every night, or once a week, just to ensure the stability of the maintained application.

Summary

Being able to trust the build is essential to a healthy project. That is the core reason for the build. The examples above may provide a framework to create or rebuild confidence in a build but these are not the only ways of doing so.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ben Moss

Debugging Travis builds

Ben Moss
Sunday, October 7, 2012

(Due credit to Trung Lê‘s article on which all this is based)

We recently moved our project’s CI from a TeamCity server onto Travis CI’s new private CI-as-a-service program. We compared several other hosted CI services and found Travis to be the easiest to use, and with the help of Trung’s article also the easiest to debug.

Travis provides all their build worker images as Vagrant boxes available for download. I’d never worked with Vagrant before, but getting it set up is pretty simple. Follow the guide on Vagrant’s page and download the latest version of Vagrant. I’ve found that the boxes that Travis provide right now don’t work with VirtualBox 4.2, and so I’d recommend installing VirtualBox with 4.1 from their ‘older builds’ page.

Once you’re done installing both, you’ll want to install the worker box. The Ruby box is installable via

vagrant box add travis-ruby http://files.travis-ci.org/boxes/provisioned/travis-ruby.box

This will download and install the VM, which will probably take a few minutes. After that’s complete, initialize the box with

vagrant init travis-ruby

which will create a Vagrantfile for you where you can configure various settings for how Vagrant hosts the VM on your machine. I’ve found it necessary to add

config.ssh.username = "travis"

to get SSH to work properly. After that,

vagrant up
vagrant ssh

will connect you to the box, and verify that things are working properly. If you are prompted for a password upon sshing, it should be travis.

Now you’ll want to either scp your Github SSH key or create a new one and clone your project down to the box. After you have your project, all that remains is to get Travis running.

I haven’t yet figured out how Travis starts from .travis.yml files, so for now we have just created a shell script in which we specify all our Travis setup tasks, put it as the ‘script’ key in our .travis.yml, and then just run it directly on our local box. You can find more info about doing this on the Travis docs page. Aside from working around the .travis.yml, we haven’t seen any other gotchas in simulating the Travis worker process.

Once you’ve successfully gotten your build to run inside the Vagrant box, you can follow the instructions on Vagrant’s site to repackage your customized Travis worker and share it with the rest of your team.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ian Zabel

TeamCity is pretty cool, you should totally check it out

Ian Zabel
Tuesday, March 13, 2012

At Pivotal, our default choice for CI is Jenkins. I feel that Jenkins does a fine job running builds and reporting on a pass/fail. It also has nice plugins and plenty of features like build labeling and clustering.

JetBrains’ TeamCity has all that, and more!

To be fair, TeamCity is missing some things that Jenkins has. However, I don’t remember what they are because I’ve never used some of the deeper features of Jenkins. One thing TeamCity doesn’t support well is running builds for multiple branches dynamically.

That said, I’m a huge fan of TeamCity. Here’s why.

TeamCity understands your tests. It uses custom formatters for RSpec, Cucumber, TestUnit and Shoulda. This means you get more than just a pass/fail on the build. You get a count of the tests that have run. You also get a count of the tests that failed. Seeing these numbers gives me a warm and fuzzy feeling that I don’t get with any other CI tool I’ve seen.

test counts

Because it understands the tests it’s running, it can keep track of them. For each spec, or cucumber step, it knows how many times it’s passed, and how many times it’s failed. And, it shows you the relevant stacktrace for each failure. You can also get statistics on a particular spec or step, like so:

test detail

It also knows what commit introduced a new failure. Here’s a shot of TeamCity showing a spec failure. The spec description is shown. Below that is the stacktrace in maroon. And to the right, it is showing that the spec first failed in build #532 with andre’s commit. The spec is still failing 105 builds later in build #637. It’s easy to see the stacktrace from both the first failure and the current failure. And yes, that spec has been broken since September 2011.

TeamCity makes it super easy to investigate what is making a build slow. Here’s a list of tests for the bundler gem, sorted by duration. You can filter, sort, and search the tests to analyze what’s going on.

You also get some interesting statistics at the build level:

test success chart
test count chart

The insight and analysis that TeamCity makes possible is extremely compelling. After using TeamCity for a few years, I used Jenkins for a a few months. I really missed all of the features above, and felt a lot less connected to my tests.

Other things I find to be very useful:

  • Immediate feedback if a test fails during a build. The build will go red as soon as the first test does.
  • If a failing test is fixed in a newly running build, it’ll let you know.
  • Besides the awesome insight into your tests, TeamCity has support for larger teams. Users can set or take responsibility for a broken build or individual test. So, it’s easy to keep your team informed about who is working on what.
  • RubyMine integration, including pre-tested commits.
  • TeamCity is free for 20 build configurations and 3 slave agents.

Full list of features: www.jetbrains.com/teamcity/features

Here’s the demo environment: teamcity.jetbrains.com

DISCLAIMER: I do not work for JetBrains, nor are they sponsoring this post. I do, however, love their products.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ian Zabel

[Standup][NY] Wed 5/18/2011: TeamCity + git + symlinks == fail

Ian Zabel
Wednesday, May 18, 2011

Interesting Things

A standup of pivots (Sam Coward, Sean Moon, Peter Jaros, and Brent Wheeldon) have recently run into a bug in TeamCity that causes trouble with symlinks when using git.

If you commit symlinks into your repo, TeamCity will not properly transfer these to the build agents. They end up being copied over to the agents as plain text files.

The workaround for this issue is to use Agent-side Checkouts instead of Server-side Checkouts.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ian Zabel

Radiating your TeamCity Builds

Ian Zabel
Friday, April 8, 2011

If you’re using a Continuous Integration tool, you should also be using an information radiator like Pivotal Labs’ CiMonitor. CiMonitor is designed to be displayed on a screen that the entire team can see. If any of your builds go red, it shows up as a big red square and the team can quickly respond.

CiMonitor has long had support for CruiseControl.rb and Jenkins (formerly Hudson). However, my CI tool of choice is TeamCity from JetBrains. We’ve recently added native support in CiMonitor for displaying your TeamCity build status, and I want to show you how to get it going. It’s as easy as configuring a new project and pointing to TeamCity’s REST API. Let’s walk through it step by step.

Install CiMonitor

For native TeamCity support, you’ll need to be on the latest version of CiMonitor. Follow the installation instructions on the CiMonitor GitHub page. If you already have CiMonitor installed locally, you’ll have to update to the latest version.

Create a New Project

Login to CiMonitor, and create a new project.

Choose “Team City Rest Project” as the Project Type.

For the Feed URL, you’ll be hitting the REST API provided by TeamCity 5.0 and newer. The correct format for the URL is as follows, with the # representing the TeamCity project number:

http://teamcity:8111/app/rest/builds?locator=running:all,buildType:(id:bt#)

You can find the correct project number by clicking onto the project in TeamCity and looking in the URL. Grab the number from the buildTypeId parameter.
TeamCity Project ID

You will also need to fill in a TeamCity username and password that CiMonitor will use to access the REST API.

Example Settings

New Project

Once you’ve set up the new project, save it and you’re all set.

Watch Your Builds Run!

You can now easily see the status of your TeamCity builds.
TeamCity Builds

CiMonitor will also show that a build is currently in progress.
Running TeamCity Build

Wrapping Up

The integration is pretty solid, but there are one or two things that may seem to be odd behavior.

CiMonitor keeps track of build start times to control the size of the build dots for each project. The older the build, the smaller the dot. Currently, TeamCity’s REST API doesn’t publish the start time of a running build. Since this data is unavailable, CiMonitor just uses the current time when it fetches the feed. This is a minor issue, and JetBrains has already committed a fix for their REST API which will be released in the next version of TeamCity. CiMonitor will use the new field if it’s present in the feed.

Also, TeamCity has a great feature that will tell you that a build is failing before it even finishes. This has an interesting effect on CiMonitor. If a TeamCity build is red, the next time it begins running, CiMonitor will show it as green until the first test fails. Once TeamCity picks up on a failure, CiMonitor will show the build as red. This can be a little confusing at first because it may look like a build-in-progress is green before it has finished.

Hopefully you find this new functionality useful!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Phil Goodwin

Standup 12/17/2010 Comparing indexed date columns, git subtrees, Headless Selenium for CI

Phil Goodwin
Friday, December 17, 2010

Helps

Is there a way to get MySql indexing to speed up queries involving greater and less than operators on date columns?

Postgres handles these operators a little bit better than MySql, but may not actually solve this problem.

Using millis instead of dates would give the DB the best chance of handling this scenario.

We are using Git’s subtree merge facility instead of submodules to stay synced to a different repository for part of our project. How do we push changes back to that repo?

See Tim Connor’s blog post “Git sub-tree merging back to the subtree for pushing to an upstream“. Early in that post is a pointer to an article describing the the subtree merge operation. Tim goes on to explain how to push your changes back through the chain.

Interesting

  • Some cloud environments leave the names of temp files visible even when their contents are not accessible. Be sure to use obfuscated names for your temporary files!

  • The “Headless” gem allows you to easily set up an alternate “display” that allows programs to execute in a headless environment. See this blog post about how to use Headless to run Selenium tests on a CI box: http://www.aentos.com/blog/easy-setup-your-cucumber-scenarios-using-headless-gem-run-selenium-your-ci-server

  • Ccrb will bog down to painfully slow levels if more than a couple of CC Tray clients are pinging it repeatedly during a build.

  • Cron will not honor your .rvmrc file unless you do some work to set up the environment. If you set up your cron job like this:

0 6 * * * /bin/bash -l -c 'echo /home/someuser/.rvm/bin/rvm rvmrc trust ... && cd ... 

the -l & -c parameters cause bash to load your environment as if your were logging in before running the specified commands. Someone also mentioned that rvm-shell can be used as a solution to this problem.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (86)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (53)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (21)
  • cucumber (20)
  • bloggerdome (19)
  • process (19)
  • pivotal tracker (19)
  • design (18)
  • jasmine (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • gem (13)
  • bdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • tdd (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • rubygems (9)
Subscribe to ci Feed
  1. 1
  2. 2
  3. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >