All feature requests, enhancements, configuration tasks, adminstration tasks, etc are represented in GitLab as issues. If a task does not have a related issue in GitLab, it does not exist as far as our process is concerned.

When a feature is proposed, an issue is created in an appropriate GitLab project. Some features have a natural project for them to live in. Generally this will be either the deployment or implementation project for a service. Issues which have no clear place to live may be placed in the generic DevOps administration project.

Issue life cycle

An issue will go through a number of states during its life.

State Label Description
Open No work has been done on this issue.
Claimed Someone has been assigned to this issue but work has not started.
Doing workflow::doing Work has started on this issue.
Review required workflow::review required The issue has been addressed and can be reviewed.
Needs testing workflow::needs testing The reviewer is happy with the code and the code now needs to be tested.
Rework workflow::rework The work associated with the issue needs to be modified, usually as a result of code review.
Blocked workflow::blocked Work cannot proceed on this issue. Usually because it depends on another issue or because we are waiting on a third party.
Done The issue has been closed.


Usually an issue will have a single assignee which is the person who has "claimed" the issue for themselves. Usually this is done immediately before starting work on the issue but occasionally we "pre-assign" people to issues if there is a clear reason for that person to tackle the issue.

Issue refinement

When written an issue may be very generic, e.g. "solve research administration in the University", or be very specific, e.g. "update Frobnicator 95 to Frobnicator 2000". A generic issue is useful to track whether a task has been completed but it can be too large and/or too general to estimate the work.

On the middle-Wednesday of a sprint we have a refinement meeting where we look at issues which have recently been added. The idea is to identify issues which can reasonably be done next sprint. If an issue is too large or too generic we try to break it down into smaller issues. Eventually we end up with a set of issues which:

  • Are small: they address a single bug or implement a single feature.
  • Are specific: they describe the work to be done in a manner which does not require further clarification.
  • Are achievable: they describe work which we believe we can complete.

We call these issues sprint ready.

Effort estimation

On the final Wednesday of a sprint we have an estimation meeting were we assign a time estimate to each issue.


We record issue estimates on GitLab by using the quick action /estimate. This allows us to quickly determine the estimated work for the current and upcoming sprints.

We score each issue on two axes. The first, effort, is measured in days and reflects our best estimate for how long the task would take if we knew exactly how to do it. This should factor in development time and testing but should not factor in uncertainty in how we address the issues.

The second axis is complexity and is unitless. We score this based on the following table.

Complexity Description
1 I know how to do this
2 Someone in the team knows how to do this
3 Someone in the world knows how to do this
4 This problem has never been solved before

The final estimate is formed by multiplying the effort and complexity.

Sprint scheduling

The sprint planner will take the issue estimates and the ad hoc priorities and schedule a sprint. We assume each member of the team contributes 8 days of effort per sprint. We reserve 2 days as "placeholders" for emergency issues so the total amount of time we have available when scheduling a sprint, ignoring leave, is (8 × number of team members) − 2. Usually we modify this estimate depending on the number of days a given team member is present for the sprint.