I have the below fields,
a) Bug environment
Value 1 - Production
Value 2 - Non - production
b) Root Cause
a few drop-down values
I wanna use a script that says, if Bug environment is 'production' and Root cause is NULL/empty. Then the bug cannot be moved to DONE , if its Non-production, then don't bother.
Sample code :
def rootcause = GetCustomFieldValue(issue, "customfield_10107");
if (issueType == "Bug")
{
if (rootcause == null || rootcause.isEmpty())
{
errors.add("Root Cause is required to accept this ${issueType}");
}
}
Any help on this, please. Thanks
Hi @Aisha M ,
My advice is to add a script validator in the transition to Done. Assuming bug environnement is a single select custom field and root cause is a multi select custom field, this should do the trick :
import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException
def customFieldManager = ComponentAccessor.getCustomFieldManager()
int bugEnvironmentId = 10000
def bugEnvironment = customFieldManager.getCustomFieldObject(bugEnvironmentId)
def bugEnvironmentValue = issue.getCustomFieldValue(bugEnvironment)
int rootCauseId = 10001
def rootCause = customFieldManager.getCustomFieldObject(rootCauseId)
def rootCauseValue = issue.getCustomFieldValue(rootCause)
if (bugEnvironmentValue != null && bugEnvironmentValue.getValue() == "Production" && rootCauseValue == null){
invalidInputException = new InvalidInputException("Root Cause is required to accept this " + issue.getIssueType().getName())
throw invalidInputException
}
Just update the custom field IDs.
Antoine
To add to this answer, if you want the error to appear next to the root cause field rather than at the top of the transition form, you can use a different signature for new InvalidInputException
def invalidInputException = new InvalidInputException(rootCauseId, "Root Cause is required to accept this " + issue.getIssueType().getName())
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry Thank you so much for the comment.
But for some reason, when I try to execute this, does not work, keeps loading and the status of the Bug remains as 'Ready to Accept" without showing a prompt that "Root cause required to accept a Bug in Production" (I filled as production and skipped the root cause, to test this out)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Aisha M ,
I just tried this script and it is working fine on my instance. Could you please tell me the exact types of these custom fields ? I am using Select List (single choice).
Also what are the logs displaying if you add
log.error("bugEnvironmentValue.getValue() : " + bugEnvironmentValue.getValue() )
log.error("rootCauseValue : " + rootCauseValue)
Antoine
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry My instance keep loading when I change the status of the Bug. And then the page gets timed out.
So, I tried adding the below simplified script in my already existing validator SCRIPT(Scriptrunner)
def defectRootCause = GetCustomFieldValue(issue, "customfield_10107");
if (issueType == "Bug")
{
if (defectRootCause == null || defectRootCause.isEmpty())
{
errors.add("Defect Root Cause is required to accept this ${issueType}")
}
}
Can you please help with the code inclusion, for adding if Bug environment (ID 13098) is PRODUCTION then defect root cause is required.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry In addition to my above comment, The Bug environment is a radio button field of values - Production & Non-Production , and the Defect root cause is a drop down field
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Aisha M ,
Radio buttons returns the same object as single select list, so you should be able to use getValue(). What do you mean by drop down ? Could you please go into Custom Fields and tell me the type of defect root cause ?
Also, may you please provide your full script so I can debug more easily ?
GetCustomFieldValue(issue, "customfield_10107");
is unlikely to work unless you have created a method inside your script.
Antoine
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry Defect root cause is a select list (single choice).
Below is a half of the code, hope it helps . . We just keep required field validators in the middle of the script & go on
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import org.apache.http.entity.StringEntity
import org.apache.log4j.Logger
import org.apache.log4j.Level
import groovy.json.*
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.opensymphony.workflow.InvalidInputException
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.view.CustomFieldParams
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.customfields.impl.CascadingSelectCFType
def log = Logger.getLogger("Shackles");
log.setLevel(Level.DEBUG);
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();
String currentUserId = "${currentUser.name}";
String currentUserRole = "";
String user = "Automation";
String pass = "noadminforsup";
String authHeader = "${user}:${pass}".bytes.encodeBase64();
def projectObject = issue.getProjectObject();
String projectName = projectObject.getName();
String projectKey = projectObject.getKey();
String issueType = issue.getIssueType().getName();
if (issueType == "Sub-task")
return;
def teamId = FindTeamId(projectKey, projectName, authHeader);
def map = new HashMap<String, String>();
def productOwners = new ArrayList<String>();
List<String> errors = new ArrayList<String>();
map = GetTeamMembers(teamId, authHeader);
for(item in map)
{
if (item.key == currentUserId)
currentUserRole = item.value;
if (item.value.contains("Product Owner"))
productOwners.add(GetUserDisplayName(item.key));
}
def acceptanceCriteria = GetCustomFieldValue(issue, "customfield_11800");
if (issueType == "Story")
{
if (acceptanceCriteria == null || acceptanceCriteria.isEmpty())
{
errors.add("Acceptance Criteria is required to accept this ${issueType}");
}
}
def defectRootCause = GetCustomFieldValue(issue, "customfield_10107");
if (issueType == "Bug")
{
if (defectRootCause == null || defectRootCause.isEmpty())
{
errors.add("Defect Root Cause is required to accept this ${issueType}")
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry I hope the above snippet helps . . I just want help with adding an ADD statement to the simplified script I had posted,
Like, If Bug Environment is PRODUCTION AND Defect Root Cause is EMPTY, then don't allow the bug to be Accepted (a status we have before DONE), if its NON PRODUCTION then no problem.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am a bit confused with your script. I guess you have created your own methods such as
GetCustomFieldValue(issue, "customfield_10107");
GetTeamMembers(teamId, authHeader);
? Because out of the box it does not exist. I am not sure what you are doing with your productOwners object but I guess it you are using it later in the script.
Anyway my advice would be to create a new validator in the transition for that part only (don't forget to replace the bug environment custom field id) :
import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException
def customFieldManager = ComponentAccessor.getCustomFieldManager()
int bugEnvironmentId = 10000
def bugEnvironment = customFieldManager.getCustomFieldObject(bugEnvironmentId)
def bugEnvironmentValue = issue.getCustomFieldValue(bugEnvironment)
int rootCauseId = 10107
def rootCause = customFieldManager.getCustomFieldObject(rootCauseId)
def rootCauseValue = issue.getCustomFieldValue(rootCause)
String issuetype = issue.getIssueType().getName()
if (issuetype == "Bug" && bugEnvironmentValue?.getValue() == "Production" && rootCauseValue == null){
def invalidInputException = new InvalidInputException("Root Cause is required to accept this " + issue.getIssueType().getName())
throw invalidInputException
}
And check in the transition that it executed without error. Also you can add some logs as I suggested above and check the log file when you are triggering the transition.
Antoine
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry Thank you so much for your constant help ! They didn't want the "If Production check", so I m just gonna be using the simplified script I had posted, as its working okay . . Anyway, Will be marking your reply as an ANSWER for helping someone with a similar requirement.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You are very welcome ! Glad to know that the problem was fixed to your likings.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Antoine Berry Hi . . Can you pleaseee have a look at my another query and give me your thoughts on that question. That would be so helpful.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Below you have something similar to what you are asking for.
please also check https://community.atlassian.com/t5/Jira-questions/Re-How-to-copy-a-custom-field-to-all-linkedissues-based/qaq-p/1020043/comment-id/326946#M326946
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.comments.CommentManager
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
// Get a pointer to the issue
Issue issueKey = issue
// Get the current logged in user
def CurrentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser() as ApplicationUser
// Get access to the Jira comment and component manager
CommentManager commentManager = ComponentAccessor.getCommentManager()
// Get the customField Escalation level and it's value
def myCustomField = customFieldManager.getCustomFieldObject("customfield_12500")
// Get the last comment entered in on the issue to a String
def comment = "This issue is: " + myCustomField.getValue(issue)
def issueManager = ComponentAccessor.getIssueManager()
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def issueLinks = issueLinkManager.getInwardLinks(issueKey.getId())
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def subOutwardElements = issueLinks.findAll { it.issueLinkType.any()}
//def subOutwardElements = outwardIssueLinks.findAll { it.issueLinkType.inward.concat("is blocked by")}
//log.warn("Before for loop issueLinks.size() " + issueLinks.size())
log.warn("Before for loop myCustomField.toString( " + myCustomField.toString())
// Check if the issue is not null
if(issueKey){
// if customField Escalation level has a value
if (myCustomField.getValue(issue) != null && myCustomField.toString() == 'Escalation level' ) {
if (subOutwardElements.size() >= 0) {
for (def i = 0; i < subOutwardElements.size(); i++ ) {
log.warn("sourceId: ${i} ")
def linkedIssue = issueManager.getIssueObject(subOutwardElements[i].sourceId)
log.warn("Issue link type with name linkedIssue: ${linkedIssue} ")
log.warn("Issue link type with name myCustomField: ${myCustomField.getValue(issue)} ")
// Create a comment on the issue
// commentManager.create(issueKey, CurrentUser,comment, true)
// Set the value of the custom field
linkedIssue.setCustomFieldValue(myCustomField, myCustomField.getValue(issue))
// Update the issue
ComponentAccessor.getIssueManager().updateIssue(user, linkedIssue, EventDispatchOption.ISSUE_UPDATED, false)
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.