Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Celebration

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root

Avatar

1 badge earned

Collect

Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!

Challenges
Coins

Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.

Recognition
Ribbon

Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!

Leaderboard

Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,456,373
Community Members
 
Community Events
176
Community Groups

How to create projects in post-function with API from Scriptrunner built-in function "copy project"?

Currently the Jira admin (me) creates new projects from a template project with Scriptrunner built-in function "copy project".

I like to give collegues the ability to create projects as well, but in a post-function. These collegues don't have Jira admin privelliges.

The project name and the project key will be in custom fields. The template project key should be configured in the post-function. The post-function has to run with Jira admin privileges.

Is there any grovvy script out there to accomplish this?

Best regards, Johannes

1 answer

0 votes

You can call the built-in script from a post function custom script. But you should validate it first in a validator custom script in case any of the input fail.

So something like this in validator:

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.opensymphony.workflow.InvalidInputException

def sourceKey = ''
def targetKey = ''
def targetName = ''

def
copyProject = new CopyProject()
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]

def errorCollection = copyProject.doValidate(inputs, false)
if (errorCollection.hasAnyErrors()) {
log.warn("CopyProject input invalid: $errorCollection")
throw new InvalidInputException(errorCollection)
}

And this in the post function

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.component.ComponentAccessor

def adminUser = 'admin'
def sourceKey = ''
def targetKey = ''
def targetName = ''

def
copyProject = new CopyProject()
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]


ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(ComponentAccessor.userManager.getUserByName(adminUser))
def cpOutput = copyProject.doScript(inputs)
def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey)
if (!newProject) {
UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin")
} else {
UserMessageUtil.success("$targetKey project created successfully")
}

 You'll have to either hard code or fetch from custom fields the values for sourceKey, targetKey  and targetName. Also, you may want to set other copy options for version, components etc.

Hi Peter-Dave,

As I have several types of projects in my instance, I created several templates.
So I created a project in Jira, with a Kanban board and a three-state workflow (Backlog, Rifinement, Done).

From this project, in the transition from the "Rifinement" to "Done" state, I intend to run the script to clone one of the templates.
I'm trying to use the script you posted here, but I see errors and as I'm not very good at code, I'm having trouble correcting them.
What am I doing wrong?
Can you help me?
It is very important to me because I create a lot of projects manually.
Thank you so much
Emanuel Lima

Post Functions.JPGValidator.JPG

Hi Peter-Dave,
Here, maybe you can better understand what is happening.

Thank you so much
Emanuel Lima

 

Capturar_02.JPGCapturar_01.JPG

This is probably partially caused by new version of scriptrunner.

Try the following:

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.opensymphony.workflow.InvalidInputException
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl

def sourceKey = ''
def targetKey = ''
def targetName = ''

def copyProject = ScriptRunnerImpl.scriptRunner.createBean(CopyProject)
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]

def errorCollection = copyProject.doValidate(inputs as Map<String, String>, false)
if (errorCollection.hasAnyErrors()) {
log.warn("CopyProject input invalid: $errorCollection")
throw new InvalidInputException(errorCollection)
}

And

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.component.ComponentAccessor

def adminUser = 'admin'
def sourceKey = ''
def targetKey = ''
def targetName = ''

def copyProject = ScriptRunnerImpl.scriptRunner.createBean(CopyProject)
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]


ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(ComponentAccessor.userManager.getUserByName(adminUser))
def cpOutput = copyProject.doScript(inputs)
def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey)
if (!newProject) {
UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin")
} else {
UserMessageUtil.success("$targetKey project created successfully")
}

Hi Peter-Dave,


Thanks for your quick turnaround.
I made the changes you indicated and I no longer have errors in the Validator. But in Post-Function I have these errors:
What will be missing?
Thanks again for the help.

Capturar_06.JPGCapturar_05.JPGCapturar_04.JPGCapturar_03.JPG
Emanuel

I can't see the full script, but the second error reads "the [adminUser] variable is undeclared"

Are you sure you have the following line above the start of the screenshot?

def adminUser = 'admin' //or other user name with permission to create projects

The other errors can probably be safely ignored. Some errors are just warning to tell you that the editor/compiler isn't sure if that will work, but the script may run fine at runtime

If you really want them to go away, you can do the following:

def cpOutput = copyProject.doScript(inputs as Map<String, Object>)

But I must warn you of something I encountered recently. If you have multiple postfunctions, using setLoggedInUser(adminUser) in the first one, will cause all subsequent post functions to to be executed as that user.

So it's better to reset the user after the copy project action.

//store the current user before changing using to proviledged user
def jiraAuthContext =ComponentAccessor.jiraAuthenticationContext
def curretnUser = jiraAuthContext.loggedInuser
jiraAuthContext.loggedInUser = ComponentAccessor.userManager.getUserByName(adminUser)

//execute the copy action
def
cpOutput = copyProject.doScript(inputs)

//change the effective user back to the stored current useer
jiraAuthContext.loggedInUser = currentUser

//continue with the rest of the script
def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey)
if (!newProject) {
UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin")
} else {
UserMessageUtil.success("$targetKey project created successfully")
}

Hi Peter-Dave,

Thanks again for the feedback,
I don't see where to make the changes you suggested. So I put all my code here:

"Post Functions" Code

 

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.project.ProjectManager
import groovy.transform.Field

def adminUser = 'admin'
def sourceKey = 'TNT'
def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'

def copyProject = new CopyProject()
def inputs = [
    (CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
    (CopyProject.FIELD_TARGET_PROJECT) : targetKey,
    (CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
    (CopyProject.FIELD_COPY_VERSIONS) : false,
    (CopyProject.FIELD_COPY_COMPONENTS) : false,
    (CopyProject.FIELD_COPY_ISSUES) : false,
    (CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]


ComponentAccessor.getJiraAuthenticationContext().setLoggedInUser(ComponentAccessor.userManager.getUserByName(adminUser))
def cpOutput = copyProject.doScript(inputs)
def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey)
if (!newProject) {
   UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin")
} else {
   UserMessageUtil.success("$targetKey project created successfully")
}
"Validators" Code:
import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.opensymphony.workflow.InvalidInputException

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.project.ProjectManager
import groovy.transform.Field

def sourceKey = 'TNT'
def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'

def copyProject = new CopyProject()
def inputs = [
    (CopyProject.FIELD_SOURCE_PROJECT)       : sourceKey,
    (CopyProject.FIELD_TARGET_PROJECT)       : targetKey,
    (CopyProject.FIELD_TARGET_PROJECT_NAME)  : targetName,
    (CopyProject.FIELD_COPY_VERSIONS)        : false,
    (CopyProject.FIELD_COPY_COMPONENTS)      : false,
    (CopyProject.FIELD_COPY_ISSUES)          : false,
    (CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]

def errorCollection = copyProject.doValidate(inputs, false)
if (errorCollection.hasAnyErrors()) {
    log.warn("CopyProject input invalid: $errorCollection")
    throw new InvalidInputException(errorCollection)
}
Thank you very much,
Emanuel

Hi Peter-Dave,

This is how I have my script, where should I implement the changes you indicated?

Thank you,

Emanuel

Here is an updated version of your PostFunction script:

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.project.ProjectManager
import groovy.transform.Field

def adminUserName = 'admin'
def sourceKey = 'TNT'
def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'

def copyProject = ScriptRunnerImpl.scriptRunner.createBean(CopyProject)
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def adminUser = ComponentAccessor.userManager.getUserByName(adminUserName)
ComponentAccessor.jiraAuthenticationContext.loggedInUser = adminUser
def cpOutput = copyProject.doScript(inputs)
ComponentAccessor.jiraAuthenticationContext.loggedInUser = currentUser
def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey)
if (!newProject) {
UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin")
} else {
UserMessageUtil.success("$targetKey project created successfully")
}

And a full version of your validator script

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import com.opensymphony.workflow.InvalidInputException

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.project.ProjectManager
import groovy.transform.Field

def sourceKey = 'TNT'
def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'

def copyProject = ScriptRunnerImpl.scriptRunner.createBean(CopyProject)
def inputs = [
(CopyProject.FIELD_SOURCE_PROJECT) : sourceKey,
(CopyProject.FIELD_TARGET_PROJECT) : targetKey,
(CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName,
(CopyProject.FIELD_COPY_VERSIONS) : false,
(CopyProject.FIELD_COPY_COMPONENTS) : false,
(CopyProject.FIELD_COPY_ISSUES) : false,
(CopyProject.FIELD_COPY_DASH_AND_FILTERS): false
]

def errorCollection = copyProject.doValidate(inputs as Map<String, String>, false)
if (errorCollection.hasAnyErrors()) {
log.warn("CopyProject input invalid: $errorCollection")
throw new InvalidInputException(errorCollection)
}

Hi Peter-Dave,
First of all thank you very much for rewriting the code.
I was absent, just now I picked up the topic again.
I copied-past the code, the "Validator" seems to be OK, but the Post Fuction still has an error.
I have attached a screenshot, can you see why this error occurs?


Thank you Dave

Emanuelpostfunction_error.JPG

Hi Dave,

I commented out this line to see what happens,
and ran the script.
However I got this error:

Thank you

Emanuel

run_script_error.JPG

Many static type checking error can be ignored. That's just the editor's syntax checking telling you it can't be sure if this will work or not.

Did you try run the code as is without commenting that line out?

You might be able to make the error go away by telling the editor's syntax checking routine what to expect from "inputs

copyProject.doScript(inputs as Map<String, Object>)

Hi,
I made the changes you suggested, I no longer have an error in the code but after running the script, I have this error:

 

-----------------------------------------------------------------------------

2022-09-28 15:39:33,298 ERROR [workflow.AbstractScriptWorkflowFunction]: Workflow script has failed on issue CPBS-4 for user 'admin'. View here: https://devjira.befig.net/secure/admin/workflows/ViewWorkflowTransition.jspa?workflowMode=live&workflowName=Software+Simplified+Workflow+for+Project+CPBS&descriptorTab=postfunctions&workflowTransition=61&highlight=1
java.lang.Exception: Could not create project: Errors: {}
Error Messages: [You must have global administrator rights in order to modify projects.]
at com.onresolve.scriptrunner.canned.jira.admin.CopyProject.doCopyProject(CopyProject.groovy:402)
at com.onresolve.scriptrunner.canned.jira.admin.CopyProject$doCopyProject.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.canned.jira.admin.CopyProject.execute(CopyProject.groovy:369)
at com.onresolve.scriptrunner.canned.jira.admin.CopyProject.execute(CopyProject.groovy)
at com.onresolve.scriptrunner.canned.AbstractCannedScript.doScript(AbstractCannedScript.groovy:81)
at Script40.run(Script40.groovy:31)

----------------------------------------------------------------------------------------------

My code in Post Functions looks like this now:

 

import com.onresolve.scriptrunner.canned.jira.admin.CopyProject import com.onresolve.scriptrunner.runner.ScriptRunnerImpl import com.onresolve.scriptrunner.runner.util.UserMessageUtil import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.IssueFactory import com.atlassian.jira.project.ProjectManager import groovy.transform.Field def adminUserName = 'admin' def sourceKey = 'TNT' def targetKey = 'COPYTNT' def targetName = 'Team Network Template 01' def copyProject = ScriptRunnerImpl.scriptRunner.createBean(CopyProject) def inputs = [ (CopyProject.FIELD_SOURCE_PROJECT) : sourceKey, (CopyProject.FIELD_TARGET_PROJECT) : targetKey, (CopyProject.FIELD_TARGET_PROJECT_NAME) : targetName, (CopyProject.FIELD_COPY_VERSIONS) : false, (CopyProject.FIELD_COPY_COMPONENTS) : false, (CopyProject.FIELD_COPY_ISSUES) : false, (CopyProject.FIELD_COPY_DASH_AND_FILTERS): false ] def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser def adminUser = ComponentAccessor.userManager.getUserByName(adminUserName) ComponentAccessor.jiraAuthenticationContext.loggedInUser = adminUser //def cpOutput = copyProject.doScript(inputs) copyProject.doScript(inputs as Map) ComponentAccessor.jiraAuthenticationContext.loggedInUser = currentUser def newProject = ComponentAccessor.projectManager.getProjectObjByKeyIgnoreCase(targetKey) if (!newProject) { UserMessageUtil.error("There was an error creating your project. Contact your Jira Admin") } else { UserMessageUtil.success("$targetKey project created successfully") }

Hi Peter,

Do you have time for a meeting to help me with this topic?

I think it would be easier for you to help me that way.

Thank you

BR

That error is telling me that your "admin" user possibly doesn't have global admin permission. Make sure you supply an active user with the global admin permission in line 11.

I don't work for either Atlassian or Adaptavist. So I'm not really in a position to provide more direct help. Answering questions here is not part of my job. I do this strictly on a voluntary basis.

Hi Dave,

How are you?

I have global permission in Jira. I'm an application administrator, and I've been checking.

I know you're not from atlassian, I appreciate all the help and support you've given me. I just really wanted to get over this issue.
I'll keep trying to figure out where I'm going wrong, and why the script doesn't work.
If you have another solution please let me know. And if I manage to get past this issue I will give you feedback.

Thank you so much

BR

Emanuel

It's not about your own personal permissions.

def adminUserName = 'admin'
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def adminUser = ComponentAccessor.userManager.getUserByName(adminUserName)
ComponentAccessor.jiraAuthenticationContext.loggedInUser = adminUser

These lines will change who the script thinks is currently logged in. It changes to a user with the username 'admin'.

And after the execution, it changes back to the current user.

This will allow non-admins to use the workflow to trigger a task reserved to admins.

Try changing "def adminUserName = 'admin'" to another user such as yourself. If that works, then examine the admin user permission and status carefully. Or create a brand new user. Something like "Automation Project Creator".

Hi Dave,

As you indicated, I used my user administrator(jiraadmin), and I replacd it as shown below, but the script still does not generate projects:

 

def adminUserName = 'jiraadmin'
def sourceKey = 'TNT'
def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'
I also used my own user, the result is always the same:
def adminUserName = 'emanuel.lima@altran.com'
def sourceKey = 'TNT' def targetKey = 'COPYTNT'
def targetName = 'Team Network Template 01'

 

Thank you

BR

Emanuel

Suggest an answer

Log in or Sign up to answer