JIRA – Epics all the way down …

Epics within Epics within …

One of the issues which I’ve encountered with JIRA is how to organise programmes of work which then contain sub-programmes, which might contain sub-sub-programmes … all the way down until you eventually reach the stories.

Within our JIRA service we have an issue link for an is implemented byimplements relationship between issues which can be used to construct this kind of hierarchy of relationship.

For example, within the SDLC Tools team we had a programme of work associated with the deprecation of the CQ2SVN integration between ClearQuest and Subversion (a programme of work necessary to deprecate ClearQuest). This work consisted of (items in blue are Epics):

  • Developing Subversion hooks to integrate with JIRA
    • Stories associated with the development work for the hooks
  • Developing a Release Note generation tool
    • Stories associated with the development work for the generation tool
  • Migration of each team with CQ2SVN integration to the new mechanism
    • Stories associated with the activity to migrate teams off CQ2SVN
  • Scheduling the shutdown of CQ2SVN
    • Testing and validation of the shutdown
    • Execution of the shutdown

This was done as a hierarchy of Epics shown below:



Pulling back all of the stories

Within the structure there are two separate sets of links:

  • is implemented byimplements
  • is Epic ofhas Epic

To find the full scope of the CQ2SVN Deprecation above, we need to pull back all of the stories from all of the Epics which are linked at any level to the top level Epic – we do this in two stages:

Finding Every Implementing Epic

The ScriptRunner plugin which we have installed on JIRA includes the function linkedIssuesOfRecursive() which we can use to perform this. This takes two arguments:

  • Subquery
  • Link Type

In our example above the top level “CQ2SVN Deprecation” Epic was CBST-689 – so to find every Epic implemented by this we can use the following JQL query:

issueFunction in linkedIssuesOfRecursive("issue = CBST-689", "is implemented by")

This is broken down into two parts:

We then saved this as a filter (we named it CQ2SVN – is implemented by) because we’re going to come back and re-use this later on.

Finding Every Story

Filters can be specified as part of a JQL query, therefore they can also be used in the subquery part of the linkedIssuesOfRecursive() function.

Making use of this function again to come up with to find every story which is part of these Epics we have the following JQL query:

issueFunction in linkedIssuesOfRecursive("filter = \"CQ2SVN - is implemented by\"", "is Epic of") OR issueFunction in linkedIssuesOfRecursive("issue = CBST-689", "is Epic of")

This is broken down into two parts:

  • Find all of the Epics returned by the CQ2SVN – is implemented by filter
  • Recursively return all of the issues linked to any of these which are linked via the is Epic of link


  • Recursively return all of the issues linked to the top level CQ2SVN Deprecation Epic via the is Epic of link

This returns a list of all 104 stories which contributed to the implementation of the CQ2SVN Deprecation Epic.

In order to re-use this query (e.g. on dashboards, etc.), we saved this as a different filter (we named it CQ2SVN Items).

For example, the filter could then be extended to only show the outstanding items:

filter="CQ2SVN Items" AND resolution IS EMPTY