Administration



Jira system admins have to do a lot within larger companies and cannot take care about individual projects out of hundreds. Therefore, you can setup and configure all necessary sign-off/approval-rules for my app "Group Sign-Off/Multi-Approvals for Jira" as project administrator, now: such rule for sign-off/approval will be stored as a default value within a new context of the related custom field for the maintained project only. Additionally, all screens will be adjusted to also contain this Group Sign-Off field except for the screen of the issue-create-operation.








Global settings

Within the app's global configuration, you can specify some overall behaviors/features as shown below:

As a system admin, you can reach that panel by clicking on the button "Configure" of the expanded section "Group Sign-Off for JIRA" on your Jira page "Manage apps".



Create additional customfield(s)

Please create any many new customfields of type "Group Sign-Off" as you need, like "Steering Committee", "Product Board" etc. Within this documentation, I am focussing on one new customfield named "Sign-Off". If you are not familiar with creation of new customfields, please have a look at the Atlassian documentation for this standard feature of JIRA.

In order to get the related unique ID of your new customfield, please click on the "configure" menu item as visible on the screenshot.

Within the URL, you will find the unique ID of your customfield as parameter, here: 10100. Please write it down to remember. You will need it while configuring listeners later.

You have to determine, who is allowed to make a decision. Using the feature of setting a default value of a customfield, you can define it once and it will be taken over while creating a new issue automatically.

A definition of a decision is divided into two parts and stored as value within the related customfield:

  • the list of responsible users being able and allowed to decide and

  • a rule to determine the final result of the decision.


The list starts at the first character, first line with the login name of the responsible user: one user per line. Each line has to be terminated by a line-break. If the login name is unknown, it will not be displayed on the screen. The list of users end with a blank line for a better overview.

The rule for the decision starts with "sign-off=" followed by a boolean expression. Internal validation of the rule will be done by replacing all login names by their related decisions (sign-off = true and decline = false, pending = nothing). As soon as this rule results in a final TRUE or FALSE, it triggers the configured listener (see below). Having no individual decisions at the beginning or necessary pending ones, the result cannot be determined and nothing happens. The boolean expression can contain brackets "(" and ")" as well as "AND" and "OR" to describe the relationship of individual decisions. If the IT-boss or her/his representative can decide, one of both sign-offs is enough, and the business product owner has to sign-off as well the rule would be like: (boss OR representative) AND productOwner.

Simple Example of a definition

fpolscheit
representative

sign-off=(fpolscheit OR representative)

 If you want to put additional information in front of the user name, you can add this as comment straight after the user name without any spacing and enclosed by /* and */. Attention: you have to use the combination of name and comment as a unique identifier within the sign-off rule. Background: you may have different roles and act in different contexts.

Simple Example with additional user infos

fpolscheit/*Manager*/
representative/*Alternative Voting by*/

sign-off=(fpolscheit/*Manager*/ OR representative/*Alternative Voting by*/)











Dynamic Rule(s) for more complex but flexible approaches

Instead of explicitly declaring a list of users and a sign-off rule using boolean algebra, you can specify a dynamic rule coded in JavaScript and using provided helper functions, which extract the users out of referred other custom fields like single- or multi-user pickers, etc. A dynamic rule MUST start with a first line just containing "// conditional rule". Then, users and a rule have to be defined as described below.

The reserved words in blue within the following complex example are mandatory within a dynamic rule!
Within a condition, you can use all methods provided by JIRA's issue API. The helper object provides the following methods:

  • contains(collection, string)

  • contains(collection, id as number)

  • getCF(issue, customfieldName)

  • getCFms(issue, customfieldName) to retrieve a customfield's value in milliseconds

  • getUsersByCustomfield(issue, customfieldName, operand) to retrieve a (list of) user(s)

  • getUsersByProjectRole(issue, JiraProjectRoleName, operand) to retrieve a list of users

  • getUsersByGroup(issue, JiraGroupName, operand) to retrieve a list of users

  • getIssueByCurrentKey(issueKey) - available since version 2.8

  • concat(list, operand) to append a list of users using logical operand like "AND" or "OR" within a rule definition and "," within user definition

  • log(data) to write data into JIRA's logfile.

If you are using getUsersByCustomfield(), getUsersByProjectRole(), getUsersByGroup() the name of the referred element (custom field, project role or group) will be displayed in front of the retrieved user name since Group Sign-Off version 1.4.0.



Complex Example with different syntax: use a customfield (multi-user or user picker) to dynamically specify voters

// conditional rule

users =""+helper.getUsersByCustomfield(issue,"Board Members",",");
rule =""+helper.getUsersByCustomfield(issue,"Board Members","OR");



Please use the exact syntax above for dynamically specifying the list of user(s) based on the referred custom field. Users must be a comma separated list, that why the operand is a comma. The rule must be a sequence of users, concatenated by a boolean operand (AND or OR). By the first voting, the content of the customfield, referenced by name as parameter, will be taken over and the members will become a fix list.

Instead of using the custom field's name, you can also use it's ID: please put that number into the quotes like "10023" instead of "Board Members".



Or you can get the value of a cascading-select-customfield and determine the deciders and their logic per field value:

Within this sample, the custom field named „myCascadingSelection“ has got the options A-1, A-2, B-I, B-II …



You can also access the following functions of an issue (similar to the functions officially provided by the Atlassian Java API):

  • issue.getReporter()

  • issue.getPriorityObject()

  • issue.getFixVersions()

  • issue.getComponentObjects()

Within the following sample, the issue's reporter is automatically retrieved and used as a decider this for approval:



Often, you do not want to see a group sign-off field and its approvals through the complete life-cycle of an issue: you can limit displaying a group sign-off field only if its issue is within a certain status.



Suppose you use multiple custom fields to retrieve all users, who have to decide all together: in this case, you have to concatenate the custom fields' content and use a logical operator within the dynamic rule. The sample below illustrates a proper definition.

All members of the custom field "Managers" will be appended but if there is at least one user, only.
BUT: this rule works fine as long as the custom field "Board Members" is not empty! In this case, the user list would start with a leading "," as a result of the appended/concatenated managers, which forces a syntax error. To avoid this, ensure that users and rules are not empty when appending data by calling the function concat() or get rid of leading operators afterward, alternatively. This second approach is used within the following sample:

Since Group Sign-Off version 2.8, you can access an issue's fields a bit easier, just using Javascript-llike JSON-notation like issue.status.name.

Or you can get the value of a single-select-customfield and determine the deciders and their logic per field value:



Or you can get the value of a cascading-select-customfield and determine the deciders and their logic per field value:

Within this sample, the custom field named „myCascadingSelection“ has options A-1, A-2, B-I, B-II …

 

The following code sample is a generic template to concat all members of referenced custom fields (single- or mutli-user pickers) as well as referenced Jira group(s):

 

Advanced feature for experienced power-user:

DEPRECATED due to security aspects and removed in Group Sign-Off version 2.8:

  • in addition to the object issue, you can read other issues rather than the current issue by using all methods of issueManager (click to jump to Atlassian's API docu) since app version 2.5.0 of Group Sign-Off for Jira Server/DataCenter. Since Group Sign-Off version 2.5.9, the methods of issueServiceissueLinkManager as well as user are also available.

Using these advanced features, you can configure suitable solutions for even more complex business scenarios.

INSTEAD, please use:





Pay attention: using a dynamic rule, it's resulting set of deciders will be automatically turned into a static equivalent by the first decision for integrity reasons!

Background information: if someone has voted (declined or signed-off) and the members of a decision would be changed later, you can manipulate the total result by removing deciders with unwanted votes or add additional deciders. To avoid this, an automatic transition into a fix set of deciders will be done together with the first vote.

Additional Options

Additional options can be added at the end of the definition like shown below.
ATTENTION: put an option per line and do not terminate by a semicolon.

Vote/decide multiple times revoking prior one

  • optionOnce=false|true(is default) : decide and reverse decision multiple times if set to false

Vote/decide multiple times revoking prior one - but limited to revert declines, only

  • optionRevertDeclines=true|false(is default): decide and be able to reverse declines later, multiple times if set to true!

Disable delegation of decisions

  • optionDelegation=false|true(is default) : prevent from delegation by deciders (available in v1.4.2.2 for JIRA 6)

Confirm decision by entering password again (re-authenticate)

  • optionReAuthenticate=true : require re-authentication by entering the user's password again to confirm (available since v1.4.7 for JIRA 7)

Disable forcing a comment if having declined

  • optionNoCommentIfDecline : by default, if a decider declines, a comment is forced to justify, but using this option, it is ignored

Overwrite standard behavior to reload an issue after deciding

  • optionNoReload : by default, an issue is reloaded after deciding to properly display its status etc., which may have changed by that decision by configured listeners or workflow post functions in the background.

Disable displaying individual users

  • optionDisplayNoUsers : by default, all users being identified as deciders are displayed including their voting, but using this option these details are omitted:
    As admin, you will see all users' decisions independent from this option setting, so that you will get all necessary information for justifications if a result is regarded in doubt.
    As decider, you will see just your own decisions or both buttons "sign-off" and "decline".
    As normal user, you will see each role (like the name of the referenced customfield or project role in case of dynamic rules) and their sum of decisions including related timestamps but without details about individual deciders and their concrete decisions.

Display decision buttons for deciders only if their decision has got an immediate and direct effect on the total result

  • optionDecisionWithEffectOnlyby default, all deciders will see the buttons for declining or signing off. If you want to reduce that just for deciders, whose decision has got an immediate effect on the total result then use this option (available since v1.6.6) depending on the complexity of your dynamic rule. In that case, a decline as well as a sign-off decision of the current decider will be simulated: if that forces a change of the total result, e.g. switching from "pending" to "signed-off" or "declined". If your dynamic rule contains e.g. "(user1 AND user2)", then it does not make sense as user1's decision will have no effect until user2 has signed-off. So, usage highly depends on your sign-off rule for specific cases!

Option for "maybe/uncertain" (available since version 2.8.6)

  • optionMaybe=true : allow voting "maybe/uncertain" as an alternative for "sign-off/approve" and "decline" to indicate the necessity of e.g. additional information and to differentiate from "pending".

  • optionNoCommentIfMaybe : by default, if a decider clicks on "maybe", a comment is forced to enter what information is missing for a decision, but using this option, it is ignored

Force sequentially voting, one after the other, instead of parallel (available since version 2.8.19)

  • optionSequentially : in the sequence of defined users, one after the other must decide.
    Attention: This feature behaves differently than the Jira Cloud’s app version! In Jira Cloud, you can configure far more complex scenarios by defining multiple users and related rules per step of a larger sequence.

Example(s) of using an option within the rule definition:









Re-authenticate by entering password to confirm decision if configured as option.







































Special Function(s)

check(param1, param2, param-3, ..., param-n) for a certain amount of specified decisions: at least x deciders …

with param-1: Boolean value TRUE or FALSE, whereas true indicates sign-off and false indicates decline
param-2: threshold, resp. minimum amount of decisions as specified within param1 to return the value of param1, otherwise this function will return null
param-3, ..., param-n: comma-separated list of deciders





If at least one decider declines, the sign-off will be "declined" or if at least two deciders have voted for sign-off, the result will be "signed-off".

Based on 3 possible results of function check(null, true, false), the sequence of both function calls combined with OR is important: if you change both, it will not work properly! Based on boolean logic, false OR null results in null, whereas null OR false results in false which is what you would like to get. So, the check for declined votes via check(false,...) has to be the second part after the OR-connector.

A more complex sample combines the check-function with other dynamic helper-functions retrieving sets of deciders: at least 2 deciders out of the project roles "Developers" and "Administrators" have to sign-off, so that this rule switches into the state "signed-off". But if 1 decider declines, it results into "declined", immediately.

Expanation: using a dynamic rule, that rule must get a string in quotes like rule = "check(true, 2, x, y, z) OR check(false, 1, x, y, z)", whereas x, y, z is build by helper-functions like a concat of getUsersByProjectRole().

 

wait_for_all( ... ): no straight-through processing

with a list of related deciders as comma-separated params as shown within the sample below: expand your sign-off rule by prepending a call to the function wait_for_all() if you want to overrule the default behavior of switching into the final state as soon as possible.

Using a dynamic rule, you have to prepend a call to "wait_for_all()" by concat your original rule like illustrated within the following sample:

Sample: Conditional rule using the function "wait_for_all()"

// conditional rule users = ""+helper.getUsersByCustomfield(issue,"Approvers",","); rule = "wait_for_all(" + users+ ") " + helper.concat(helper.getUsersByCustomfield(issue,"Approvers","AND"), "AND");

 

majority( ... ): the final result is the majority decision

with a list of related deciders as comma-separated params, as shown in the sample dynamic rule below: as soon as the majority of all deciders have either signed off/approved or declined, this becomes finally signed off resp. declined and will not wait until all deciders have voted to get the best straight-through processing (the pending decisions have no effect and are irrelevant, then).

Sample: Conditional rule using the function "majority()"

// conditional rule users =""+helper.getUsersByProjectRole(issue,"Board Members",","); rule = "majority(" + users + ")";

You can also combine multiple special functions like: wait until all deciders have voted and set the final result to the majority one …

// conditional rule users =""+helper.getUsersByProjectRole(issue,"Board Members",","); rule = "wait_for_all(" + users + ") AND majority(" + users + ")";



Create additional listener(s) for automatic workflow transition(s)

You can add multiple listeners to define a switch within your workflow. In case of a signed-off issue, the automatically executed workflow transition should be different from the one in case of declining that issue. As soon as enough individual decisions have been done to determine the final result of the overall decision, these listeners will execute the specified workflow transition immediately like JIRA's event system. Nobody has to check decisions manually!

Within admin mode, please select "system -> advanced -> listeners" in order to insert a new listener. The class name must be de.polscheit.jira.plugins.listener.WorkflowAutoTransition whereas the name of the listener can by as you want.

















Since version 2.7.6 of Group Sign-Off, you can configure listeners which trigger the related workflow transition if all specified Group Sign-Off fields are all together within the referenced, final state "signed-off" or "declined": see screen copies on the right, too. To determine the overall result, all final decisions of these multi-fields are aggregated using AND-logical operations



After having created a new listener, you must edit it: just click on the related button on the right side of the listener.
You must specify three parameters:

  • customfield ID: please enter the ID (see above)

  • decision result: please enter the expected result to trigger this listener as signed-off or declined

  • transition ID: please enter the ID of the workflow transition, which has to be executed in case of matching the decision result as defined above.


Attention: please take care, that your IDs exist and that the specified workflow transition can be executed within your workflow sequence.
Also, do not block such transition by any Condition other than "Group Sign-Off: Blocking transition" (block this transition for all but specified user, like 'technical-user' only.)!



In case of any problem, the listener cannot execute it. Therefore, I recommend to test your settings carefully!

Modify your workflow(s) with new Condition(s)

At the point of time when a group decision shall happen, it does not make sense to click on the related button and continue the workflow without synchronisation with the result of the decision. So, you have to block the further processing by adding a workflow condition "Group Sign-Off". 

You have to specify the customfield, the workflow condition checks if the result of the rule is equal to the specified value: in that case, the related workflow transition will be visible and executable by a permitted user.

Using the blocking condition "Group Sign-Off: Blocking transition", please enter "technical-user" as name into the input field as shown below: automatically, the GSO listeners are executing a sudo to "technical-user" while forcing any workflow transition.

Modify your workflow(s) with new Validator(s)

Alternatively, you can configure workflow validators for your transitions to define prerequisite results of the related group sign-off field(s) accordingly.

Modify your workflow(s) with new Post Function(s)

Group Sign-Off: Reset my decision

reset my decision(s)

Group Sign-Off: Reset my LAST decision

reset my last voting based on timestamp (date/time hh:mm:ss) if having multiple roles e.g. based on dynamic rule. Decisions within the same second are treated as simultaneously and will be reset together.

Group Sign-Off: Reset ALL decisions

reset all decisions

Group Sign-Off: Remove myself from this decision

remove myself from list of deciders

Group Sign-Off: set option ONCE

set Option-Once to specified value

Group Sign-Off: set rule

set static or dynamic approval rule overwriting current value

Group Sign-Off: set to default

set rule to configured default value



You have to specify the customfield, the workflow post funciton will use to modify/reset. 

Cloning of issues

If users clone issues in Jira, that is not treated differently to a fresh create: both actions result in an issue create-event. In order to solve this Jira behavior, an admin has to configure a new workflow post function "Group Sign-Off: set rule" to the initial transition targeting into the first status, which may be named "open" but can differ according to each Jira project configuration. Depending on your approach of setting group sign-off rules, you have to set the content of the rule to be empty, indicating that no rule will be set, and set its rule to the necessary value later within another workflow transition depending on reaching a certain status. Alternatively, you have configured a default value for that group sign-off field. In this case, please use the post function "set back to default" instead of "set rule" to overwrite prior decisions.


Analog to add a new workflow condition or validator, you can add a Group Sign-Off Post Function

Email-Notifications (available since v2.4.1)

Each project admin can enable Email-Notifications per Group Sign-Off custom field within the related project administration. Additionally, you can specify which issues fields shall be included in such emails for information without the necessity to open the related issue itself (see sample below).

As a decider, you just have to click on the button "Sign-Off" or "Decline" within the email: if you are already logged in to your Jira within an open browser - such single click is enough to approve! Otherwise, you have to log in for security reasons but that's it.

How to change the sender of email notifications in Jira?

Group Sign-Off uses the native Atlassian API for notifications with just passing the information of the receivers and the message body, only. The sender is put in by Jira, natively. You can change that according to the official Atlassian documentation or have a look at https://confluence.atlassian.com/jirakb/how-to-change-the-sender-s-name-of-the-jira-notifications-967334941.html





Custom Events "Issue Signed-Off Event" and "Issue Declined Event" for automatic Notifications/Emails

A related "Issue Signed-Off Event" or "Issue Declined Event" is fired as soon as a final decision has been determined.
Both events are custom events, which are created by the app automatically.

This feature has been available since version 1.7.0.



Within a project's notification scheme, you can configure the automatic sending of emails to various persons of interest, such as reporters and watchers.

Please refer to the original documentation of Atlassian, if you are unfamiliar with Notification Schemes of Jira.



Properly configured notifications for issue signed-off or declined events will send related users emails analogous to Jira's standard notification "issue update," as shown in the sample email on the right.

Issue Property “jira.issue.editable“ depending on status

Suppose you have put an issue into a status that has set the property jira.issue.editable = false but additionally set the new property jira.issue.group-sign-off.votable = true:
in this case, this will overwrite the property “editable”, and all deciders can vote, but nobody can modify that issue’s (custom)fields.

Using Jira Automation

You can use Jira Automation to listen on any issue update, which will be triggered by deciders' votes (assuming that events are enabled in the app global configuration). For any final decisions, app specific events are triggered: “issue signed-off” or “issue declined”. Unfortunately, Jira Automation cannot be triggered by a custom event (also see https://jira.atlassian.com/browse/JSDSERVER-4461) and this feature request has been regretted by Atlassian due to limited demand!

As a workaround for this limitation of Jira Automation, I have implemented to automatically set an issue entity property having the same name as the related group sign-off field and set that property to the value “pending”, “finally signed-off” or “finally declined”. This feature is available since Group Sign-Off version 2.8.12. Using this version, you can configure Jira Automation as follows: “Approval” is the name of the used Group Sign-Off Field.

Within your Jira Automation Rule, you have also to check the option “Check to allow other rule actions to trigger this rule ….“.

 

 

JQL functions

Please check and verify that your configured customfield uses the “Group Sign-Off Searcher”. If you have configured the “Group Sign-Off Alternative Searcher (searching as text)”, you can use the "~" operator to search text within the group sign-off definitions but not the following JQL functions!

pendingDecisionsByCurrentUser(project key, Group Sign-Off customfield name)

You can search for all issues of a specified project having a pending decision for the specified Group Sign-Off custom field of the currently logged-in user.



CheckForCurrentUser(project key, Group Sign-Off customfield name, decision)

You can search for all issues of a specified project being "signed-off" or "declined" for the specified Group Sign-Off custom field of the currently logged-in user.



CheckForUser(project key, Group Sign-Off customfield name, decision, user)

You can search for all issues of a specified project having a decision as 'signed-off' or 'declined' for the specified Group Sign-Off custom field by the specified user.









Support of "Rich filters" on Jira dashboards

see: Support of "Rich filters" on Jira dashboards

Reporting

Report of all pending decisions within specified project or by individual (multi-project) filter.

d