Post Functions
This page describes several post functions that might be useful.
Each of these has examples of SIL code.
Required apps
Power Scriptsâ„¢ for Jira (server)
Level: BASIC
Making a HTTP request to an external system
An example of how you can add a configurable post-processing workflow function to a Jira instance.
It is able to pass workflow specific parameters in a HTTP request to a specified target host.
It is possible to configure a specific target URL and add custom parameters from the issue affected by the workflow transition.
Supported HTTP Methods are:
- GET
- POST
The following code creates a HTTP Get request to the "http://www.myserver.com/geturl" URL. It uses specific issue parameters in the header of the Request.
string [] headers = "Accept-Charset|utf-8|X-Powered-By|JJupin 2.5"; httpGet("http://www.myserver.com/geturl?project=" + project, headers); //note: you have to manually encode the values.
The following code creates a HTTP Post request to the "http://www.myserver.com/posturl" URL.You can configure its body parameters and its header like this:
string [] headers = "Accept|text/plain|X-Powered-By|JJupin 2.5"; string [] params = {}; params += "Summary"; params += summary; params += "Project"; params += project; params += "Created"; params += created; httpPost("http://www.myserver.com/posturl", headers, params);
where:
- Accept
- X-Powered-By
are the HTTP header fields
 and
- Summary
- Project
- Created
are the corresponding values from your issue.
Of course, you can use it with any HTTP header / parameter your endpoint requires.
Set assignee if reporter has a certain project role
Create a post function on the create transition in Jira with the following code:
string given_assignee = "mike"; string project_role = "Developers"; if(isUserInRole(reporter, project, project_role)) { assignee = given_assignee; }
The assignee is set to the given value("mike"), if the reporter has the specified project role("Developers").
This is useful when the reporter creates an issue and the project has more than one project lead.
Give it a name of your choice and let's create other post functions.
Control who can see individual issues within a project if reporter/assignee has a certain project role
In order to prevent some users to see individual issues within a project, you have to set the security level on an issue. Here is the documentation regarding the security level.
Create a post function on the create transition on the workflow assigned to the current project with the code below.
string security_level = "Documentation"; string project_role = "Analysts"; if(isUserInRole(reporter, project, project_role) || isUserInRole(assignee, project, project_role)) { security = security_level; }
The security level of the current issue is set to "Documentation" value, if the assignee, or the reporter has the specified project role("Analysts").
Assign to last role member
A SIL post function that assigns the current issue to the latest assignee (excluding the current one) who is a member of the specified project role:
string project_role = "Developers"; string[] previous_assignees = fieldHistory(key, "assignee"); for(number i = size(previous_assignees) - 1; i > 0; i -= 2) { string user = getElement(previous_assignees, i); if(user != assignee && isUserInRole(user, project, project_role)) { assignee = user; return; } } //Optionally you can check and consider also reporter if no previous assignee was found with the specified role if(reporter != assignee && isUserInRole(reporter, project, project_role)) { assignee = reporter; }
Increase value of numeric field
A SIL post function that increases the value of a numerical field by a given value:
number increment = 2.5; customfield_10000 += increment;
In the above example we assume that customfield_10000 is the id of a numeric custom field.
This can be used as a counter for example, for counting the times an issue has been reopened, by incrementing a number custom field with 1 on the Reopen Issue transition.
Set field value from user property value
A SIL post function that sets a field to the value of a user property:
customfield_10100 = getUserProperty(reporter, "country");
The reporter's country property value will be stored on issue in the text custom field with id customfield_10100.
Copy field value to parent
A SIL post function that sets a field value to the value(s) of the same field of the issue's parent issue:
if(!isNull(parent)) { parent.affectedVersions = affectedVersions; }
When executing the transition, the parent's affected versions will be automatically updated with the values set on the current sub-task.
Copy value from field to field
A SIL post function that copies the value(s) of a field to another field of the same issue:
description = summary;
When executing the transition, the description field will be updated with the text from summary.
Add field value to parent
A SIL post function that adds the value(s) of a multi-valued field into the same field of the issue's parent issue:
if(!isNull(parent) && size(fixVersions) > 0) { parent.fixVersions = arraysConcat(parent.fixVersions, fixVersions); }
When executing the transition, the fix versions for sub-task will be added to the parent's issue fix versions, if they don't already exist.
Set field value from parent
A SIL post function that sets a field value to the value(s) of the same field of the issue's parent issue:
if(!isNull(parent)) { components = parent.components; }
When executing the transition, the components for current sub-task will be set to the values of parent's issue components.
Set issue security from user's project role
A SIL post function that sets the issue security level based on a project role to which the current user belongs:
string PROJECT_ROLE = "Developers"; if(isUserInRole(currentUser(), project, PROJECT_ROLE)) { securityLevel = "Internal"; } else { securityLevel = "Anybody"; }
This post function can be used on the Create transition to set a different issue security level depending on whether the issue is being created by a developer or by any other user.
Transition parent issue
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
A SIL post function that triggers a named transition on the parent issue of the current sub-task:
string TRANSITION_NAME = "Start Progress"; if(!isNull(parent)) { autotransition(TRANSITION_NAME, parent); }
When executing the transition on sub-task, the "Start Progress" transition will be triggered on the parent issue, if this transition is valid for the current status of the issue.
Sending a custom email
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
A SIL post function that sends a custom email. For example, the reporter of the issue wants to be notified when the assignee resolves the issue. You can do this with the following code:
sendEmail(userEmailAddress(assignee), userEmailAddress(reporter), {}, "Issue resolved", "bodyTemplate.tpl", "en_US", key, "solution.txt");
The bodyTemplate.tpl contains the message body. In our example the bodyTemplate.tpl contains the following:Â
Hello $recipient$! I just resolved the issue: $summary$. I spent $timeSpent$ for resolving it. I attached the solution I found to resolve the issue. Thanks, $sender$
This sends an email from the issue assignee to the reporter and attaches the solution.txt file from the issue to the email.
Info
For more information about email templates, see Mail configuration.
Copy a parsed text to a field
Description of issue is set with a text automatically generated in the moment of issue creation:
description = "Current issue of type " + issueType + " was created on " + created + " by " + userFullName(reporter) + " in project " + project + " with the following summary: '" + summary + "'.\n" + "It affects versions " + (string)affectedVersions + " and is expected to be resolved on " + dueDate + ".";
A customized text is added as a comment at the moment of issue closing:
string USER = currentUser(); string COMMENT = "Closed on " + updated + " by " + userFullName(USER) + " with fixed versions " + (string)fixVersions + "."; addComment(key, USER, COMMENT);
Copy issue labels to a custom field:
customfield_10000 = labels;
Adding and removing single or set of items from multi valued fields
Adding components in subtasks to components in main issue:
string[] subtasks = subtasks(key); for(string subtask in subtasks) { components = arraysConcat(components, %subtask%.components); }
Removing reporters of linked issues from a Multi User field called Team:
string[] linkedIssues = linkedIssues(key); for(string issue in linkedIssues) { Team = deleteElement(Team, %issue%.reporter); }
Combining the values of several Multi User picker fields:
Team = arraysConcat(Team, UsersA); Team = arraysConcat(Team, UsersB); Team = arraysConcat(Team, UsersC); for(string user in arraysConcat(UsersD, UsersE)) { deleteElement(Team, user); }
In the above example we set a multi-user picker field Team with the combined values of three multi-user picker fields UsersA, UsersB, UsersC minus the values of other two multi-user picker fields UsersD and UsersE.
Mathematical and date-time expression calculator
Getting the number of selected values from a custom field of type Multi Select in a numeric custom field:
Number = size(MultiSelectList);
where Number is the name of a numeric custom field and MultiSelectList is the name of the Multi Select custom field.
Updating Due Date with respect to current date (eg adding 2 days):
dueDate = currentDate() + "2d";
Setting total time spent by adding current date-time - date-time of last update:
timeSpent += currentDate() - updated;
Set a field as a function of other fields
Setting a custom field called Urgency from issue Priority and another numeric custom field called Impact.:
Urgency = Impact + priorityId;
Set a field from a set of rules based on regular expressions
Changing issue priority depending on issue description:
string TEXT = "REPORTEDPRIORITY="; string REGEX = ".*\b" + TEXT + "[1-5]\b.*"; if(!matches(description, REGEX)) { logPrint("DEBUG", "Description doesn't contain reported priority in right format."); return; } number index = indexOf(description, TEXT) + length(TEXT); //starting index of priority id string substr = substring(description, index, length(description)); index = indexOf(substr, " "); if(index < 0) { index = length(substr); } priorityId = substring(substr, 0, index);
In the above example we use a string in the issue description to alter the issue priority upon issue creation. The description must contain a string of form REPORTEDPRIORITY=1 for fetching the priority id.
We make use of the SILâ„¢ routines matches, indexOf, length and substring. More useful string routines can be found in the String routines section.
Setting field based on reporter's email:
string EMAIL_REGEX = ".*@gmail\\.com$"; if(matches(userEmailAddress(reporter), EMAIL_REGEX)) { Defect = "Development"; }
The customer field Defect is a drop down with the values: None, Production, and Development, with Production as the default value.
The Defect value changes during the creation transition to Development if the reporter's email address matches a '@gmail.com' email address.
Setting watchers depending on the value of a custom field:
string CUSTOMER_REGEX = ".*\bBT\b.*"; for(string user in Customers) { if(matches(userFullName(user), CUSTOMER_REGEX)) { watchers = addElement(watchers, user); } }
In the above example, if in the multi user picker Customers custom field there are selected users which contain the value "BT" in their full name, these users are set as watchers upon creation.
Setting a custom field (User Picker) based on the value of another custom field (Text Field):
string COUNTRY_NAME = "Germany"; if(contains(Country, COUNTRY_NAME)) { User = "Person1"; }
In the above example, if text custom field Country contains Germany it sets the User field to Person1.
Setting a field's default value based on other field
In the below example, we have a custom field called Billable which is of type Radio Button. This field is set to 'No' if the issue type is 'Bug' and is set to "Yes" for any other issue type.
if(issueType == "Bug") { Billable = "No"; } else { Billable = "Yes"; }
Set due date to current date at issue creation
A SILâ„¢ post function that sets the due date to current date at issue creation, if no value was specifically set for the due date:
if(isNull(dueDate)) { dueDate = currentDate(); }
Setting assignee based on issue type and components
In the below example, if issue type is Bug, and it has component component1, the issue is assigned to user1, if it doesn't have component1 it is assigned to user2, and if issue type is not Bug it is assigned to user3.
if(issueType == "Bug") { if(elementExists(components, "component1")) { assignee = "user1"; } else { assignee = "user2"; } } else { assignee = "user3"; }
Assign an issue to a reporter or a user depending on the project key
A SILâ„¢ post function for assigning an issue to user tester if project is TST, or assign it to the issue reporter otherwise:
if(project == "TST") { assignee = "tester"; } else { assignee = reporter; }
Turn issue unassigned when assigned to project leader
A SILâ„¢ post function that turns an issue unassigned if it is assigned to the project leader:
if(assignee == projectPM(project)) { assignee = ""; }
Format text value of a custom field
Setting a text custom field with the formatted value of due date:
string FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; customfield_10000 = formatDate(dueDate, FORMAT);
customfield_10000 = formatNumber(123456789 ,"###,###.###");
Add a comment to all blocked issues when this issue is transitioned
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
Adding a comment on behalf of the current user, to all blocked issues by the current issue transitioned:
string COMMENT = "Blocking issue " + key + " was transitioned."; string[] issues = linkedIssues(key, "Blocks"); for(string issue in issues) { addComment(issue, currentUser(), COMMENT); }
Automatically adding or removing watchers from a workflow transition
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
Setting current user as a watcher for the current issue:
watchers = addElement(watchers, currentUser());
Similar, you can remove the current user from the list of watchers during transition:
watchers = deleteElement(watchers, currentUser());
Create issue link
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
A SIL post-function that links the current issue to another issue by the Relates issue link type:
linkIssue(key, "TST-123", "Relates");
Close sub-tasks and duplicated linked issues when current issue is closed
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
A SIL post-function that closes all subtasks and duplicated issues for current issue when close issue transition is triggered:
string[] issues = arraysConcat(subtasks(key), linkedIssues(key, "Duplicates")); for(string issue in issues) { autotransition("Close Issue", issue); }
Set/Read user property
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
A SILâ„¢ post-function that sets the "country" property for the current user and puts it into a text custom field with id customfield_10100:
string USER = currentUser(); setUserProperty(USER, "country", "Romania"); customfield_10100 = getUserProperty(USER, "country");
Copy a cascading select custom field to a simple text custom field
A SILâ„¢ post-function that copies the string representation of a cascading select custom field value with name "Cascade" into a text custom field with id customfield_10100:
customfield_10100 = Cascade;
The value displayed will be of form parent1|child1.
Fast-tracking (auto-transition) an issue through another action if a condition is true
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
Using this you can effectively have multiple start states for a workflow, with the initial state depending on, for example priority, reporter, or whatever.
This SILâ„¢ post-function will automatically transition an issue if the provided condition holds true.
For example, if all new Critical priority issues should go to the Change Control Board for approval when the issue is created, this can be achieved with the following SILâ„¢ post-function:
if(priority == "Critical") { autotransition("Ask For Approval", key); }
Auto-transition parent when all sub-tasks are resolved
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
Put this SILâ„¢ post-function on the sub-task workflow on transitions where the workflow could be set, typically Resolve Issue. If all sibling sub-tasks are resolved this will transition the parent issue using the provided action (eg Resolve Issue):
if(isNull(parent)) { return; } string[] subtasks = subtasks(parent); for(string subtask in subtasks) { if(%subtask%.status != "Resolved") { return; } } //all sub-tasks are resolved so we can transition the parent autotransition("Resolve Issue", parent);
Fire an event when condition is true
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
This SILâ„¢ post-function can be used for conditional notification of only high priority issues for instance:
string[] PRIORITIES = {"Major", "Critical", "Blocker"}; string EVENT = "Critical Issue Created"; if(elementExists(PRIORITIES, priority)) { raiseEvent(EVENT, key, currentUser()); }
In the above example we assume that the event "Critical Issue Created" was added to the list of Jira events, sending mail notifications to the project lead for example.
Clone an issue and link on transition
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
Yes, this is available in other places, but this method offers a lot of flexibility (at the expense of a fancy GUI).
Clones the current issue to a new one and links it with the given link type name (eg Cloners, Duplicate etc). All system and custom fields are copied from the source issue.
If you want to override some of the field values rather than have them inherited from the source issue you can set their values after calling the cloneIssue routine.
The following SILâ„¢ post-function clones the current issue, creates a Duplicate link type between the two issues, and sets the summary for the cloned issue:
string LINK_NAME = "Duplicate"; string clonedIssue = cloneIssue(key, LINK_NAME); %clonedIssue%.summary = "This is a clone of issue " + key + ".";
The post-function should be placed immediate after the function: Re-index an issue to keep indexes in sync with the database.
Create one or more sub-tasks on transition, and optionally reopen existing sub-tasks
Availability
This feature is available for the Jira server deployment option only. We plan to add it to the Cloud version in the near future.
This SILâ„¢ post-function function can be used to create several sub-tasks.
For instance, if you have an issue type that requires approval by two groups you might create a sub-task to represent each approval.
We can use this function to create two sub-tasks when parent is resolved, so that two departments can give approval. If a matching sub-task already exists it will be reopened for approval.
string[] SUMMARIES = {"First sub-task for approval", "Second sub-task for approval"}; string[] subtasks = subtasks(key); for(string summ in SUMMARIES) { boolean exists = false; for(string subtask in subtasks) { if(%subtask%.summary == summ) { autotransition("Reopen Issue", subtask); exists = true; } } if(!exists) { createIssue(project, key, "Sub-task", summ); } }