Retrieve workflow used by a project via scriptrunner

Joel Batac
Contributor
July 29, 2022

Hi,

 Is there a way to retrieve the workflow name a project is using. Basically I have a behaviour for a project that sets the custom field (CF Level) value to default 6.  Based on the value of Level (from 1 to 6) I will hide or show another field (CF Id).  At the same time, I have the same behaviour for another project but Level doesn't have default value.

  Now, our jira have more than 2000+ projects that uses 2 workflow templates. Half uses template 1 and half uses template 2. I don't want to add 1000+ project for each behaviour. 

Is it possible to check the workflow name. If project uses template 1, then set Level to 6.  Else, if project is using template 2, then no default value. 

1 answer

2 votes
Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 30, 2022

Hi @Joel Batac

If you try retrieving the workflow's name using the Behaviour, this will not work as expected.

Instead, you will first need to create a REST Endpoint to get the workflow's details and filter out its name. 

Below is the sample REST Endpoint code for your reference:-

import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.transform.BaseScript
import groovyx.net.http.HttpResponseDecorator
import groovyx.net.http.RESTClient
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate
getWorkflowNames { MultivaluedMap queryParams ->

def applicationProperties = ComponentAccessor.applicationProperties

final def hostUrl = applicationProperties.getString('jira.baseurl')

final def projectKey = queryParams.getFirst('projectKey')

final def username = 'admin' //your username
final def password = 'q' // your password

final def headers = ['Authorization': "Basic ${"${username}:${password}".bytes.encodeBase64()}", 'Accept': 'application/json'] as Map

def http = new RESTClient(hostUrl)
http.setHeaders(headers)

def resp = http.get(path: "/rest/projectconfig/1/workflowscheme/${projectKey}") as HttpResponseDecorator

if (resp.status != 200) {
log.warn 'Commander did not respond with 200'
}

def workflowName = resp.data['mappings']['name'] as List

Response.ok(new JsonBuilder(workflowName.first()).toPrettyString()).build()
}

Below is a screenshot of the REST Endpoint configuration:-

rest_config.png

Once you have configured the REST Endpoint, you will need to add a Behaviour configuration which points to all projects and not to any specific project and add something like:-

import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours behaviours

def sampleList = getFieldByName('Sample List')
sampleList.setFormValue(null)

def applicationProperties = ComponentAccessor.applicationProperties

def project = issueContext.projectObject

final def baseUrl = applicationProperties.getString('jira.baseurl')

def hostUrl = "${baseUrl}/rest/scriptrunner/latest/custom/getWorkflowNames?projectKey=${project.key}".toString()

def response = hostUrl.toURL().text

def workflowName = response.substring(1, response.length()-1)

//specify the workflow name

if (workflowName == 'Software Simplified Workflow for Project MOCK') {
sampleList.setFormValue('Option 1')
}

Below is a screenshot of the Behaviour configuration:-

behaviour_config.png

Please note that the sample codes provided are not 100% exact to your environment. Hence, you will need to make the required modifications.

What this Behaviour does is that it calls the REST Endpoint, gets the Workflow name and adds a condition to determine if the project uses that particular workflow.

Since 50% of your project uses one workflow and the other 50% uses another workflow, you will only need to add one if condition to specify the Workflow for which you want to set the default value in the List as shown above. 

I hope this helps to answer your question. :)

Thank you and Kind regards,

Ram

Joel Batac
Contributor
July 31, 2022

Thanks Ram, I will try this out. 

 

 What about - " Based on the value of Level (from 1 to 6) I will hide or show another field (CF Id).  "

Basically if Level is 1-5, Id should show up else hide it. How can i add this check/behaviour?

 

Also, do you have something for oauth authentication as opposed to basic?

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 31, 2022

Hi @Joel Batac

For your requirement to hide or display a field based on the value selected from your list, you will need to add a Server-Side Behaviour for the Level field.

Below is a sample Behaviour code:-

import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours behaviours
def sampleList = getFieldById(fieldChanged)
def sampleListValue = sampleList.value.toString()

def sampleTextField = getFieldByName('Sample Text Field')
sampleTextField.hidden = false

if (sampleListValue in ['null', 'Option 4']) {
sampleTextField.hidden = true
}

Please note that the sample code provided is not 100% exact to your environment. Hence, you will need to make the required modifications.

Below is a screenshot of the Server-Side Behaviour configurations:-

behaviour_config.png

You can add this Server-Side Behaviour on the exact configuration page the Behaviour initialiser above was added.

Below are a few test screenshots for your reference:-

1) When the Behaviour starts, the Initialiser will invoke the REST Endpoint and specify the List value depending on the project workflow that is used. If the condition is true, the Sample List will set the value to Option 1, and the Sample Text Field will be visible.

image1.png

2) If the List's option is updated to either Option 2 or Option 3, the Sample Text Field will still be visible.

image4.png 

3) If the Sample List field is updated to either Option 4 or None, the Sample Text Field will be hidden, as shown in the screenshots below:-

image2.png

 

image3.png

I hope this helps to answer your question. :)

 

Thank you and Kind regards,
Ram

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
August 3, 2022

Hi @Joel Batac

If your question has been answered, kindly accept the answer.

Thank you and Kind regards,

Ram

Joel Batac
Contributor
August 3, 2022

Hi Ram, 

 Thanks for the info. I haven't got it working yet as our Jira is not accepting Basic authentication. Do you have something that uses Bearer + token authentication?

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
August 4, 2022

Hi @Joel Batac

You will need to change the approach if you want to invoke the REST service using the Bearer token. You will need to update the headers that you are using in the REST request from:-

def applicationProperties = ComponentAccessor.applicationProperties

final def hostUrl = applicationProperties.getString('jira.baseurl')

final def username = 'admin' //your username
final def password = 'q' // your password

final def headers = ['Authorization': "Basic ${"${username}:${password}".bytes.encodeBase64()}", 'Accept': 'application/json'] as Map

def http = new RESTClient(hostUrl)
http.setHeaders(headers)

to something like:-


def applicationProperties = ComponentAccessor.applicationProperties

final def hostUrl = applicationProperties.getString('jira.baseurl')

def token = '<YOUR TOKEN>'
def http = new RESTClient(hostUrl)

final def headers = ['Accept': ContentType.JSON, 'Autorization: "Bearer ${token}"] as Map

http.setHeaders(headers)

You can refer to this Adaptavist Library Example on how to use the Bearer Token.

I hope this helps to answer your question. :)

Thank you and Kind regards,

Ram

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
August 11, 2022

Hi @Joel Batac

 

Does my suggestion help to solve your question?

Are you able to get the Authorization using the Bearer token to work?

 

Thank you and Kind regards,

Ram

Joel Batac
Contributor
August 19, 2022

Hi Ram,

 Sadly no, as our token changes every hour so this approach is not feasible. 

Joel Batac
Contributor
September 6, 2022

Hi @Ram Kumar Aravindakshan _Adaptavist_ , I found a workaround.

Since half of my projects are using screen A and the other half is using screen B. I used that as a condition instead. If project is using screen A, CF is 6,  if project is using screen B then CF is NULL. Else do nothing (in case there's a rouge project that doesn't use either of the screens). 

Suggest an answer

Log in or Sign up to answer