Skip to end of banner
Go to start of banner

SIL Script Migration

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Current »

Overview

This guide provides comprehensive instructions for migrating Power Scripts from Jira Data Center (DC) to Jira Cloud. The migration process requires careful planning and execution to ensure the continued functionality of your scripts in the cloud environment.

Power Scripts migration involves moving scripts between fundamentally different environments. Key differences include:

  • Modified execution context

  • Different API availability

  • Updated security constraints

  • Changed performance characteristics

The guide focuses on maintaining script functionality while adapting to cloud-specific requirements.

Contents:

Prerequisites

  • Administrator access to both Jira DC and Jira Cloud instances

  • Inventory of existing Power Scripts

  • Knowledge of Simple Issue Language (SIL)

  • Understanding of cloud environment constraints

  • Review the Jira DC to Cloud script migration reference to learn which scripts migrate successfully and which scripts require readjustment.


Migration method

You can use an automated or manual migration method.

Automated migration

For automated script migration, use a tool such as Jira Cloud Migration Assistant (JCMA) or Configuration Manager for Jira (CMJ). When using a tool, the following consistencies help ensure script compatibility:

  • Project and issue type names remain exact matches between Jira DC and Jira Cloud. This ensures project keys or issue type names used directly in scripts will continue to operate after migration.

  • Custom field names are preserved as exact matches between Jira DC and Jira Cloud, but custom field IDs will be different.

    • If SIL aliases were used, which is a best practice, you can update the SIL aliases settings in Power Scripts for Jira Cloud. This way, the scripts will automatically work with the new IDs.

    • If custom field aliases were not used, the migration is a good opportunity to start using them.

  • Status and transition names remain exact matches between Jira DC and Jira Cloud. This ensures scripts using status names, transition names, or IDs should continue to operate after migration.

For details, see Script migration process.

Manual migration

If you aren’t using a migration tool, scripts can still be migrated by uploading them to the SIL manager or through the Apps > Power Scripts > Self Help menu in Jira Cloud admin settings and then configuring them manually.

 Steps for manual script migration

This page explains the steps for manually migrating your SIL scripts from Jira Server/Data Center (Jira DC) to Jira Cloud.

While migrating scripts and settings from Jira Server/Data Center to Jira Cloud can be done manually, there are automation tools that can help with large script volumes. In such cases, we can provide assistance with the script migration process. See how to get help.

Prerеquisites

Your Power Scripts and SIL Engine version must be 5.8.0.0 or higher.

Procedure

  1. Export all scripts from your Jira Server or DC instance.

    1. Open the SIL Manager and right-click the silprograms folder.

    2. From the dropdown menu that opens, select Download.

      This screenshot shows the Download menu that opens after right-clicking on the silprograms folder in the SIL Manager.
  2. Install Power Script for Jira Cloud on your target cloud instance.

  3. From the application server running Jira, create a zip file of the silprograms directory found in the Jira Home folder.

  4. In your Jira Cloud instance:

    1. Navigate to the Apps > Power Scripts > Self Help page.

    2. Select the Backup/Restore tab.

    3. Upload the zip file.

This screenshot shows the Self Help page open on the Backup-Restore tab where the Upload button is located.

Your SIL scripts are now migrated to the new Jira Cloud instance.


Script migration process

 Steps for automated script migration

The table below outlines the steps to perform automated script migration using a tool such as Jira Cloud Migration Assistant (JCMA) or Configuration Manager for Jira (CMJ).

Step 1: Migrate the Jira instance using a tool

  1. Update the sil.aliases properties file. For details, see SIL aliases.

  2. Search code for hard-coded custom field IDs.

  3. Convert hard-coded custom field IDs to aliases.

Step 2: Validate post function and Listener scripts

Starting with the post function and listener script types will quickly expose potential major issues. These scripts are more likely to contain project names, issue type names, and other configuration-specific elements that may need to be resolved. Early identification of discrepancies in these names lets you minimize the impact on the project and resolve potential issues that require Jira changes.

  1. In SIL Manager, run the syntax check on each script to validate the code.

  2. If you discover any name conflicts, use find/replace to search for similar issues across all scripts.

Step 3: Validate Scheduler scripts, Webhooks, SIL Panel, and SIL Runner Gadget scripts

Scripts of these types should migrate easily. Any major issues would have been caught and resolved earlier in the process.

  1. In SIL Manager, run the syntax check on each script to validate the code.

  2. If you discover any name conflicts, use find/replace to search for similar issues across all scripts.

Step 4: Convert Mail handler scripts

The changes required by mail handler scripts are minor and this conversion effort should be minimal.

For details, see the Mail handler scripts section.

Step 5: Convert JQL function scripts

Due to the nature of the changes, JQL scripts require more extensive updates than other script types during migration. SIL provides utility scripts that can help with JQL-related migration in two ways:

  • To scan your existing JQL filters and identify where DC keywords are used that won't work in Jira Cloud.

  • To automatically update those JQL filters to use the Cloud-compatible keywords.

For details, see the Scripted JQL functions/keywords section.

Step 6: Convert Live Fields scripts

Live Fields in Jira Cloud uses JavaScript and Atlassian APIs, unlike Data Center, which uses SIL. The cloud version of Live Fields has more limited functionality than the Data Center version. Converting these scripts requires significant work, including developing workarounds where Cloud features are missing.

For details, see the Live Fields section.


Post-migration testing

After the migration, test your scripts by performing a syntax check in the SIL Manager (in Power Scripts for Jira Cloud).

If a script passes the syntax test, it means that:

  • The functions shown in this code are compatible with both Jira DC and Cloud environments.

  • The syntax of the script it correct.

  • Custom field IDs are correct or have been updated in the alias file.

Passing the syntax test does not mean the script will operate exactly the same way between Jira DC and Jira Cloud.

Some scripts may not work identically between DC and cloud environments and can require adjustments due to differences in project names, issue type names, JQL queries, or other script-contained information. While using migration tools (JMCA or CMJ) improves the chances of successful script migration, these elements may still need to be adjusted to ensure the scripts operate in the cloud instance as expected.

See the Jira DC to Cloud script migration reference to learn which scripts migrate from Jira DC to Cloud and which will require adjustment.

To avoid issues in the target cloud environment, testing all scripts after the migration is strongly recommended.


Required post-migration script changes

When migrated between Jira DC and Jira Cloud, the following script types require additional changes: conditions and validator scripts, Live Fields, and mail handler scripts. In addition, all existing scripted JQL functions/keywords must be updated for Jira Cloud.

Conditions and validator scripts

Jira Cloud uses Jira Expressions language for conditions and validators; scripted conditions and validators are not currently supported in Jira Cloud. While many users find Jira Expressions challenging and time-intensive to work with, there are alternative approaches. As with other features in Jira Cloud, rather than directly converting scripts and replicating Data Center solutions, consider rethinking your approach. To learn about ways to continue using SIL scripted conditions and validators in Jira Cloud, see this article.

 Jira Expressions example
issue.issueType.name.match('^(Dev Task)$') == null || 
(issue.issueType.name.match('^(Dev Task)$') != null && 
issue.parent.subtasks.filter(subtask => subtask.assignee != null).length == 
issue.parent.subtasks.length)? true : false
 SIL plus Jira Expressions example
//SIL code
boolean passConditionValue = true;
if(issueType == "Dev Task") {
    for(string s in subtasks(parent)) {
        if(s.issueType == "Dev Task && isNull(s.assignee)) {
            passConditionValue = false;
        }
    }
}
setIssueEntityPropertyValue(key, "passCondition", passConditionValue);
//Jira Expression
JSON.stringify(issue.properties['passCondition']).includes('true')

Live Fields scripts

Live Fields works differently in Jira DC versus Jira Cloud.

In Jira DC

In Jira Cloud

  • Live Fields is a collection of functions in Power Scripts.

  • Used to manipulate issue screens and UI.

  • Uses SIL language for scripting.

  • Live Fields is a standalone application.
    See Live Fields documentation for details.

  • It is built separately for Cloud architecture requirements.

  • Uses JavaScript/TypeScript instead of SIL.

  • Requires an API written by Atlassian.

Because of these differences, all Live Fields scripts must be converted from SIL to JavaScript when migrating.

Example

//SIL (Data Center)
lfSet("summary", "Value to set");

//JavaScript (Cloud)
getFieldById("summary").setValue("Value to set");

Mail handler scripts

The Power Scripts incoming email service works differently in Jira Cloud than in Data Center. Due to Atlassian’s Cloud architecture, email scripts In Jira Cloud:

  • Cannot intercept messages sent to your primary Atlassian address (youremail@atlassian.net).

  • Can only intercept emails going to an external email accounts, such as Gmail.

Due to the differences in email handling between DC and Cloud, email scripts require different functions in each environment. Existing DC email scripts must be updated to use the new Cloud-compatible functions.

 Data Center email handler script example
IncomingEmail mail = getIncomingEmail();
string issueKey = matchText(mail.subject, "[A-Z][A-Z]+-[0-9]+"); // find an issue key in the subject
if(isNull(issueKey)) {
	// if no issue key found, create a new issue
    string [] fields = {};
    fields += {"reporter", currentUserKey()};
    fields += {"assignee", getUserByEmail(mail.cc[0]).key}; 
    string newIssue = createIssue("TEST", "", "Task", mail.subject, "Minor", mail.body, {}, "", "", 0, fields);
    attachAllFilesFromEmail(newIssue);
    %newIssue%.watchers = getUserKeysFromEmails(mail.cc); 
} else {
	// if issue key found in subject, add a comment
    addComment(issueKey, currentUserKey(), mail.body);
}
 Cloud incoming email processing script example
IncomingEmail mail = getIncomingEmail();
string issueKey = mail.subject;
if(issueExists(issueKey)) {
    // add comment
    string commentText = mail.body;
    string userCommenting = getUserByEmail(mail.from).key;
    addComment(issueKey, userCommenting, commentText);
    attachAllFilesFromEmail(issueKey);
} else {
    // create issue
    string summary = mail.subject;
    string description = mail.body;
    string [] fields = {};
    fields += {"reporter", getUserByEmail(mail.from).key};
    createIssue("SCRUM", "", "Task", summary , "Minor", description, {}, "", "", fields);
}

Scripted JQL functions/keywords

Jira DC and Jira Cloud handle scripted JQL functions/keywords in fundamentally different ways. This difference stems from Jira's core architecture, not from Power Scripts functionality.

In Jira DC

In Jira Cloud

  • Scripts execute during the search operation.

  • Each issue is evaluated individually through separate JQL searches.

  • Results are calculated in real-time.

  • Scripts execute before the search operation.

  • Results are pre-calculated and stored with each issue.

  • JQL searches in Cloud reference the pre-calcualted and stored values to determine which issues to include in the results.

These architectural differences require the following changes to JQL script construction for Jira Cloud:

  • Scripts no longer contain their own JQL searches within their code.

  • Return statements require additional Cloud-specific operations.

  • JQL scripts in Jira Cloud can update the search values of parent and child issues as well as the value within the issue that triggered the script.

Due to these differences, all existing scripted JQL functions/keywords must be updated to use the new methods in Jira Cloud.


Converting Groovy scripts to SIL

If your migration plan includes converting Groovy scripts to SIL, familiarize yourself with the key differences between the Groovy and SIL approaches to scripting.

 Groovy to SIL conversion guidelines

Converting scripts from Groovy to Simple Issue Language (SIL) can be simpler than expected, as SIL has been simplified and requires fewer programming steps than used in Groovy code. This page presents a few key concepts and steps to help prepare Groovy scripts for conversion, especially when using a tool like WorkFlow Pro - AI assistant for Jira.

Basic differences between Groovy and SIL

Import statements

Import statements in programming (lines 1-4 in the example Groovy script below) enable access to code from other modules or packages, making their functions, classes, and variables available in your program. Groovy depends heavily on these modules and packages, particularly Atlassian packages that provide the API to interact with the system.

SIL does not rely on import statements, so they can be deleted from the code. This eliminates time spent researching API documentation to determine which class files need to be imported or contain specific functionality.

Contents:

This approach also protects scripts from system updates that change imported class files. Since SIL scripts don't directly access these classes, they aren't affected by such changes. Instead, Power Scripts handles API class updates, allowing scripts to continue functioning normally after updates.

When using AI tools to convert Groovy scripts to SIL, remove import statements before starting the conversion process. Even though AI tools are trained on SIL, they tend to replicate Groovy patterns in their output. Removing imports prevents the AI from attempting to reproduce patterns that shouldn't exist in SIL.

Class initialization

SIL is designed to avoid direct use of Atlassian API classes, making it simpler to use. This approach makes SIL easier to use, protects scripts from class-level changes, and eliminates the class initialization step that Groovy requires (as shown in lines 12-13 of the example below).

While removing initialization code lines before AI conversion is optional, they should be deleted if the AI attempts to replicate this pattern in SIL.

Example 1

 Example Groovy Script 1

This Groovy script identifies projects where a specific Jira group is used in the project’s permission scheme, either directly or through a project role.

import com.atlassian.confluence.user.DisabledUserManager
import com.atlassian.crowd.embedded.api.CrowdService
import com.atlassian.sal.api.component.ComponentLocator
import com.onresolve.scriptrunner.parameters.annotation.ShortTextInput

@ShortTextInput(label = "Users", description = "Type usernames of deactivated users you would like to reactivate, seperated by spaces")
String names
assert names

def disabledUsers = names.split()

def disabledUserManager = ComponentLocator.getComponent(DisabledUserManager)
def crowdService = ComponentLocator.getComponent(CrowdService)

disabledUsers.each { userName ->
    def user = crowdService.getUser(userName)
    if (user) {
        if (disabledUserManager.isDisabled(user)) {
            disabledUserManager.enableUser(user)
            log.info("User $user.name has been enabled")
        } else {
            log.info("User $user.name is not disabled")
        }
    } else {
        log.debug("User $userName was not found.")
    }
}

Issue initialization

In SIL, you don't need to initialize an issue to make it editable, unlike Groovy, which requires this initialization step (shown in line 7 in Example 2 below). This is particularly true when the script runs in the issue's context. This example shows the difference:

//Groovy approach
def issue = Issues.getByKey('SR-1') as MutableIssue

//SIL approach
string key = "SR-1";

Groovy gets the issue and makes it editable (MutableIssue); SIL simply stores the issue key as a string.

Setting values

Unlike Groovy, SIL doesn't require a function to set field values (shown in lines 12-13 in Example 2). AI conversion tools often incorrectly retain this Groovy pattern when converting to SIL.

This example shows the difference in setting values:

//Groovy approach
setPriority('Highest')

//SIL approach
priority = "Highest";

Groovy uses a function call (setPriority) and takes the priority as a parameter; SIL uses direct assignment and treats priority like a regular variable.

Function for storing issue data

The saveModifiedIssues() function in SIL (Cloud only) serves for memory optimization, not for saving changes; it's not required for storing issue data. Unlike Groovy's explicit save operation (shown in line 16 in Example 2), SIL automatically commits all changes when the script completes.

Reindexing

SIL automatically reindexes issues when changes are made, making Groovy's explicit reindex command (shown in line 17) unnecessary; it can be deleted.

Example 2

 Example Groovy Script 2

This script performs bulk issue updates without triggering emails, modifying last update times, or creating change history records.

import com.adaptavist.hapi.jira.issues.Issues
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.index.IssueIndexingParams
import com.atlassian.jira.issue.index.IssueIndexingService

def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)

def issue = Issues.getByKey('SR-1') as MutableIssue

issue.set {
    setPriority('Highest')
    setSummary('my new summary')
}

issue.store()
issueIndexingService.reIndex(issue, IssueIndexingParams.INDEX_ISSUE_ONLY)

Basic error handling

SIL simplifies coding by automating common tasks. Most functions in SIL come with built-in protection against data that is null, missing, or invalid in ways that can cause code error and result in code crashes. This makes Groovy's explicit error handling (as shown in lines 15-21 in Example 3 below) unnecessary in SIL.

SIL provides error-handling capabilities and can throw specific error types, giving you control over how scripts handle errors.

Type conversion

SIL is very flexible when it comes to type conversion; it handles most conversions automatically.

Example 3

 Example Groovy Script 3

This script validates a custom template field, returning false if no template is selected and true if a template value exists. It logs the validation status through error messages.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.CustomFieldManager


CustomFieldManager cfm = ComponentAccessor.getCustomFieldManager();
CustomField templateCF = cfm.getCustomFieldObject(10112L);
log.error('[LOG] templateCF: ' + templateCF)

Map templateValue = issue.getCustomFieldValue(templateCF)
log.error('[LOG] templateValue: ' + templateValue)

boolean templateIsEmpty = templateValue.get("SELECTED_TEMPLATE") == null;

if (templateIsEmpty) {
    log.error("Template is empty")
    return false;
}

log.error("Template is not empty")
return true;

Best practices

SIL aliases

SIL includes a built-in feature called SIL aliases that simplifies managing custom field IDs in your code. Using aliases makes code more readable and migrations easier, making it a good practice when converting from Groovy to SIL.

Troubleshooting

runnerLog()

When writing scripts in the SIL Manager, you can use a special function called runnerLog() to write output to the console. These output messages are only visible in the SIL Manager or the SIL Runner Gadget and can safely remain in your code, even when scripts run elsewhere (such as post functions).

The output messages are helpful for understanding script execution and debugging.

Run and debug scripts

To test and troubleshoot scripts, you can run them as if they were triggered by a specific issue. To do this:

  1. In SIL Manager, open the script you want to test.

  2. From the Run menu, select Default Script Context.

    This screenshot shows the Default Script Context option in the Run drop-down menu in SIL Manager.
  3. In the Script context configuration dialog window that opens, select a specific issue.

    script-context-configuration.png
  4. Click Run to test your script.

  5. Use the script debugger for troubleshooting.


Jira DC to Cloud script migration reference

Learn more about which scripts migrate successfully from Jira DC to Cloud and which scripts will require adjustment.

 See reference

The following table provides information about the expected outcome of script migration by script type. It shows which scripts that:

  • Are expected to migrate without any significant changes (marked with (tick) in the table)

  • Will migrate, but significant changes are required (marked with 🟡)

  • Will not migrate or the feature is not available in Jira Cloud (marked with (error))

For additional details, see Scripts requiring changes when migrating.

DC script type/feature

Migrates

Feature in Cloud

Notes

Workflow conditions

🟡

(tick)

Condition scripts use Jira Expressions in Jira Cloud and not SIL unless rewritten in a different way.

Workflow validators

🟡

(tick)

Validator scripts use Jira Expressions in Jira Cloud and not SIL unless rewritten in a different way.

Workflow post functions

(tick)

(tick)

Listeners

(tick)

(tick)

Scheduler

(tick)

(tick)

Start/Stop scripts

(error)

(error)

This feature will not be added to Jira Cloud.

Live Fields scripts

🟡

(tick)

Live Fields is written in JavaScript using Atlassian APIs in Jira Cloud.

Mail handler scripts

🟡

(tick)

Incoming email scripts use a different set of functions in Jira Cloud.

Remote systems

(tick)

(tick)

SIL Panel

(tick)

(tick)

SIL Runner Gadget

(tick)

(tick)

SIL Template Language

(tick)

(tick)

Scripted JQL functions

🟡

(tick)

The concept of JQL functions is different in Jira Cloud. All scripts need to be modified to reflect this.

JSM automation scripts

(error)

(error)

Feature not currently available in Jira Cloud. May not be added.

Jira automation scripts

(error)

(error)

Feature not currently available in Jira Cloud. May be added H2 2025 at the earliest.

Webhooks

(tick)

(tick)


Useful tools and scripts for post-migration script adjustment

You can use some tools and methods to help convert, update, and clean up scripts when migrating from Jira DC to Jira Cloud, including workflow conversion, filter updates, and bulk script modifications.

Script conversion assistance with WorkFlow Pro

WorkFlow Pro is an AI chat agent run on Rovo that simplifies Jira automation processes. This application is currently being trained on the complete range of Apprifre workflow and automation apps, including the Simple Issue Language (SIL) used in Power Scripts. While Workflow Pro is new and its training is still ongoing, it can provide significant help for converting scripts after Jira DC to Cloud migration.


Scripts for cleaning up saved filters

You can use scripts to audit filters and update the syntax of specific functions used in saved filters.

 Script to identify filters that need updating based on function used

This analysis script helps assess the impact before making changes by identifying which filters need updating. It's a safe, read-only tool to use before running the actual update script.

for(JFilter f in admGetAllFilters()) {
    string oldFunction = "hasLinkType";
    
    if(contains(f.jql, oldFunction)) {
        runnerLog("Filter \"" + f.name + "\" [" + f.id + "] owned by " + userFullName(f.owner) + " <strong style=\"color:red;\">contains</strong> the function for removal: <strong>" + oldFunction + "</strong>", true);
    } else {
        runnerLog("Filter \"" + f.name + "\" [" + f.id + "] owned by " + userFullName(f.owner) + " <strong style=\"color:green;\">does not contain</strong> the function for removal: <strong>" + oldFunction + "</strong>", true);
    }
}
 Script to update the syntax of function used in saved filters

When migrating JQL queries from Jira DC to Cloud, use this template to convert function syntax from the issueFunction in format to the new equals operator format:

//Starting JQL format:
issueFunction in FUNCTION_NAME("PARAMETER") and ADDITIONAL_CONDITIONS

//Changes to:
FUNCTION_NAME = "PARAMETER" and ADDITIONAL_CONDITIONS

Where:

  • FUNCTION_NAME represents any JQL function name

  • PARAMETER represents the function's parameter

  • ADDITIONAL_CONDITIONS represents any additional JQL conditions

Example

This example shows how the transformation can work on a specific JQL query.

//starting JQL format
issueFunction in hasLinkType("Blockers") and resolution is empty

//would be changed to:
hasLinkType = "Blockers" and resolution is empty

This query is looking for:

  1. Issues that have a link of type Blockers.

  2. AND are unresolved (resolution is empty)

for(JFilter f in admGetAllFilters()) {
    string oldFunction = "hasLinkType";
    string newFunction = "hasLinkType";
    
    if(contains(f.jql, oldFunction)) {
        string jql = f.jql;    
        string [] pieces = split(f.jql, oldFunction);
        
        jql = replace(pieces[0], "issueFunction in ", "") + newFunction;
        
        pieces[1] = replace(pieces[1], "(", " = ");
        pieces[1] = replace(pieces[1], ")", "");
        
        jql += pieces[1];
        f.jql = jql;
        
        admUpdateFilter(f);
        runnerLog("Filter \"" + f.name + "\" [" + f.id + "] owned by " + userFullName(f.owner) + " has been updated to use the new syntax for function: <strong>" + oldFunction + "</strong>", true);
    }
}

For each filter containing the old hasLinkType syntax, the script:

  1. Splits the JQL at hasLinkType

  2. Removes issueFunction in from the first part

  3. Replaces parentheses with an equal sign (=)

  4. Reconstructs the JQL with the new syntax

  5. Updates the filter with the new JQL


How to make bulk changes on scripts

After migrating to Jira Cloud, scripts often require bulk changes. A common task is identifying scripts that use hard-coded custom field IDs (for example, customfield_). Here's how to search across all scripts for these references and perform the update:

  1. In the SIL Manager, right-click the silprograms folder, then click Download.

    This screenshot shows the expanded actions menu for the silprograms folder.

  2. Extract the downloaded zip file and open it in a tool such as VS Code.

  3. Use find and replace features to search and update all files in the selected folder.

    This screenshot shows the Find and Replace menus available from the Edit drop-down in VS Code.

  4. Compress (zip) the updated files.

  5. Go back to Power Scripts and navigate to the Self Help > Backup/Restore tab.

  6. Next, upload the zip file you saved.

    self-help-page-a.png

Uploading the zip file will replace ALL files in the silprograms folder.

  • No labels