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

Monthly Archives: January 2010

Will Read

"Point" Me in the Right Direction

Will Read
Friday, January 29, 2010

“Bugs and Chores don’t get points, unless you want to give them points, then they get points, but don’t point your bugs or chores.” Whaaaa?

In Tracker, you can (and should) always point your features. But you have to turn on this setting buried deep in the menus and next to a disclaimer if you want to point your bugs and chores.

If you’re looking for that check box, you’re probably a developer, or someone who is responsible for justifying the work of the developers. The business side has no interest in it what-so-ever. “Why?” That’s the right question.

The two of you (business and development) are trying to answer two different questions. Business wants to know how long it’ll be before they can release a product. As such, they have a set of features that must get in to a release. Doing anything aside from features, like chores and bugs, is paying down debt, and thus should be subtractive from velocity.

As a developer, you are less interested in when the business guys have decided to put a stamp on it and “go live”, you’ll still be developing just as much the next day anyway. You want to know if you’re getting better, faster, stronger as a team (we have the technology btw, just ask for Pivotal Labs!). Typically you might do an iteration or two with a lot of features, build up a solid velocity, push it to staging, and wait for the bugs to roll in. Now your next iteration is almost all bugs and your team is killing it, but Tracker says “0 points” and it kills you. “The guys (and gals) are doing all this work, and this will wreck their velocity”, you think to yourself.

Yes. But! Only their points completed for that iteration will be zero. Their velocity will accurately reflect their ability to deliver features over time. To better illustrate my point consider the following team:

  • They get started on a new feature set, first iteration: 10 points, 1 bug, 4 chores
  • Second iteration, the groundwork is laid out now: 15 points, 4 bugs, and 1 chore
  • By the third iteration, they’re in the groove: 20 points, 1 bug, 1 chore
  • They push to staging, get a bug list back and get to mashing in the fourth iteration: 2 points, 18 bugs, 0 chores
  • Release!

If you fiddle with the number of iterations Tracker uses to compute the velocity, you see numbers like this at the end of the final iteration:

  • 1 iteration: velocity = 2
  • 2 iterations: velocity = 11
  • 3 iterations: velocity = 12
  • 4 iterations: velocity = 11

In this case, 11, from the average of the past 4 iterations, is the interesting number to most. It includes the bug part and the ramp up part. If your releases tend to be 3 iterations, you might consider making velocity an average of 3 iterations. If your releases are 15 iterations long, you might want to consider breaking them down into smaller releases.

By matching the number of iterations used to compute velocity to the length of your typical release, you should arrive at a very stable velocity for your team. This not only helps the business side predict when you can release, it also gives you something to point at when the financial guy wonders if the whole engineering team took the week off when you had a 0 velocity. And if he really grills you, you can always pop open Tracker and show the list of bugs and chores that were found by the other outstanding employees and how they’ve since been corrected, making the product better than it has ever been before.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Christian Sepulveda

Tweed 1.3: RT Style setting, bug fixes

Christian Sepulveda
Thursday, January 28, 2010

Version 1.3 has been submitted and should be in the App Catalog soon.

Bugs

  • Load More showing gaps in home timeline
  • TweetPhoto: upload and in-app photo viewing restored
  • can remove account if username changed on Twitter
  • RT’s now show timestamp of RT, not original tweet
  • webOS 1.4 issues are fixed (for upcoming webOS update)

Features and Changes

  • specify RT style: old, new or prompt (per tweet)
    tions

Tweed
Tweed
Tweed

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Davis W. Frank

Report: Palm webOS Workshop 1/23

Davis W. Frank
Wednesday, January 27, 2010

Sarah Allen approached Pivotal back in December wanting to host a Palm webOS hack session. She knew that there was curiosity among the San Francisco Rails community about the platform and wanted to have a hands-on coding day where they could learn.

And so it happened this past Saturday. Pivotal hosted in our downtown SF offices. Palm sponsored, which meant about a half-dozen Palm employees attended to help out…oh, and give every attendee a copy of Mitch Allen’s O’Reilly book and a phone (Sprint Pre or Pixi).

While our previous events were more presentation + Q&A, thanks to Sarah Allen, this event was much more hands-on. I kicked off with a presentation and live coding, then we had lunch, then spent the afternoon hacking.

Overall I think it went well (see the Twitter search #webosworkshop). The crowd was a focused group of (mostly) Rails developers who were curious about the platform. I got lots of help during the live coding session (despite our failed monkey patch of JavaScript’s String prototype). People paired up and worked on projects together, proving that webOS is an easy platform to pick up if you’re a Rails developer. I expect a few new apps for Palm in the coming weeks.

We recorded my presentation & coding session, so we’ll post that in a few days along with my slides. Unfortunately we didn’t tape the live demo of Palm’s Ares, their in-browser development environment. But there’s a nice tutorial video on their portal. Other posts:

  • Sarah posted her notes
  • Palm’s Lisa Brewster posted her awesome photos
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Adam Milligan

Standup 01/25/2010: Doing our part

Adam Milligan
Monday, January 25, 2010

One of our clients recently presented a demo of a new web application we built for them to a potential customer. This customer happens to be a large corporation who enforces, as large corporations will do, the use of IE6 on all of their corporate machines. When we found this out we feared the worst: many tortuous hours of work twisting the fabric of good sense and CSS standards to eke a sensibly rendered site out of the maw of the IE6 beast.

Imagine our relief and surprise when the head of corporate IT for the potential customer not only decided that the application was essential for the organization, but that to support it they would eliminate the use of IE6 on their corporate machines.

Mark one in the win column for the good guys.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
JB Steadman

more page dynamics, less client logic

JB Steadman
Saturday, January 23, 2010

Ajaxed pages frequently need to update many parts of the page within ajax callbacks. Here I’ll outline how we use jQuery and Rails do this on Mavenlink. Our approach encodes behavior declaratively in markup and minimizes client-side logic.

Mavenlink provides a rich collaborative workspace for clients and consultants. All workspace activity happens within a single page. When a user adds a new deliverable to the workspace, we need to update three parts of the page. The dynamic page areas are highlighted in this screenshot of a typical workspace:

Mavenlink workspace

See the page in action yourself by creating your own workspace on Mavenlink.

To add a deliverable, the user submits the ajaxed form circled at right. Upon success, we need to update the deliverable module (A), the list of deliverables in the popup (B), and the event feed (C).

However, we’d like to avoid having our javascript know this. We try to avoid callback code along the lines of “when X happens, do A, B, and C”. Additionally, we want to avoid creating multiple event listeners responsible for dealing with something like a “deliverableCreated” event.

Instead, we mark up the parts of our document that can be updated dynamically. When new content arrives via ajax, we match the new content to the marked up dynamic elements, using shared attribute values to perform the match.

Specifically, we define a custom attribute called ‘content-key’ on our dynamic elements. Here’s three sections of the page’s original markup defining the three elements outlined in the screen shot:

<!-- deliverable module (A) -->
<div content-key="deliverable-module">
  ...
</div>

<!-- the deliverable popup (B) -->
<ul content-key="deliverable-popup">
  ...
</ul>

<!-- the event feed (C) -->
<ul content-key="events">
  ...
</ul>

In handling an ajax request to create a deliverable, we generate response markup with matching elements. The response looks something like this:

<div content-key="deliverable-module">
 <!-- new html -->
</div>
<ul content-key="deliverable-popup">
 <!-- new html -->
</ul>
<ul content-key="events">
 <!-- new html -->
</ul>

Our ajax success callback invokes a function that uses jQuery to inject the new html into the page’s original content-key elements:

function updateContent(event, newContent) {
  var $contentKeyElements = $(newContent).filter('[content-key]');

  // iterate through each new content-key element

  $contentKeyElements.each(function() {
    var contentKey = $(this).attr("content-key");

    // replace existing content-key html with new content-key html

    $("[content-key="+contentKey+"]").html($(this).html());
  });

  $(document).trigger('content-updated');
}

One advantage of this approach is that we can add new behavior without adding client-side logic. For example, if we want to show a flash message when a deliverable is created, we add a <div content-key='flash-notice'> element to the page, and match it with markup returned in the ajax response. The new behavior is encoded declaratively in our markup.

This approach keeps the server side pretty simple as well. In our create() action, we render the same partial whether the xhr request succeeds or fails:

class DeliverablesController < ApplicationController
  ...

  def create
    @deliverable = @workspace.deliverables.build(params[:deliverable])
    status = @deliverable.save ? 200 : 400
    render :partial => 'deliverables/deliverable_response', :status => status
  end
end

The deliverable_response partial renders secondary partials that each render a content-key element reflecting the new state of the page:

<%= render :partial => 'deliverables/deliverables_module' %>
<%= render :partial => 'workspaces/deliverable_popup' %>
<%= render :partial => 'workspaces/events' %>

These secondary partials are the same ones used to build the original page, so we’re not writing any new rendering code for ajax. Validation error messages are rendered within deliverables/deliverables_module in the manner of normal Rails forms.

You may have noticed that in our ajax responses, we render more than we strictly need to. For example, when a deliverable is created, we could just add a single new <li> element within our <ul>s instead of rebuilding the <ul>s entirely. For moderately-sized, moderately dynamic pages like our workspace page, micro-optimizing responses can needlessly complicate code without providing any meaningful performance benefits. When reality permits, we prefer blunt stupidity over intricate precision. It’s much easier to deal with.

Watch out for replacing markup that carries dynamic state, such as tab selection and expand/collapse state, both of which we use on Mavenlink’s workspace page. You can either avoid destroying state by narrowing the scope of your content-key elements, or restore the state in javascript after new markup is loaded. In a later post, I’ll detail how we deal with it on the workspace page.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

New in Pivotal Tracker: API V3, GitHub & Campfire support, JIRA, Lighthouse, and Satisfaction integration

Dan Podsedly
Saturday, January 23, 2010

This Pivotal Tracker update allows you to see GitHub or other SCM commits in your stories, your project activity in your team’s Campfire chat room, and introduces the first wave of integrations with other bug/issue tracking applications including JIRA, Lighthouse, and Satisfaction.

There is also a new version of the API (V3), with support for moving stories, file attachments, as well as activity web hooks. The first version of the API (V1) is no longer available.

Continue reading for more details on what’s new.

API V3

This is a new version of the API. As part of this release, the first version of the API (V1) has been removed. You can continue to use V2, but that version will deprecated at some point in the future.

Highlights of what’s new in API V3:

  • access to more complete and detailed project activity
  • support for adding file attachments to stories
  • ability to move (re-prioritize) stories
  • GitHub post-commit support, as well as a generic post-commit hook, to allow you to associate source commits with stories
  • more information in the project resources, including labels

Complete documentation is available on the API Help Page. For more details about what’s new or changed in the API, see this blog post.

Activity Web Hook

Tracker can now post notifications to a URL you specify as story activity happens in your project. The POST body of these requests will contain XML describing the event, as well as the affected story, in the exact same format as the API activity response.

One way to use the web hooks is for integration, to keep stories synchronized with resources in other systems. We’re hoping you’ll find other interesting ways to use them.

Activity web hooks can be enabled on your project’s Integrations page. To get there, go to your project settings, and click on the Integrations tab at the top right. More information on activity web hooks, as well as other types integration are available on the Integrations help page.

Bug / Issue Tracking Tool Integration

In this release, we’re introducing the first of many external integrations, starting with support for JIRA, Lighthouse, and Satisfaction.

The objective of these integrations is to allow your team to prioritize, and collaborate around stories that are tied to existing tickets/issues in other systems, increasing overall visibility without having to do manual double entry. For the JIRA and Lighthouse integrations, changes to story states, and new comments will be reflected in the linked ticket/issue.

In the first release of integrations, story – ticket synchronization is 1 way only (Tracker -> JIRA/Lighthouse), but it’s possible to make that 2 way by using the Tracker API, and Lighthouse web hooks or a JIRA plugin.

See the Integrations help page for more on integrations, and how to set them up for your project.

Campfire Notification

You can now see activity from your Tracker project in your Campfire chat room.

Read more about the Campfire integration on the on the Integrations help page

As always, we welcome your feedback. If you have something that you’ve created with the API, and would like to share it with our user community, please let us know!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

UTC vs Ruby, ActiveRecord, Sinatra, Heroku and Postgres

Alex Chaffee
Friday, January 22, 2010

Now that I’m starting to use DelayedJob to perform jobs in the future in my Heroku Sinatra app, its important that they happen at the scheduled time. But unless you pay attention, you’ll find that times get mysteriously changed — in my case, since I’m in San Francisco in the wintertime, by +/-8 hours — which means that some conversion to or from UTC is being attempted, but it’s only working halfway.

Trying to keep a handle on which libraries are attempting, and which are failing, to convert times is a losing battle, so I’m trying to do the right thing and save all my times in the database in UTC, and convert them to and from the user’s local time as close to the UI as possible. Unfortunately, a variety of gotchas in Ruby and ActiveRecord and PostgreSQL makes this trickier than it should be. Here’s a little catalog of my workarounds.


You must set both Time.zone = "UTC" and ActiveRecord::Base.default_timezone = :utc. Since I’m using Sinatra, not Rails, this stuff goes either in main (i.e. not inside any class) right after require 'active_record', or in a configure block in your app, depending on your preference.


When ActiveRecord creates queries — which are used for both reading and writing, mind you — it will only convert to UTC times that are instances of ActiveSupport’s proprietary TimeWithZone class. It will not convert regular Ruby Time objects, even though Time objects are perfectly aware of their time zones, and AR is perfectly aware that you’d prefer they be written as UTC (due to the default_timezone setting). This is clearly a bug IMHO, but the Rails core marked the bug as “will not fix”, so w/e. Here’s a monkey patch, courtesy of Peter Marklund:

  module ActiveRecord
    module ConnectionAdapters # :nodoc:
      module Quoting
        # Convert dates and times to UTC so that the following two will be equivalent:
        # Event.all(:conditions => ["start_time > ?", Time.zone.now])
        # Event.all(:conditions => ["start_time > ?", Time.now])
        def quoted_date(value)
          value.respond_to?(:utc) ? value.utc.to_s(:db) : value.to_s(:db)
        end
      end
    end
  end

When outputting timestamps to a UI — either inside HTML or in a JSON API — you’ll probably want to use Time#strftime. Beware: on Mac OS X under Ruby 1.8, the %z (lowercase Z) selector will emit the local time zone, not the zone of the Time object you’ve called strftime on. The solution is to either use %Z (capital Z) or just a plain Z which stands for Zulu Time. The latter is OK if you know you’re using UTC, which, if you’ve followed my advice, you probably do. This is a pretty annoying issue, since it’s much safer to use %z‘s hour offsets than %Z‘s three-letter codes, since the three-letter codes can be ambiguous, and in any case require an extra conversion to time offset, so you may as well just emit the offset.

Here are some methods on Time you may want to use that work around this %z issue:

  # Note: do NOT call this file 'time.rb' :-D

  require 'time'

  class Time
    def full_date_and_time
      strftime('%Y-%m-%d %H:%M:%S %Z')
    end

    def iso8601
      strftime('%Y-%m-%dT%H:%M:%SZ') # the final "Z" means "Zulu time" which is ok since we're now doing all times in UTC
    end
  end

That iso8601 method comes in really handy when you’re using the excellent timeago jQuery plugin by Ryan McGeary (@rmm5t).


By default PostgreSQL saves timestamps sans time zone, which means that ActiveRecord interprets them as being in the default_timezone. If you want to be extra clear and save them with time zone, you’ll have to change the Postgres adapter’s type mapping. ActiveRecord doesn’t let you configure this but here’s a monkey patch, courtesy of
Chirag Patel (with a couple of mods):

    require 'active_record/connection_adapters/postgresql_adapter'
    class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
      def native_database_types
        {
          :primary_key => "serial primary key".freeze,
          :string      => { :name => "character varying", :limit => 255 },
          :text        => { :name => "text" },
          :integer     => { :name => "integer" },
          :float       => { :name => "float" },
          :decimal     => { :name => "decimal" },
          :datetime    => { :name => "timestamp with time zone" },
          :timestamp   => { :name => "timestamp with time zone" },
          :time        => { :name => "time" },
          :date        => { :name => "date" },
          :binary      => { :name => "bytea" },
          :boolean     => { :name => "boolean" }
        }
      end
    end

It turned out that I didn’t need this, so I ended up commenting it out. It may be that storing timestamps with time zones will cause a hiccup with some other random DB code, so watch out. If you do use it, and you’ve already got some data, make sure to write a migration that changes the types of all extant datetime and timestamp fields, and maybe a migration that shifts the times too.


That’s all I’ve got for right now. I’m sure some more problems will come up on March 14, 2010…

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

Pivotal Tracker maintenance and upgrades this weekend

Dan Podsedly
Friday, January 22, 2010

We are planing to do a Tracker upgrade (with new features including API V3 and some integrations) tomorrow, Saturday Jan 23, at 5:30pm PST. We expect the upgrade to take under two hours.

Also, Engine Yard will be performing some maintenance and upgrades our hardware cluster on Sunday, from 10:00am to 1:00pm PST.

Sorry for the inconvenience. If you need access to your project data during the downtime, we recommend you export your project(s) beforehand:

http://www.pivotaltracker.com/help#howcaniexportstoriesfrommyproject

Also, as a reminder, the first version of the API (V1) will be disabled as part of tomorrow’s release. More information on that here.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Dan Podsedly

tgethr email collaboration and Pivotal Tracker

Dan Podsedly
Friday, January 22, 2010

If you’ve been looking for a way to turn emails into Tracker stories, take a look at tgethr. It’s an email collaboration service for groups, and it now integrates with Pivotal Tracker.

Read about it in this tgethr blog post.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Davis W. Frank

Standup 2010.01.21: Questionable Latin Edition

Davis W. Frank
Thursday, January 21, 2010

Interesting Things

  • Caveat Experior: Pivot Mike found a bug in Webrat in Selenium mode when using #click_link. He filed a ticket at Lighthouse.
  • Caveat Coracinatus: Attention to those “Riding the Toad” (I didn’t make this up – it’s on Hoptoad’s homepage): the Hoptoad Notifier gem that was released on Jan 20, v2.1.1, is missing a file. Make sure to update to the latest version, v2.1.2 in order for this gem to work. You should be on the latest gem anyway because there’s a deprecation in the session code that will stop working in February. If you have a site that’s not actively being developed you will need to update the gem & redeploy your app in order to continue to receive exception notifications.
  • 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 Community Feed
  1. 1
  2. 2
  3. 3
  4. →
  • 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 >