Objective: Update Epic Link Status based on current status of Epic Link and current status of the Issue being transitioned
Problem:
Consider a simple workflow: To Do > In Progress > Done
If a story is in Done status, then is transitioned to To Do or In Progress AND the Epic Link is in Done Status, then update the Epic status to In Progress
Scenarios:
Scenario 1
Scenario 2
Attempted Solution used as a Workflow Post Function:
See Screenshot below w/ error I'm receiving. Any advice?
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.workflow.TransitionOptions
def ACTION_ID = 21 // Repoace with the ID of the Epic action to be taken
def EPIC_STORY_LINK = "Epic-Story Link"
def STATUS_NAME = "In Progress" //Target Epic Status
def issue = issue as MutableIssue
def workflow = ComponentAccessor.workflowManager.getWorkflow(issue)
def action = workflow.allActions.find { it.id == ACTION_ID }
//getting current workflow description
def wfd = workflow.getDescriptor()
def actionName = wfd.getAction(transientVars["actionId"] as int).getName()
log.debug("Current action name: $actionName")
//
if (!action) {
log.debug "No action with id $ACTION_ID found, for workflow $workflow.name"
return
}
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueLinkManager = ComponentAccessor.issueLinkManager
def epicIssue = issueLinkManager.getInwardLinks(issue.id).find {
it.issueLinkType.name == EPIC_STORY_LINK
}?.sourceObject
if (!epicIssue) {
return
}
//If the Story Current Status is Done and Epic Link Status is Done, then update Epic Status to In Progress
if (myIssue.statusObject.name =="Done" && epicIssue.statusObject.name == "Done")
{
transitIssue(epicIssue, ACTION_ID, user)
{
MutableIssue transitIssue (Issue issue, int actionId, ApplicationUser cwdUser) {
def issueService = ComponentAccessor.issueService
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.setComment("This Epic automatically moved to In Progress since a previously completed story was reopened.")
issueInputParameters.setSkipScreenCheck(true)
def transitionOptions = new TransitionOptions.Builder()
.skipConditions()
.skipPermissions()
.skipValidators()
.build()
def transitionValidationResult =
issueService.validateTransition(cwdUser, issue.id, actionId, issueInputParameters, transitionOptions)
if (!transitionValidationResult.isValid()) {
log.error transitionValidationResult.errorCollection
return null
}
issueService.transition(cwdUser, transitionValidationResult).issue
}
}
}
Without actually testing it, the following removes your compilation errors:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.workflow.TransitionOptions
def ACTION_ID = 21 // Replace with the ID of the Epic action to be taken
def EPIC_STORY_LINK = "Epic-Story Link"
def STATUS_NAME = "In Progress" //Target Epic Status
def issue = issue as MutableIssue
def workflow = ComponentAccessor.workflowManager.getWorkflow(issue)
def action = workflow.allActions.find { it.id == ACTION_ID }
//getting current workflow description
def wfd = workflow.getDescriptor()
def actionName = wfd.getAction(transientVars["actionId"] as int).getName()
log.debug("Current action name: $actionName")
//
if (!action) {
log.debug "No action with id $ACTION_ID found, for workflow $workflow.name"
return
}
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueLinkManager = ComponentAccessor.issueLinkManager
def epicIssue = issueLinkManager.getInwardLinks(issue.id).find {
it.issueLinkType.name == EPIC_STORY_LINK
}?.sourceObject
if (!epicIssue) {
return
}
//If the Story Current Status is Done and Epic Link Status is Done, then update Epic Status to In Progress
if (issue.status.name =="Done" && epicIssue.status.name == "Done"){
def issueService = ComponentAccessor.issueService
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.setComment("This Epic automatically moved to In Progress since a previously completed story was reopened.")
issueInputParameters.setSkipScreenCheck(true)
def transitionOptions = new TransitionOptions.Builder()
.skipConditions()
.skipPermissions()
.skipValidators()
.build()
def transitionValidationResult = issueService.validateTransition(user, issue.id, ACTION_ID, issueInputParameters, transitionOptions)
if (!transitionValidationResult.isValid()) {
log.error transitionValidationResult.errorCollection
return null
}
def transitionResult = issueService.transition(user, transitionValidationResult)
if(!transitionResult.isValid()){
log.error transitionResult.errorCollection
return null
}
}
I don't see any need to encapsulate the transition into a "transitIssue" method (that's what it looks like you were trying to do).
If you were insistent in doing that, the call to the method can't include the method.
Try this instead:
if (myIssue.statusObject.name =="Done" && epicIssue.statusObject.name == "Done")
{
transitIssue(epicIssue, ACTION_ID, user)
}
MutableIssue transitIssue (Issue issue, int actionId, ApplicationUser cwdUser) {
/* ... */
}
Thanks! I'll try it out and let you know how it goes.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Show up and give back by attending an Atlassian Community Event: we’ll donate $10 for every event attendee in March!
Join an Atlassian Community Event!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.