Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Troubleshooting Running a Groovy Script as a Service (Scriptrunner)

ChristopherJenks Qlik
June 10, 2019

I'm trying to figure out what I'm doing wrong to get a Scriptrunner groovy script running as a service, after reviewing posts such as these:

https://community.atlassian.com/t5/Answers-Developer-Questions/Unable-to-run-a-groovy-script-as-a-service-using-script-runner/qaq-p/503808 

https://scriptrunner.adaptavist.com/5.5.5/jira/services.html

For context, I'm running Jira Server 7.10.2 on a Linux box with the Scriptrunner version 5.5.5 plugin.

I've created a simple sanity-check script as follows, ensuring to set the logged in user to an admin user (obfuscated):

/*
This script is here for sanity-checking setting up a Jira service to execute
a groovy script
*/

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.component.*;

ApplicationUser user = ComponentAccessor.getUserManager().getUserByName("******");
ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(user);

Logger log = Logger.getLogger("com.foo.groovyScripts");
message = "This is a test confirming groovy scripts run in Jira as a Service."
log.debug(message)
log.info(message)
log.warn(message)
log.error(message)

I can copy-paste this script and run it successfully from the Script Console, and I can see the output in the logs when I tail the atlassian-jira logs.

So, I've created a script in the scripts directory and have made sure it has both read and execute permissions, and that it is owned by the service account and that the file actually contains the script:

[foo@ip-123-456-789-321 scripts]# pwd
/path/to/jira/home/scripts

[foo@ip-123-456-789-321 scripts]# ls -la
...
-rwxr-xr-x 1 jira jira 620 Jun 10 12:18 test-service.groovy

[foo@ip-123-456-789-321 scripts]# cat test-service.groovy
/*
This script is here for sanity-checking setting up a Jira service to execute
a groovy script
*/

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.component.*;

ApplicationUser user = ComponentAccessor.getUserManager().getUserByName("*****");
ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(user);

Logger log = Logger.getLogger("com.foo.groovyScripts");
message = "This is a test confirming groovy scripts run in Jira as a Service."
log.debug(message)
log.info(message)
log.warn(message)
log.error(message)

I've also setup the script in Jira with the class:

com.onresolve.jira.groovy.GroovyService 

and cron expression (should run every 5 seconds):

 0/5 0/1 0 ? * * * 

And finally I've tried both the absolute and relative-to-script-roots paths:

/path/to/jira/home/scripts/test-service.groovy

test-service.groovy

However, the script just won't run. (I don't see anything in the logs)

In addition to my own package (com.foo.groovyScripts), I've also tried enabling logging on com.atlassian.jira.service, com.atlassian.jira.services, and com.onresolve.jira.groovy to see if I could find any information at the DEBUG level. I can see that some beans are being instantiated and script registered, however I'm seeing no error information.

2019-06-10 ... /secure/admin/EditService.jspa [c.o.jira.groovy.GroovyService] groovyService.init : input-file=/path/to/jira/home/scripts/test-service.groovy
2019-06-10 ... /secure/admin/ViewServices!default.jspa [c.o.j.groovy.groovyrunner.spring] BeforeInstantiation [bean=com.onresolve.jira.groovy.GroovyService, type=com.onresolve.jira.groovy.GroovyService]
2019-06-10 ... /secure/admin/ViewServices!default.jspa [c.o.j.groovy.groovyrunner.spring] AfterInitialisation [bean=com.onresolve.jira.groovy.GroovyService, type=com.onresolve.jira.groovy.GroovyService]

Is there anything else I can do to figure out why this is not running?

I'm not sure if there is something simple I'm missing (I've checked permissions on the files, user executing the script, existence of the file, content of the file, log levels, and service settings), or if this is a degrade/bug.

1 answer

1 accepted

Suggest an answer

Log in or Sign up to answer
2 votes
Answer accepted
Leonard Chew
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Champions.
April 15, 2020

Hi there.

This is a useful script, and a tricky question.
I think the problem is wether related to the List, nor to the ObjectType of the Element.
The problem seems to be in the data you fetch to get the board admins. The elements contain an id. But if you want to insert a new admin, the id needs to be empty.

See:

for (f in boardAdminService.getBoardAdmins(ourBoard))
{ log.warn(f) }

BoardAdmin newAdmin = BoardAdmin.builder().key(group.getName()).type(BoardAdmin.Type.GROUP).build();
log.warn(newAdmin)

admin.png

Conclusion: I think you'll need to convert the existing admins to users and re-build an admin object, so that the id gets deleted.

Hope this works
Cheers Leonard

Derek Fields _RightStar_
Community Champion
April 17, 2020

Your response was spot on. I modified the script to create a new list of admins using the original list as input and it works as expected. I appreciate the help.

For anyone who wants to see the correct solution

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.groups.GroupManager;
import com.atlassian.greenhopper.model.rapid.RapidView;;
import com.atlassian.greenhopper.manager.rapidview.RapidViewManager;
import com.atlassian.greenhopper.service.rapid.view.RapidViewService;
import com.atlassian.greenhopper.model.rapid.BoardAdmin;
import com.atlassian.greenhopper.service.rapid.view.BoardAdminService;
import com.atlassian.greenhopper.model.rapid.BoardAdmin.Type;

import com.onresolve.scriptrunner.runner.customisers.PluginModuleCompilationCustomiser
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

@WithPlugin("com.pyxis.greenhopper.jira")
// We need a user to retrieve and update the board. this should probably be a service account
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();

// This gets all of the boards available to the current user
// We are going to randomly pick the first one, just for testing purposes
// In a Listener, the event should provide the board and we won't have to look it up
// Note that a Board is called a RapidView
RapidViewService rapidViewService = PluginModuleCompilationCustomiser.getGreenHopperBean(RapidViewService);
List<RapidView> boards = rapidViewService.getRapidViews(currentUser).get();
RapidView ourBoard = boards[0]

// Now we construct a new list of BoardAdmins using the current BoardAdmin list as our base
BoardAdminService boardAdminService = PluginModuleCompilationCustomiser.getGreenHopperBean(BoardAdminService);
List<BoardAdmin> boardAdmins = boardAdminService.getBoardAdmins(ourBoard).collect {
BoardAdmin.builder().key(it.getKey()).type(it.getType()).build();
};

// Add the new admin to the boardAdmins list.
// This line constructs a new BoardAdmin
def group = ComponentAccessor.getGroupManager().getGroup("jira-administrators");
BoardAdmin newAdmin = BoardAdmin.builder().key(group.getName()).type(BoardAdmin.Type.GROUP).build();
boardAdmins.add(newAdmin);

// Update the board admins
boardAdminService.updateBoardAdmins(ourBoard, currentUser, boardAdmins);
Like # people like this
Jeremy Jedlicka
Contributor
July 11, 2022

@Derek Fields _RightStar_

This is exactly what I've been trying to write.  Thanks for this.  Question though, I can't figure out how to use the list "boards" to add the admin across all boards.  I've tried to accomplish this through iterating though "boards", but it keeps erroring out.

Can you provide the modification to the above code that uses "boards" instead of "ourBoard" to update the admins?

Derek Fields _RightStar_
Community Champion
July 11, 2022

@Jeremy Jedlicka - This is simply a matter of iterating through the different boards in the list. Here is the modified code.

 

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.security.groups.GroupManager;
import com.atlassian.greenhopper.model.rapid.RapidView;;
import com.atlassian.greenhopper.manager.rapidview.RapidViewManager;
import com.atlassian.greenhopper.service.rapid.view.RapidViewService;
import com.atlassian.greenhopper.model.rapid.BoardAdmin;
import com.atlassian.greenhopper.service.rapid.view.BoardAdminService;
import com.atlassian.greenhopper.model.rapid.BoardAdmin.Type;

import com.onresolve.scriptrunner.runner.customisers.PluginModuleCompilationCustomiser
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

@WithPlugin("com.pyxis.greenhopper.jira")
// We need a user to retrieve and update the board. this should probably be a service account
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();

// This gets all of the boards available to the current user
// We are going to randomly pick the first one, just for testing purposes
// In a Listener, the event should provide the board and we won't have to look it up
// Note that a Board is called a RapidView
RapidViewService rapidViewService = PluginModuleCompilationCustomiser.getGreenHopperBean(RapidViewService);
List<RapidView> boards = rapidViewService.getRapidViews(currentUser).get();

// This iterates over each board updating the admins
boards.each { ourBoard ->
  // Now we construct a new list of BoardAdmins using the current BoardAdmin list as our base
  BoardAdminService boardAdminService = PluginModuleCompilationCustomiser.getGreenHopperBean(BoardAdminService);
  List<BoardAdmin> boardAdmins = boardAdminService.getBoardAdmins(ourBoard).collect {
     BoardAdmin.builder().key(it.getKey()).type(it.getType()).build();
  };

  // Add the new admin to the boardAdmins list.
  // This line constructs a new BoardAdmin
  def group = ComponentAccessor.getGroupManager().getGroup("jira-administrators");
  BoardAdmin newAdmin =   BoardAdmin.builder().key(group.getName()).type(BoardAdmin.Type.GROUP).build();
  boardAdmins.add(newAdmin);

  // Update the board admins
  boardAdminService.updateBoardAdmins(ourBoard, currentUser, boardAdmins);
}

TAGS
AUG Leaders

Atlassian Community Events