I forget to move tickets around the board when I’m supposed to. After working with 10+ ticketing systems for some 20 years, it’s still too alien to have to perform a manual step in a completely separate system at the same time as trying to concentrate on the development. So why not automate this process a bit?

This article is a brain dump for my future self to implement, and therefore makes a bunch of simplifying assumptions, glossing over a bunch of details and considerations like team size. Still, the central idea might be useful.

Assumptions

  • Tickets are tracked electronically, or you have a robot and sufficient time to automate your physical Kanban board 😉.
  • The ticket tracking system has a sane API.
  • Tickets all have a unique ID, so that you don’t have to do fancy heuristics to connect them to change sets.
  • You use feature branches. It would be possible to adapt this approach to trunk-based development, but it would probably require some rethinking and heuristics.
  • Each branch corresponds to exactly one ticket. This is doable if tickets are small.
  • Some work is not related to a specific ticket, and that’s OK. We have finite time, after all.

Discussion

Tickets are often created with just some hastily scribbled notes. This may be OK in a one-person team, but implicit knowledge can’t generally be inferred from such notes, so we probably want to make sure there’s separate “(not) ready [for an arbitrary developer to start working on without further context]” states. Only once the ticket is ready should anyone start working on it.

In standard “make the change easy, then make the easy change” fashion, feature branches mean that preparatory work such as refactoring should probably be in separate commits in the same branch as the actual feature. These commits should not be squashed when merging, since that makes reverts extremely painful.

Process

  1. Work starts when creating the branch1. This can be signalled by implementing a create-feature-branch Git alias. This alias would take just the ticket ID, then perform something like the following process:
    1. Download the ticket metadata. If it’s not in the “ready” state, either warn the user or abort, depending on the state and how strict you want to be with the process. For example, it’s probably not expected that a cancelled ticket moves into “in progress”, so any such attempt can probably be assumed to be a typo.
    2. Create a slug containing the ticket title and ID, in such a way that it’s easy to programmatically extract the ID from the slug. For example, a ticket with a title of “Alert on excess CPU use” and ID of “1234” might get a slug of “alert-on-excess-cpu-use-1234”.
    3. Create a branch with the name of the slug. As in, git branch SLUG DEFAULT_REMOTE/DEFAULT_BRANCH.
    4. Change to the new branch.
    5. Call the ticketing system API to change the ticket state to “in progress”.
  2. Create a draft merge request when pushing the first time. This could use the name of the ticket as the title. This shows how work is progressing, and should give the right idea about the fact that the branch is not ready to base other work on, because the commit history may change. Signalling that the history might change encourages atomic commits (as opposed to fix-up commits for linting issues) and a clean history through rebasing onto the target branch rather than merging from it.
  3. Move the ticket to “in review” when a merge request is no longer in draft, and/or when deployed to a user acceptance environment.
  4. Move the ticket to “in production” (often called “done”, which is misleading) when it’s been deployed to production.
  5. Move the ticket to “in use” when log monitors detect that the relevant code has been triggered.
  6. Move the ticket to “cancelled” if the branch is deleted before merging.
  7. Create a new ticket to remove the functionality when log monitors detect that the relevant code has not been triggered for a Long Time™. This might be too much work, but for a complex system it could be one way to keep the maintenance burden manageable.
  1. It might be simpler to implement a server-side hook to set the state to “in progress” when someone first pushes a branch with a ticket ID, but that pushes a lot of information-gathering much later into the process. Part of the appeal of the process above is that information is updated ASAP.