The Problem

One of the challenges that I encountered this week was the need to include Advanced Roadmaps plans in a Jira DC to Cloud migration.  As you may be aware, JCMA gives you the option to either migrate ALL plans, or none of them.  There is no facility for selectively adding plans.  This is a problem because the client instance has 1200 Roadmaps plans, and trying to add that many plans to a migration causes JCMA to crash.

I set out this week to build the foundations of what I’m calling the Roadmaps Insight Tool.  The first version was intended to simply list every Roadmaps plan in an instance, and list each of its data sources (project, board, or filter). 

The resulting dataset is useful in a number of ways. First, it gives transparency to a part of Jira that is otherwise quite opaque.

Second, it indicates which data sources on each plan are invalid; typically this is because the referenced data source no longer exists.  A Jira administrator wanting to do a cleanup of the Roadmaps Plans could easily base that cleanup on this information.

Third, in the case of this particular client it allows us to


This script retrieves all the members of a supplied Confluence group, and then retrieves the timestamp of the last time that user logged in to Confluence.

The Code

As you can see from the code below, we’re working with three classes.  The usual Component Locator, the Login Manager, and the Group Manager.

After telling the Component Locator to fetch the Login Manager and Group Manager, we feed the name of a group to the getGroup() method of the Group Manager.  This returns a group as an object.

We also need to define an array that will hold our results. This is because the ScriptRunner console doesn’t easily provide output; you can’t simply throw in a System.out.println().   If you try to use the log as output, it truncates after 300 results.  Instead we need to add the results to an array, and then return the array at the end.

The group object we created is passed to the getMemberNames() method of the group manager, which unsurprisingly returns the names of group members.

Next a for-each statement takes each user in the group and uses the getLoginInfo of the Login Manager to get the login information of each user.

Finally, within


There are two types of permissions at the Space level in Confluence: Space permissions, and Page permissions.

Page permissions are much simpler than Space permissions, for the simple reason that there are only TWO types of Page permission: VIEW and EDIT.

Getting Permissions From a Page

Simply retrieving the permissions of a Page is pretty simple. As you can see in the code below, you need only fill in a view variables: the page ID, and the type of Permission you’d like review.

 import com.atlassian.confluence.pages.PageManager
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.user.UserAccessor

def userAccessor = ComponentLocator.getComponent(UserAccessor)
def pageManager = ComponentLocator.getComponent(PageManager)
//Define the user accessor and the page manager

def currentPage = pageManager.getPage(83591282)
//Use the page manager to get a specific page

def editPermissions = currentPage.getContentPermissionSet(ContentPermission.VIEW_PERMISSION)
//Define the type of permissions to be returned

editPermissions.getUserKeys().each{names -> 
//For each person with the type of permissions
    //Take the user key and user it to fetch the name of the associated user


The page ID of any Confluence page is available under Page Information, under the ellipses in the top-right corner:

In this case the Page ID is 83591282.  The other piece of information that the