Featured Plugin: Workflow

Tuesday, September 15, 2009 by David Fullerton

In a previous article, I wrote about the FogBugz Plugin Architecture, and how it lets us answer some very common customer requests without suffering from feature bloat. In this article we'll examine in detail one of our most popular plugins, Workflow, which does just that.

The Default FogBugz Workflow and Why It's Good

Out of the box, FogBugz provides an intentionally simple workflow for cases. Each case passes through three stages: active, resolved, and closed. When a case is created it is assigned to someone as an active case. When the issue has been dealt with, it is resolved. At that point, it automatically goes back to the original opener so that they can verify the solution. Once they are satisfied, they close the case.

This workflow turns out to work very well for a variety of case types. Bugs start out at a tester or user who found the issue, then go to a developer who fixes it and then resolves it back to the opener for verification. Features begin at the person requesting the feature, go to a team lead or developer to implement, and then end up back at the person who opened it to confirms that the feature meets their requirements.

Furthermore, this workflow encourages a particular way of using FogBugz. It encourages users to verify the resolution of cases, which means more bugs are actually fixed. It also encourages a simple process, so a developer can open a "remember to write the documentation" case without it having to go through six steps of approval. This means that more cases make it into FogBugz instead of ending up as sticky notes all over the monitor.

The default FogBugz workflow: active, resolved, and closed

When the Default Workflow Isn't Enough

Unfortunately, there are some cases where the default workflow breaks down. Sometimes a customer will open a case to report a bug, but they really shouldn't be responsible for verifying it. Often there is a QA person who should be involved in the process for certain categories of bugs. Or a team might want to differentiate between a feature that still being specced and one that is in development.

The default Workflow is very much a 90% solution: it works great 90% of the time (probably more, actually), but that last 10% of the time it just doesn't do what you want. The result is that you end up fighting with the tool, rather than having the tool get out of your way and allow you to get your work done.

At the same time, the last thing we want is for an organization to get FogBugz and then spend a week in meetings drawing flowcharts trying to decide what happens if a bug gets found by a tester in Department A, but it actually comes from a component developed by Department C, so it needs to be verified by the QA teams in both and there's absolutely, positively no way anybody can start creating bugs until this is figured out.

We want FogBugz to JUST WORK, right up until the point where it doesn't, at which point you find the super easy solution we've prepared for you, click a few buttons, and continue on your merry way.

Customizing the FogBugz Workflow

Fortunately, plugins give us a great way to have both simple, sane out-of-the-box behavior, and powerful customization only a few clicks away. For users who don't care or who find that the default workflow is good enough for them, FogBugz continues to work exactly the same. But for the users who need the ability to customize their system, the Workflow plugin can be installed with just a few clicks from the FogBugz Plugin Gallery.

The Workflow plugin allows users to customize workflow in two ways: by defining new categories and statuses, and by specifying how cases are assigned when transitioning a case between statuses.

The Workflow plugin adds a new item to the Admin menu

Custom Categories and Statuses

The first thing to do when customizing the FogBugz workflow is decide what types of cases the customization should apply to. This isn't always as straightforward as it seems. It may seem obvious that all bugs should have to be verified by QA, until you actually implement it and your developers start complaining that every time they create a little case for themselves to remember to fix something it has to be verified by QA. Before you know it, they're back tracking their bugs in notepad and you're amazed at how effective your new process is at reducing the number of bug reports in your software.

Since changing the workflow is potentially so disruptive, we recommend trying out major changes on an entirely new category, which the Workflow plugin makes completely painless to create. In our example, we might create the category "Bug (Needs QA)". Now developers can continue to create reminder cases for themselves that don't have to go through QA, and testers can create cases that will always follow your new workflow. Later on, with just a few clicks you can delete the old "Bug" category if you find you're not using it.

Once you have your categories nailed down, you'll want to create some statuses for them. Here you can take advantage of another new feature in FogBugz 7: multiple active statuses. Before FogBugz 7, all categories only had one active status: "Active". Now using the Workflow plugin it's possible to add multiple active statuses. For example, you could create the "Active (In Development)" status for bugs, or the "Active (Needs Spec)" status for features.

For our example above, we'll add two resolved statuses: "Resolved (Fixed)" and "Resolved (Verified)". When the development team has finished fixing the bug, they resolve the case as "Fixed". When QA has finished verifying the case, they'll resolve it as "Verified".

Add a new category with just a few clicks

Customizing Case Assignment

The other half of custom workflow is defining how cases get assigned when changing the status. In FogBugz 7, each project can have its own workflow. This allows you, for example, to have a special workflow just for the "Inbox" project, or have one workflow shared between all development projects.

Each workflow determines to whom cases are assigned for each status in four different circumstances:

  1. Creating or Editing the status of an active case
  2. Reactivating a resolved case
  3. Reopening a closed case
  4. Resolving a case

When selecting to whom the case is assigned, you can choose either a particular user (e.g. "Joel Spolsky"), or you can choose a special value such as "Primary Contact" or "Case Opener", or even "No Change" to keep it assigned to the same user.

You can also choose whether the assignment is forced. Forced assignment means that when the workflow rule is in effect, the "Assign To" dropdown will not be editable. This guarantees that the case will be at least initially assigned to the specified user.

For our QA example, we'll set the rules for our statuses as follows:

When Resolving a Bug (Needs QA),

  • Resolved (Fixed) assigns to "Alison Tirrell", our QA lead, and is forced
  • Resolved (Verified) assigns to "Case Opener", and is forced

For everything else we'll use the defaults. This will give us the following workflow for cases opened as "Bug (Needs QA)":

  1. Case Opened
  2. Active & gets assigned to a developer
  3. Resolved (Fixed) & gets assigned to QA by the developer
  4. Resolved (Verified) & gets assigned to the case opener by QA
  5. Closed by the case opener

Using this workflow, we've preserved the original spirit of the FogBugz workflow, where the opener verifies a case, and added a QA step for bugs that need it.

Determine to whom cases are assigned by editing the workflow

What Custom Workflow Isn't

As powerful as this method of custom workflow is, there are a few things that it can't do. It doesn't allow restricting the order that statuses have to go in, so there's no way to say that the "Active (Needs Spec)" status must progress to "Active (In Development)" before going to "Resolved (Implemented)".

It also doesn't allow restricting on users: there's no way to say that only an administrator can close a case, or that cases with the status "Active (In Development)" have to be assigned to a developer.

Also, having a "forced" assignment in the workflow only determines who the case is initially assigned to. Once the case is assigned to a user by a "force" rule, it can be reassigned to anyone (though the original user will always get a notification that the case was assigned to them).

In this, workflow follows the FogBugz philosophy of keep it simple, and stay out of the user's way. If a non-QA user really wants to resolve a case as "Verified", they probably have a good reason to do so. If a user needs to grab a case back after it has been assigned to the Primary Contact for review, they probably know what they are doing better than FogBugz does.

Advanced Custom Workflow

With that said, it is possible to build on the Workflow plugin to create more advanced workflows. If you want to make sure that cases with status "Active (In Development)" are assigned to a developer, you could make a plugin that automatically finds cases in violation of this and reassigns them to an appropriate user.

You could also use plugins to create special virtual users that your workflow assigns to, which have a special meaning in the plugin. For example, you could create a "Case Owner" plugin that adds a new "Case Owner" field to cases, and then lets you choose "Case Owner" as the person assigned to when a case is resolved. Or you could make a "Round Robin" virtual user, and have the plugin distribute incoming cases to one of several users, and use this to handle incoming support requests.

A plugin could even do a similar thing with statuses, by having a special "Next Step" or "Auto" status. When a case is set to the status "Next Step", the plugin takes over and moves it to the correct status and assigns it to the appropriate user.

These are just a few ideas of advanced workflow plugins that could be created. If you have your own idea, you could add it to the Plugin Ideas Forum, or get started writing your own, and of course we'll be happy to answer any questions you might have on our StackExchange site.


Categories: FogBugz

Tags: ,

Actions: E-mail, Permalink


The FogBugz Plugin Architecture

Monday, August 10, 2009 by David Fullerton

Feature Bloat

Feature bloat is a familiar problem for any software project, especially one approaching a decade of continuous development.  For FogBugz, the sirens' call of bloat usually sounds something like this:

"Hi Fog Creek!  I love the new tagging feature in FogBugz 7!  My only problem is that I don't seem to be able to create a reverse-alphabetical, zebra-striped tag cloud.  In my organization we only use reverse-alphabetical, zebra-striped tag clouds and without them our entire production line has ground to a halt!  How soon will you be adding this feature?"

Now, 90% of our users have never even heard of reverse-alphabetical, zebra-striped tag clouds, and adding support for it to FogBugz will just add one more confusing feature and make FogBugz as bloated as the Michelin Man after Thanksgiving dinner.  But this is something that at least one customer really needs, and we don't want to just ignore them forever.

In the past we've always dealt with the threat of bloat by implementing the 90% solution really, really well.  The 90% solution means building the features that most people are asking for while we punt on the other 10%.  This lets us spend our energy on making sure the features for the 90% are both powerful and easy to use, and make our customers ridiculously happy.

Unfortunately, adding 90% solutions together doesn't mean that 90% of our users are 100% happy. That last 10% is never the same 10% for everyone, so we end up with an insane Venn diagram of competing desires, some of which may even be mutually exclusive!  With every release we address the biggest of these, but we also accumulate a few more customers who just wish we would add that one feature that would make FogBugz perfect for their organization.

One of our goals for FogBugz 7 was to provide a way of addressing all of these requests for features, without compromising the core simplicity and elegance of FogBugz out-of-the-box.

Sometimes we get carried away trying to make everyone happy

Enter Plugins

Plugins provide an elegant solution to this problem: create snap-on features that integrate seamlessly with FogBugz, but can be added and removed with the click of a button.  With a simple plugin, we can satisfy the 10% of customers dying for that reverse-alphabetical, zebra-striped tag cloud without the other 90% ever having to know that it even exists.

Even more exciting, plugins finally allow other people to modify FogBugz without having to dive into our scary Wasabi source code.  Anyone can write their own custom plugins, and then share them with the world in the FogBugz Plugin Gallery.

Installing plugins is dead simple: if you have FogBugz on your own server just download the zip file from the Plugin Gallery and click the upload link in FogBugz.  For FogBugz On Demand, just follow a link to the Plugin Gallery from your FogBugz account and it will be automatically installed when you click the install button.

Install plugins from the FogBugz Plugin Gallery with just a few clicks

The Plugin Architecture

So how did we actually do it?  First we had to port FogBugz from classic ASP to ASP.NET, but that's the subject of another post.  Once we did that, we were able to use some cool facilities built into .NET.

In FogBugz, plugins are simple .NET assemblies (DLLs) loaded into FogBugz.  As such, they can be written in any .NET language (C#, VB.NET, F#, etc.), and can leverage the powerful .NET Framework libraries.

These plugin assemblies communicate with FogBugz in two ways: by calling methods on the API, and by implementing special interfaces.

The interfaces that a plugin implements determine when and how FogBugz calls into the plugin.  Let's say a plugin wants to add a color-coded label to a case, and it should be displayed as a column in the case list.  All the plugin developer has to do is implement IPluginGridColumn, which specifies how to display the column and sort it, and FogBugz does the rest.  When FogBugz needs to display the column, it looks up the plugin and calls the appropriate methods (see an example).

Inside those methods the plugin will probably want to query FogBugz for some information.  It does this using special API methods that let a plugin do things like query the database, edit a case, or add a notification to the top of the page.  Since the plugin is running as an assembly on the server, there are no crazy hoops to jump through: for example, loading a bug is as simple as calling api.Bug.GetBug(caseId)!

Since these interfaces and API methods are the heart and soul of the plugin architecture, every single method and property has full Visual Studio IntelliSense documentation, and every interface has an example implementation in the Plugin Developers Wiki.

Full Visual Studio Intellisense

The FogBugz API includes complete Visual Studio Intellisense

What Plugins Can Do

So what exactly can Plugins do?  A lot, and we're actively expanding it.  Here are just a few quick examples:

  • Create new FogBugz pages
  • Add new column types to the case list grid
  • Create custom fields on cases
  • Extend search with custom search axes
  • Add customizable filter criteria
  • Load, modify, and save FogBugz entities like Cases, Users, Projects, Milestones, Wikis, and more
  • Create custom database tables
  • Query FogBugz database tables
  • Create FogBugz "Editable Tables" with AJAX popups
  • Write raw binary data and set content headers to allow custom file downloads
  • Run periodic tasks during FogBugz background maintenance

Much more information and loads of examples can be found in the Plugin Developers Wiki; many of the examples above have a complete annotated example to help developers get started!

The Kanban Board plugin adds a new column to the grid

Plugin Security and AppDomains

Being able to run directly on the server is great for plugin developers, but it could be a nightmare for system administrators, especially for plugins coming from unknown third parties. In fact, our sys admins nearly had a fit when we first started talking about how plugins would work.  The problem, however, is not nearly as bad as it seems at first blush thanks to the power of .NET AppDomains.

AppDomains in .NET are a way to run assemblies in specially managed sandboxes with fine-grained control of what they can and can't do.  For example, the .NET FileIOPermission specifies what directories an assembly can read or write, and the WebPermission controls what URLs an assembly can hit over the web.  .NET itself defines dozens of permissions, and has facilities to allow developers to define their own.

So what permissions do we deny plugins in FogBugz?  Almost everything!  They are forbidden from accessing the file system or the registry, or connecting to databases, or running unmanaged code, or...well it's easier to say that we basically start with a completely blank slate, and only give plugins the handful of permissions they need to run.

"Wait!", you say.  "Plugins can't access the database?  How do they do anything interesting?".  Plugins aren't allowed to talk to the database, but FogBugz sure can.  So if a plugin wants to do something that it doesn't normally have permission to do, the request has to go through FogBugz via an API.  FogBugz, in turn, is very restrictive about what it allows plugins to do: for example, every SQL query is run through a validator to ensure that it doesn't do anything dangerous.

"But what if I want my plugin to be able to talk to another database", you cry again.  Well, in the 7.0 release all plugins run in a single, very restricted AppDomain, but in future releases we plan to add support for FogBugz administrators to loosen the restrictions for certain plugins known to be safe.  This would allow, for example, a plugin that integrates FogBugz with a sales database, or lets the plugin access certain network resources.

We start with a blank slate and only allow necessary permissions

Enforcing FogBugz User Permissions

Of course, when loading information from the database, Plugins need to be aware of another level of security: FogBugz user permissions.  Not every user in FogBugz has access to every case, or is allowed to modify a project.  To make things simpler for plugin developers and to reduce the risk of data exposure, whenever possible the FogBugz plugin architecture adopts a "fail closed" policy.

A "fail closed" policy means that by default we enforce the permissions of the current user when the plugin runs.  For example, if a user visits a plugin page that displays information about a case, a permission check is automatically run when the plugin tries to access the case data.  If the current user does not have access to view the case, the plugin will receive an exception.

Automatically enforcing permissions means that much of the time plugin developers can write without having to worry about permissions.  In the worst case, the plugin will return an error rather than revealing potentially sensitive data.  In the special situations where a plugin needs to do something unusual with permissions, it can turn off the automatic permission handling on an object and manage the permissions itself.

FogBugz automatically enforces the user's permissions

The Future of the Plugin Architecture

We're all extremely excited about the first version of the plugin architecture in FogBugz 7.  We think it provides a powerful foundation for a wide variety of plugins.  Already we've implemented several long-requested features for FogBugz as plugins: Workflow, Custom Fields, Project Backlog, and CSV Export (built-in to FogBugz 7) are just the start!

We're also excited about the plugins under development that will start to push the architecture to its limits.  The Balsamiq Mockups plugin allows creating beautifully simple user interface mockups from inside FogBugz which can be attached to cases and wiki pages.  The Kanban Board plugin allows creating an Agile Kanban board with FogBugz cases, complete with AJAX drag-and-drop.  You can browse these plugins and many more at the FogBugz Plugin Gallery.

FogBugz is just getting started with plugins.  Stay tuned in the coming weeks and months for more and more feature-loaded plugins, along with expansions and additions to the plugin architecture that will allow developers to do more and more.  If you have an idea for a plugin that you'd like to see, you can even suggest it to the development community at the FogBugz Plugin Ideas uservoice site, and maybe somebody will take it and run with it!

Or, even better, stop waiting for  somebody else to add reverse-alphabetical, zebra-striped tag clouds and get started writing it yourself!  The FogBugz Developer Wiki has all the information you need to get started, and the Plugin Developer Discussion Group is a great place to get all of your questions answered.

A simple "Hello, World" plugin is only a few lines long


Categories: FogBugz

Tags:

Actions: E-mail, Permalink