Prerequisites
Administrator access to both Jira DC and Jira Cloud instances
Inventory of existing Power Scripts
Knowledge of
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 Jira Cloud Migration Assistant (JCMA) or Configuration Manager for Jira (CMJ). When using a tool, the following consistencies help ensure script compatibility:
ira DC and Jira Cloud. This ensures project keys or issue type names used directly in scripts will continue to operate after migration.
If SIL aliases were used, which is a best practice, you can update the SIL aliases settings in Power Scripts for Jira Cloud. e 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 will be between Jira DC and Jira Cloud. This ensures scripts using status names, transition should continue to operate after migration.
For details, see Script migration process.
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
Export all scripts from your Jira Server or DC instance.
Open the SIL Manager and right-click the silprograms folder.
From the dropdown menu that opens, select Download.
Install Power Script for Jira Cloud on your target cloud instance.
In your Jira Cloud instance:
Navigate to the Apps > Power Scripts > Self Help page.
Select the Backup/Restore tab.
Upload the zip file.
Your SIL scripts are now migrated to the new Jira Cloud instance.
Steps for aoutmated 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 | Update the sil.aliases properties file. For details, see SIL aliases.
|
---|
Step 2: Validate scripts | Starting with the 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. In SIL Manager, run the syntax check on each script to validate the code. If you discover any name conflicts, use find/replace to search for similar issues across all scripts.
|
---|
Step 3: | Scripts of these types should migrate easily. Any major issues would have been caught and resolved earlier in the process. In SIL Manager, run the syntax check on each script to validate the code. If you discover any name conflicts, use find/replace to search for similar issues across all scripts.
|
---|
Step 4: Convert scripts | The changes required by mail handler scripts are minor and this conversion effort should be minimal. For details, . |
---|
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: For details, |
---|
Step 6: Convert Live Fields scripts | Live Fields in Jira Cloud uses JavaScript and Atlassian APIs, unlike Data Center, which uses SIL. The version of Live Fields has more limited functionality than the Data Center version. Converting these scripts significant work, . For details, |
---|
Post-migration testing
After the migration, test your scripts by performingsyntax checkin 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
The syntax of the script it correct.
Custom field IDs are correct or have been updated in the alias file.
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 as expected.
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 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 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:
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 .
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
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.
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-handlingand 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;
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 messages are only visible 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.
To test and troubleshoot scripts, you can run them as if they were triggered by a specific issue. To do this:
In SIL Manager, open the script you want to test.
From the Run menu, select Default Script Context.
In the Script context configuration dialog window that opens, select a specific issue.
Click Run to test your script.
Use the script debugger for troubleshooting.
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 :
Are expected to migrate without any significant changes (marked with 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 )
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 .
Script conversion assistance with Pro
is an AI 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 .
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
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 :
//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:
Issues that have a link of type
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:
Splits the JQL at hasLinkType
Removes issueFunction in
from the first part
Replaces parentheses with an sign (=
)
Reconstructs the JQL with the new syntax
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,
). Here's how to search across all scripts for these references and perform the update:
, right-click the silprograms folder, then click Download.
Extract the downloaded zip file and open it in a tool such as VS Code.
Use find and replace features to search and update all files in the selected folder.
Compress (zip) the updated files.
Go back toand navigate to the Self Help Backup/Restore tab.
Next, upload the zip file you saved.
Uploading the zip file will replace ALL files in the silprograms folder.