Project Configurator for Jira Server and DC

Groovy Examples

What’s New

From version 3.3.1, the method getExportedFile from the interface ExportResult is deprecated. The method getExportedReturnFile should be used instead. This new method returns the export configuration file directly, so it is no longer necessary to write the XML string to a file.

Synchronous Export Example Version 3.3.1 or Newer

This example has a simple approach to error handling.

Synchronous-Export-Example.groovy (v 3.3.1 or newer)

// Required Imports
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.task.TaskProgressSink
import com.awnaba.projectconfigurator.operationsapi.ProjectConfigExporter
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.awnaba.projectconfigurator.operationsapi.ConfigOpFullProcessResult
import com.awnaba.projectconfigurator.operationsapi.ReturnCode

// The required annotation to enable access to the functionality provided by the plugin within our script.
@WithPlugin("com.awnaba.projectconfigurator.projectconfigurator")

// Get an instance of the export method

ProjectConfigExporter exporter = ComponentAccessor.getOSGiComponentInstanceOfType(ProjectConfigExporter)

try {
// Define the project keys to be exported in the set below
   Set<String> projectKeys = ["DEMO", "OTHER"].toSet()

// Define the options for how you want to configure the export.
   Map<String, String> exportOptions = [
           "filterCFMode"           : "filterUnusedCFExtended", // Options: none, filterUnusedCFExtended, all
           "jiraFilterExportMode"   : "none", // Options: none, global, projects, global-or-projects, shared, all
           "jiraDashboardExportMode": "none", // Options: none, global, projects, global-or-projects, shared, all
           "agileBoardsExportMode"  : "none" // Options: none, projects, all
   ]

// Run the export synchronously using the options specified above
   ConfigOpFullProcessResult export = exporter.exportSynchronous(exportOptions, projectKeys, TaskProgressSink.NULL_SINK);
   def exportFinalResult = export.getFinalResult()
   def exportCall = export.getCallResult()

// Check if the export completed successfully and if so generate the XML file

// If the export failed notify the user
   if (exportFinalResult == null || exportFinalResult.getReturnCode() != ProjectConfigExporter.ReturnOpCode.SUCCESS) {
       return "The export did not complete successfully: " + exportFinalResult == null ? exportCall.getReturnCode() : exportFinalResult.getReturnCode()
   } else {
       // If the export was successful notify the user where the file is stored
       return "Export file created at " + exportFinalResult.getExportedResultFile().toPath()
   }
} catch (Exception e) {
   return "An unexpected error occurred. Please check your atlassian-jira.log for more information" + "<br/>" + e
}

Synchronous Export Example Version 3.0.5 or Newer

From 3.0.4 to 3.0.5: method getExportedXML from FinalResult object is now called getExportedFile to unify interface ExportResult. This example has a simple approach to error handling.

Synchronous-Export-Example.groovy (v 3.0.5 or newer)

// Required Imports
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.task.TaskProgressSink
import com.awnaba.projectconfigurator.operationsapi.ProjectConfigExporter
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.awnaba.projectconfigurator.operationsapi.ConfigOpFullProcessResult
import com.awnaba.projectconfigurator.operationsapi.ReturnCode

// The required annotation to enable access to the functionality provided by the plugin within our script.
@WithPlugin("com.awnaba.projectconfigurator.projectconfigurator")

// Get an instance of the export method

ProjectConfigExporter exporter = ComponentAccessor.getOSGiComponentInstanceOfType(ProjectConfigExporter)

try {
// Define the project keys to be exported in the set below
   Set<String> projectKeys = ["DEMO", "OTHER"].toSet()

// Define the options for how you want to configure the export.
   Map<String, String> exportOptions = [
           "filterCFMode"           : "filterUnusedCFExtended", // Options: none, filterUnusedCFExtended, all
           "jiraFilterExportMode"   : "none", // Options: none, global, projects, global-or-projects, shared, all
           "jiraDashboardExportMode": "none", // Options: none, global, projects, global-or-projects, shared, all
           "agileBoardsExportMode"  : "none" // Options: none, projects, all
   ]

// Run the export synchronously using the options specified above
   ConfigOpFullProcessResult export = exporter.exportSynchronous(exportOptions, projectKeys, TaskProgressSink.NULL_SINK);
   def exportFinalResult = export.getFinalResult()
   def exportCall = export.getCallResult()

// Check if the export completed successfully and if so generate the XML file

// If the export failed notify the user
   if (exportFinalResult == null || exportFinalResult.getReturnCode() != ProjectConfigExporter.ReturnOpCode.SUCCESS) {
       return "The export did not complete successfully: " + exportFinalResult == null ? exportCall.getReturnCode() : exportFinalResult.getReturnCode()
   } else {
       // If the export was successful write the XML out to a file and notify the user where the file is stored
       // Define the path and export filename to be used below
       File exportFile = new File("/tmp/export.xml")
       // Write the generated xml out to a configuration export XML file.
       exportFile.write(exportFinalResult.getExportedFile().toString())
       // Return the location to the created export file
       return "Export file created at " + exportFile
   }
} catch (Exception e) {
   return "An unexpected error occurred. Please check your atlassian-jira.log for more information" + "<br/>" + e
}

Synchronous Export Example Version 3.0.4 or Older

This example has a single approach to error handling.

Synchronous-Export-Example.groovy (v 3.0.4 or older)

// Required Imports
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.task.TaskProgressSink
import com.awnaba.projectconfigurator.operationsapi.ProjectConfigExporter
import com.onresolve.scriptrunner.runner.customisers.WithPlugin

// The required annotation to enable access to the functionality provided by the plugin within our script.
@WithPlugin("com.awnaba.projectconfigurator.projectconfigurator")

// Get an instance of the export method
ProjectConfigExporter exporter = ComponentAccessor.getOSGiComponentInstanceOfType(ProjectConfigExporter)


try {
// Define the project keys to be exported in the set below
    Set projectKeys = ["DEMO", "DEMO1"]

// Define the options for how you want to configure the export.
    Map<String, String> exportOptions = [
            "filterCFMode"           : "filterUnusedCFExtended", // Options: none, filterUnusedCFExtended, all
            "jiraFilterExportMode"   : "none", // Options: none, global, projects, global-or-projects, shared, all
            "jiraDashboardExportMode": "none", // Options: none, global, projects, global-or-projects, shared, all
            "agileBoardsExportMode"  : "none" // Options: none, projects, all
    ]

// Run the export synchronously using the options specified above
    def exportFinalResult = exporter.exportSynchronous(exportOptions, projectKeys, TaskProgressSink.NULL_SINK).getFinalResult()

// Check if the export completed successfully and if so generate the XML file

// If the export failed notify the user
    if (exportFinalResult == null || exportFinalResult.getReturnCode() != ProjectConfigExporter.ReturnOpCode.SUCCESS) {
        return "The export did not complete successfully"
    } else {
        // If the export was successful write the XML out to a file and notify the user where the file is stored
        // Define the path and export filename to be used below
        File exportFile = new File("/tmp/export.xml")
        // Write the generated xml out to a configuration export XML file.
        exportFile.write(exportFinalResult.getExportedXML())
        // Return the location to the created export file
        return "Export file created at " + exportFile
    }
} catch (Exception e) {
    return "An unexpected error occurred. Please check your atlassian-jira.log for more information" + "<br/>" + e
}

Synchronous Import Example

Synchronous-Import-Example.groovy (all versions)

// Required Imports
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.task.TaskProgressSink
import com.awnaba.projectconfigurator.operationsapi.ProjectConfigImporter
import com.awnaba.projectconfigurator.operationsapi.ConfigOpFullProcessResult
import com.awnaba.projectconfigurator.operationsapi.ConfigImportResult
import com.awnaba.projectconfigurator.operationsapi.ConfigOpCallResult
import java.io.Serializable;

// The required annotation to enable access to the functionality provided by the plugin within our script
@WithPlugin("com.awnaba.projectconfigurator.projectconfigurator")

// Get an instance of the import method
def importer = ComponentAccessor.getOSGiComponentInstanceOfType(ProjectConfigImporter.class)

// Specify the path to the export file
def importFile = "/tmp/import.xml"

// Perform the import if the file is valid
try {
 // Extract the contents of the export file to a String that the import method can use
 def fileContents = new File(importFile).text
 String[] skipObjects = [new String()] as String[]
 // Define the options for how you want to configure the export.
 Map<String, Serializable> importOptions = new HashMap<String, Serializable>();
 importOptions.put(ProjectConfigImporter.IS_SIMULATION, false)
 importOptions.put(ProjectConfigImporter.CREATE_EXTRA_PROJECTS, false)
 importOptions.put(ProjectConfigImporter.SMART_CF_CONTEXTS, false)
 importOptions.put(ProjectConfigImporter.PUBLISH_DRAFTS, true)
 importOptions.put(ProjectConfigImporter.SKIP_OBJECTS, skipObjects)


 // Construct a new ConfigOpFullProcessResult object which will store the results of the configuration import
 // Requires the following parameters of XML config, applyChanges,createExtraProjects,smartCFContexts,publishDrafts,continueOnDashboardFilterErrors,doNotLoadObjects as well as an instance of the TaskProgressSink object.
 def importResult = importer.importConfigurationSynchronously(fileContents.toString(), importOptions, TaskProgressSink.NULL_SINK) as ConfigOpFullProcessResult<ProjectConfigImporter.ReturnCallCode, ? extends ConfigImportResult>

 // Check if the import completed successfully and if so display the results
 def callResult = importResult.getCallResult() as ConfigOpCallResult;
 def callReturnCode = callResult.getReturnCode()

// If the import failed notify the user
// Possible return codes that can be checked = IMPORT_STARTED, NOT_LOGGED_IN, UNAUTHORIZED, UNLICENSED, ERROR_READING_CONFIG_FILE, IMPORT_ALREADY_RUNNING
 if (callReturnCode!=null && callReturnCode != ProjectConfigImporter.ReturnCallCode.IMPORT_STARTED) {
 return "The import did not launch successfully. Launching failed with a return code of " + callReturnCode.toString()
        // If the import was successful display the results
 } else {
     // get the results of the import
     ProjectConfigImporter.ReturnOpCode opCode = importResult.getFinalResult().getReturnCode()
     String message = opCode==ProjectConfigImporter.ReturnOpCode.SUCCESS ? importResult.getFinalResult().getSuccessMessage() : "Import failed"
     return opCode.name() + "<br/>" + message +  "<br/><br/>" + importResult.getFinalResult().getLoadTrace().replaceAll("\n", "<br/>");
 }

// If an invalid file is found print an exception on screen
} catch (FileNotFoundException e) {
 return "You must provide a valid file: " + "<br/>" + e
}