Hello!
I need some help about scripted post function. I want to fire an Action (ex: Sent to Review) as a Post Function another transition (ex: Integrate) if a complicated condition goes true.
I have some questions:
1, Is it possible to fire an Action (transition) as a post function of another transition.
I am writing you the whole situation and my expectation. If anybody has idea how to figure out the solution please answer me.
I want to fire automatic transitions on my parent issue depending on sub-task's status, different sub-task types and different statuses. All automatic transition has different condition concern to sub-task's types and statuses and the parent issue is must be in specified status.
Here is what is made:
import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.user.util.UserManager import java.util.logging.Logger; import com.atlassian.jira.bc.issue.IssueService import com.atlassian.jira.issue.IssueInputParameters public void doTransition(String statusId, int transitionId) { try{ Thread thread = Thread.start { sleep(1000); IssueService issueService = ComponentAccessor.getIssueService() UserManager userManager = (UserManager) ComponentAccessor.getUserManager() IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters.setStatusId(statusId); IssueService.TransitionValidationResult transitionValidationResult = issueService.validateTransition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), issue.id, transitionId, issueInputParameters); if (transitionValidationResult.isValid()){ IssueService.IssueResult transitionResult = issueService.transition(currentUser, transitionValidationResult); if (!transitionResult.isValid()) { transitionResult.errorCollection.errorMessages.each {log.error "Error Message: $it"} transitionResult.errorCollection.errors.each {log.error "Error: $it"} transitionResult.errorCollection.reasons.each {log.error "Reason: $it"} } } else { transitionValidationResult.errorCollection.errorMessages.each {log.error "Error Message: $it"} transitionValidationResult.errorCollection.errors.each {log.error "Error: $it"} transitionValidationResult.errorCollection.reasons.each {log.error "Reason: $it"} } } } catch (Exception e){ log.error(e.getMessage()); } } def subtasks = issue.getSubTaskObjects(); def cFieldValue = issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_22200")) // status before trigger def goToReproduction = false; def goToProcessing = false; def goToIntegrating = false; def goToVerifying = false; def goToConcluding = false; for (int i=0; i < subtasks.size(); i++) { def nextIssue = subtasks[i]; if (cFieldValue == 'Categorizing') { if (nextIssue.getIssueTypeId() == "13602" && nextIssue.getStatus()?.name != 'New') { goToReproduction = true break; } } else if (cFieldValue == 'Reproduction') { if ((nextIssue.getIssueTypeId() == "13603" || nextIssue.getIssueTypeId() == "13701") && nextIssue.getStatus()?.name != 'New') { goToProcessing = true break; } } else if (cFieldValue == 'Processing') { if ((nextIssue.getIssueTypeId() == "13603" || nextIssue.getIssueTypeId() == "13701") && nextIssue.getStatus()?.name == 'Closed') { goToIntegrating = true break; } } else if (cFieldValue == 'Integrating') { if ((nextIssue.getIssueTypeId() == "13507" && nextIssue.getStatus()?.name != 'New')) { goToVerifying = true break; } } else { } } if (goToReproduction){ doTransition("3", 21); } if (goToProcessing) { doTransition("4", 31); } if (goToIntegrating) { doTransition("5", 41); } if (goToVerifying) { doTransition("6", 51); } if (goToConcluding) { doTransition("7", 61); }
Does anybody have better solution then mine, without hack?
As I understand you have several transitions from single status of parent issue and you want automatically select correct one.
For this purpose I usually use respective conditions for transitions. When conditions are well organised user has the only button for transtion.
Bonus: I like to refactor code, here is refactored version of your code:
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue; import com.atlassian.jira.user.util.UserManager import java.util.logging.Logger; import com.atlassian.jira.bc.issue.IssueService import com.atlassian.jira.issue.IssueInputParameters public void doTransition(String statusId, int transitionId) { try{ Thread thread = Thread.start { sleep(1000); IssueService issueService = ComponentAccessor.getIssueService() UserManager userManager = (UserManager) ComponentAccessor.getUserManager() IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters.setStatusId(statusId); IssueService.TransitionValidationResult transitionValidationResult = issueService.validateTransition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), issue.id, transitionId, issueInputParameters); if (transitionValidationResult.isValid()){ IssueService.IssueResult transitionResult = issueService.transition(currentUser, transitionValidationResult); if (!transitionResult.isValid()) { transitionResult.errorCollection.errorMessages.each {log.error "Error Message: $it"} transitionResult.errorCollection.errors.each {log.error "Error: $it"} transitionResult.errorCollection.reasons.each {log.error "Reason: $it"} } } else { transitionValidationResult.errorCollection.errorMessages.each {log.error "Error Message: $it"} transitionValidationResult.errorCollection.errors.each {log.error "Error: $it"} transitionValidationResult.errorCollection.reasons.each {log.error "Reason: $it"} } } } catch (Exception e){ log.error(e.getMessage()); } } boolean goToConcluding = false; for(Issue subtask: issue.getSubTaskObjects()) { switch (issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_22200"))) { case "Categorizing": if (subtask.getIssueTypeId() == "13602" && subtask.getStatusObject()?.getName() != 'New') { doTransition("3", 21); break; } case 'Reproduction': if ((subtask.getIssueTypeId() == "13603" || subtask.getIssueTypeId() == "13701") && subtask.getStatusObject()?.getName() != 'New') { doTransition("4", 31); break; } case 'Processing': if ((subtask.getIssueTypeId() == "13603" || subtask.getIssueTypeId() == "13701") && subtask.getStatusObject()?.getName() == 'Closed') { doTransition("5", 41); break; } case 'Integrating': if ((subtask.getIssueTypeId() == "13507" && subtask.getStatusObject()?.getName() != 'New')) { doTransition("6", 51); break; } } } if (goToConcluding){ doTransition("7", 61); }
Hello Vasiliy!
Thank you very much for your answer and refactoring my code. I am quiet new at scriting, so this things always helps me a lot!
Yes, you understand well, I have several transitions from a single status and I want to fire the right one depending on sub-tasks type and status, but this transition I want to occur automatically.
More details about the situation.
I have a simple workflow for the parent ticket with one "hidden" status, named "Triggerd". I real process we don't use this status, this is just to help in automatize our complex workflow. In specified sub-task types, on the right transitions I added a post-function to call Trigger transition in parent ticket. (Trigger transition move to Triggered status). And I want my parent ticket to move toward to the right status is I fire this "triggering" transition in sub-task. I don't want to stay the parent ticket at "Triggered" status.
Easier, I want to automatize selecting and firing the right transition in parent ticket, launched with the specified sub-task transition.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Your solution seems to difficalt for me.
I think that it could be easer to have respective postfunction on sub-task transitions. In this case there is no any need to check sub-task type and status.
Try to reorganise you processes and onle then start writing code. If information about your processes is not secret, I could help you to organase it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I have never heard about respective post-functions. I will look for some information about it.
My process is not a secret but I think would be easier to contact each other on another platform not to disturb other users. Please contact me through my e-mail. mullnerbianka@gmail.com
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Respective is not some type of post-function. I mean appropriate or post-function which do what it should do
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I see......
I need to monitor the sub-tasks because in my process it is possible to have more than one sub-task typed for ex. Reproducing and the parent ticket can't go toward to the next Status (ex:Fixing) until all the Reproducing tickets are not closed.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think that it is better to add a postfunction on close transition:
import com.atlassian.jira.issue.Issue for(Issue subtask: issue.getParentObject().getSubTaskObjects()){ if((subtask.getIssueTypeObject().getName().equals("Reproducing")) && (subtask.getResolutionObject()) == null){ return; //we have at least 1 unresolved Reproducing issue } } //Code to trasit parent issue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.