Skip to content

Instantly share code, notes, and snippets.

@jtbonhomme
Last active October 26, 2016 12:14
Show Gist options
  • Save jtbonhomme/50765706150e85468d8292dee9d0c82a to your computer and use it in GitHub Desktop.
Save jtbonhomme/50765706150e85468d8292dee9d0c82a to your computer and use it in GitHub Desktop.
Perfoms Epic trasitions
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.workflow.WorkflowManager
import com.atlassian.jira.ComponentManager;
import com.opensymphony.workflow.loader.ActionDescriptor;
enableCache = {-> false}
def text = ""
// Performs transition to an actionId (ie status)
private boolean transitionIssue(Issue issue, int actionId, User user) {
boolean result = false;
IssueService issueService = ComponentManager.getInstance().getIssueService();
IssueService.IssueResult transResult;
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters();
TransitionValidationResult validationResult = issueService.validateTransition(user, issue.getId(), actionId, issueInputParameters);
result = validationResult.isValid();
if (result) {
transResult = issueService.transition(user, validationResult);
}
return result;
}
// Get actionId from its name
private int getActionID(Issue issue, String actionName) {
int result = -1;
WorkflowManager workflowManager = ComponentManager.getInstance().getWorkflowManager();
JiraWorkflow jiraWorkflow = workflowManager.getWorkflow(issue);
Collection<ActionDescriptor> cActionDesc = jiraWorkflow.getAllActions();
for (ActionDescriptor res : cActionDesc) {
if (res.getName().equals(actionName)) {
result = res.getId();
break;
}
}
return result;
}
// return epic target status according to issues linked statuses
private String getEpicStatus(List<Issue> issues) {
String epicStatusShouldBe = "NEW"
String firstStatus = ""
boolean isOnGoing = false
boolean isBlocked = false
boolean hasSameStatus = true
// check if all issues has the same status.
// If yes, the Epic should have the same status
// If no, if one issue is blocked, the epic is blocked
// If no issue is blocked and one issue is on going, the epic is on-going
// If no issue is blocked nor on going, the epic has the lowest status of its issues
issues?.find {curIssue ->
def status = curIssue.getStatusObject()
// first iteration
if( firstStatus == "" )
firstStatus = status.getName();
// compare next iterations ti the first one
if(firstStatus != status.getName())
hasSameStatus = false;
if( status.getName() == "BLOCKED") {
isBlocked = true;
epicStatusShouldBe = "BLOCKED";
}
if( status.getName() == "ON GOING") {
isOnGoing = true;
epicStatusShouldBe = "ON GOING";
}
if( status.getName() != "TERMINATED" && !isOnGoing && !isBlocked) {
if( status.getName() == "BLOCKED") {
epicStatusShouldBe = status.getName()
}
if( epicStatusShouldBe == "IN PROD"){
epicStatusShouldBe = status.getName()
}
if( epicStatusShouldBe == "DONE" && status.getName() != "IN PROD" && status.getName() != "BLOCKED"){
epicStatusShouldBe = status.getName()
}
if( epicStatusShouldBe == "INTEGRATED" && status.getName() != "IN PROD" && status.getName() != "DONE" ){
epicStatusShouldBe = status.getName()
}
if( epicStatusShouldBe == "READY" && status.getName() != "IN PROD" && status.getName() != "DONE" && status.getName() != "INTEGRATED"){
epicStatusShouldBe = status.getName()
}
if( epicStatusShouldBe == "NEW" && status.getName() != "IN PROD" && status.getName() != "DONE" && status.getName() != "INTEGRATED" && status.getName() != "READY"){
epicStatusShouldBe = status.getName()
}
}
if( hasSameStatus )
epicStatusShouldBe = firstStatus;
}
return epicStatusShouldBe;
}
// Services variables
SearchService searchService = ComponentAccessor.getComponent(SearchService.class)
User user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
IssueManager issueManager = ComponentAccessor.getIssueManager()
List<Issue> epics = null
def jqlSearchEpics = "project = RPP and issuetype = epic and resolution = Unresolved and key in (rpp-97, rpp-95, rpp-85)"
SearchService.ParseResult parseResult = searchService.parseQuery(user, jqlSearchEpics)
if (parseResult.isValid()) {
def searchResultEpics = searchService.search(user, parseResult.getQuery(), PagerFilter.getUnlimitedFilter())
epics = searchResultEpics.issues.collect {issueManager.getIssueObject(it.id)}
epics?.each {curEpic ->
def epicStatusShouldBe = "IN PROD"
List<Issue> issues = null
def jqlSearchLinkedIssues = "issueFunction in linkedIssuesOf(\"project = RPP AND issueKey = " + curEpic.id + "\")"
def epicName = curEpic.getStatusObject().getName();
text += curEpic.getKey() + " has status " + epicName + " (" + getActionID(curEpic, epicName) + "): "
parseResult = searchService.parseQuery(user, jqlSearchLinkedIssues)
if (parseResult.isValid()) {
def searchResultIssues = searchService.search(user, parseResult.getQuery(), PagerFilter.getUnlimitedFilter())
issues = searchResultIssues.issues.collect {issueManager.getIssueObject(it.id)}
epicStatusShouldBe = getEpicStatus(issues);
text += "should have status " + epicStatusShouldBe + " (" + getActionID(curEpic, epicStatusShouldBe) + ") ----- "
transitionIssue(curEpic, getActionID(curEpic, epicStatusShouldBe), user)
} else {
return "Invalid JQL: " + jqlSearchLinkedIssues
}
}
} else {
return "Invalid JQL: " + jqlSearchEpics
}
return text as String
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment