code transfer
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-21-2025 03:10 AM
<table style="width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; border: 1px solid rgb(136, 136, 140);">
<tbody>
<!-- Table Title -->
<tr>
<td colspan="2" style="background-color: rgb(126, 128, 126); color: white; font-size: 1.5em; font-weight: bold; padding: 8px; border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 15.0pt;">Critical Incident Communication</span>
</td>
</tr>
<!-- Priority Banner -->
<tr>
<td colspan="2" style="background-color: ${mail_script:im_cic_priority_color}; color: ${mail_script:im_cic_priority_textcolor}; font-weight: bold; padding: 4px; border: 1px solid #88888c; border-top: none;">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">Priority ${mail_script:im_cic_priority}</span>
</td>
</tr>
<!-- Incident hyperlink (WHITE row, no shading) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140); padding: 4px;">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">${URI_REF}</span>
</td>
</tr>
<!-- Priority (gray row) -->
<tr style="background-color: rgb(201, 201, 201);">
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Priority:</span> ${priority}
</span>
</td>
</tr>
<!-- Start (white row) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Start:</span> ${u_outage_start}
</span>
</td>
</tr>
<!-- Resolved (gray row) -->
<tr style="background-color: rgb(201, 201, 201);">
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Resolved:</span> ${u_outage_end}
</span>
</td>
</tr>
<!-- Duration (white row) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Duration:</span> ${mail_script:im_cic_duration}
</span>
</td>
</tr>
<!-- Systems Impacted (gray row) -->
<tr style="background-color: rgb(201, 201, 201);">
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Systems Impacted:</span> ${mail_script:im_cic_getAffectedProducts}
</span>
</td>
</tr>
<!-- Description (white row) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Description:</span> ${u_cic_description}
</span>
</td>
</tr>
<!-- Impact to Clients (gray, full width) -->
<tr style="background-color: rgb(201, 201, 201);">
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Impact to our Clients:</span> ${u_external_impact}
</span>
</td>
</tr>
<!-- Impact to Employees (white, full width) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Impact to our Employees:</span> ${u_internal_impact}
</span>
</td>
</tr>
<!-- Cause (gray, full width) -->
<tr style="background-color: rgb(201, 201, 201);">
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Cause:</span> ${u_probable_cause}
</span>
</td>
</tr>
<!-- Completed Actions (white, full width) -->
<tr>
<td colspan="2" style="border: 1px solid rgb(136, 136, 140);">
<span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">
<span style="font-weight: bold;">Completed Actions<br></span> ${u_previous_activities}
</span>
</td>
</tr>
</tbody>
</table>
18 REPLIES 18
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-03-2025 06:16 AM
(function runMailScript(current, template, email, email_action, event) {
var table = '';
table += '<table style="width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; border: 1px solid rgb(136,136,140);"><tbody>';
// Title Row
table += '<tr><td colspan="2" style="background-color: rgb(126,128,126); color: white; font-size: 1.5em; font-weight: bold; padding: 8px; border: 1px solid rgb(136,136,140);"><span style="font-family: Aptos, sans-serif; font-size: 15.0pt;">Critical Incident Communication</span></td></tr>';
// Priority Banner
table += '<tr><td colspan="2" style="background-color: ' + prioritybgcolor(current) + '; color: ' + prioritytextcolor(current) + '; font-weight: bold; padding: 4px; border: 1px solid #88888c; border-top: none;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">' + incpriority(current) + '</span></td></tr>';
// Incident Number/Hyperlink Row (alternating color will be handled with row count logic)
var colorToggle = false; // start with white after banners
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;">${URI_REF}</span></td></tr>';
colorToggle = !colorToggle;
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Priority:</span> ' + current.priority.getDisplayValue() + '</span></td></tr>';
colorToggle = !colorToggle;
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Start:</span> ' + current.u_outage_start + '</span></td></tr>';
colorToggle = !colorToggle;
if (email_action.event_name.getDisplayValue() != 'im_cic_new') {
if (!current.u_outage_end.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Resolved:</span> ' + current.u_outage_end + '</span></td></tr>';
colorToggle = !colorToggle;
}
var duration = '';
if (!current.u_outage_start.nil() && !current.u_outage_end.nil()) {
duration = calcDiff(current.u_outage_start.getDisplayValue(), current.u_outage_end.getDisplayValue());
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Duration:</span> ' + duration + '</span></td></tr>';
colorToggle = !colorToggle;
}
}
var aff = '';
aff = getAffectedProducts(current.sys_id);
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Systems Impacted:</span> ' + aff + '</span></td></tr>';
colorToggle = !colorToggle;
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Description:</span> ' + current.u_cic_description + '</span></td></tr>';
colorToggle = !colorToggle;
if (email_action.event_name.getDisplayValue() != 'im_cic_new') {
if (!current.u_external_impact.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Impact to our Clients:</span> ' + current.u_external_impact + '</span></td></tr>';
colorToggle = !colorToggle;
}
if (!current.u_internal_impact.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Impact to our Employees:</span> ' + current.u_internal_impact + '</span></td></tr>';
colorToggle = !colorToggle;
}
if (!current.u_probable_cause.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Cause:</span> ' + current.u_probable_cause + '</span></td></tr>';
colorToggle = !colorToggle;
}
}
if (email_action.event_name.getDisplayValue() != 'im_cic_new' && email_action.event_name.getDisplayValue() != 'im_cic_update') {
if (!current.u_resolution_activities.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Resolution Activities:</span> ' + current.u_resolution_activities + '</span></td></tr>';
colorToggle = !colorToggle;
}
}
if (email_action.event_name.getDisplayValue() == 'im_cic_update' || email_action.event_name.getDisplayValue() == 'sno.im.cic.restore.verify') {
if (!current.u_previous_activities.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Completed Actions:</span> ' + current.u_previous_activities + '</span></td></tr>';
colorToggle = !colorToggle;
}
}
if (email_action.event_name.getDisplayValue() == 'im_cic_pis') {
if (!current.u_previous_activities.nil()) {
table += '<tr' + (colorToggle ? ' style="background-color: rgb(201,201,201);"' : '') + '><td colspan="2" style="border: 1px solid rgb(136,136,140); padding: 4px;"><span style="font-family: Aptos, sans-serif; font-size: 12.0pt;"><span style="font-weight: bold;">Action Items:</span> ' + current.u_action_items + '</span></td></tr>';
colorToggle = !colorToggle;
}
}
table += '</tbody></table>';
template.print(table);
function prioritybgcolor(current) {
var bgcolor = '';
var bgpriority = current.priority + '';
if (email_action.event_name.getDisplayValue() == 'im_cic_pis') bgcolor = '#00b050';
else if (bgpriority == '2') bgcolor = '#C00000';
else if (bgpriority == '3') bgcolor = '#E97132';
else if (bgpriority == '4') bgcolor = '#FFFF66';
return bgcolor;
}
function prioritytextcolor(current) {
var textcolor = '';
var textpriority = current.priority + '';
if (email_action.event_name.getDisplayValue() == 'im_cic_pis') textcolor = '#FFFFFF';
else if (textpriority == '2') textcolor = '#FFFFFF';
else if (textpriority == '3') textcolor = '#FFFFFF';
else if (textpriority == '4') textcolor = '#000000';
return textcolor;
}
function incpriority(current) {
var priority = current.priority;
if (email_action.event_name.getDisplayValue() == 'im_cic_pis') {
return "Post Incident Summary";
} else if (priority == 2) {
return "Priority 1";
} else if (priority == 3) {
return "Priority 2";
} else if (priority == 4) {
return "Priority 3";
}
}
function calcDiff(start, end) {
var durr = gs.dateDiff(start, end, false);
durr = durr.toString().replace(/:/g, ' ').split(' ');
var duration = '';
switch (durr.length) {
case 1:
duration = durr[0] + ' Seconds.';
break;
case 2:
duration = durr[0] + ' Minutes ' + durr[1] + ' Seconds.';
break;
case 3:
duration = durr[0] + ' Hours, ' + durr[1] + ' Minutes ' + durr[2] + ' Seconds.';
break;
case 4:
duration = durr[0] + ' Days, ' + durr[1] + ' Hours, ' + durr[2] + ' Minutes ' + durr[3] + ' Seconds.';
break;
}
return duration;
}
function getAffectedProducts(current) {
var pdct = [];
var gr = new GlideRecord("task_ci");
gr.addQuery('task', current);
gr.query();
while (gr.next()) {
if (!gr.ci_item.u_tla.nil()) {
pdct.push(gr.ci_item.u_tla.getDisplayValue());
}
}
pdct = pdct.sort();
pdct = pdct.toString();
//add spaces to the string for readability
pdct = pdct.replace(/,/g, ', ');
return pdct;
}
})(current, template, email, email_action, event);
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-20-2026 05:21 AM
// Code Generated by Sidekick is for learning and experimentation purposes only.
var RelatedTaskCloseUtil = Class.create();
RelatedTaskCloseUtil.prototype = {
initialize: function () {},
closeChildren: function (parentSysId, fromNumber) {
var grTask = new GlideRecord('task');
grTask.addQuery('parent', parentSysId);
// Keep/adjust this line to match your original intent.
// In your screenshot it looks like you were trying to EXCLUDE kb_submission.
grTask.addQuery('sys_class_name', '!=', 'kb_submission');
grTask.query();
while (grTask.next()) {
var childTable = grTask.getValue('sys_class_name');
var childSysId = grTask.getUniqueValue();
if (childTable === 'incident') {
this._closeIncident(childSysId, fromNumber);
} else if (childTable === 'problem') {
this._closeProblem(childSysId, fromNumber);
} else if (childTable === 'change_request') {
this._closeChange(childSysId, fromNumber);
} else {
// Generic close for other task-derived records
grTask.setValue('active', false);
grTask.update();
gs.print('Task ' + grTask.getValue('number') + ' closed based on closure of task ' + fromNumber);
}
}
},
_closeProblem: function (sysId, fromNumber) {
var gr = new GlideRecord('problem');
if (gr.get(sysId)) {
var msg = 'Problem ' + gr.getValue('number') + ' closed based on closure of task ' + fromNumber;
gr.setValue('state', 7); // confirm "7" is your Closed state
var notes = gr.getDisplayValue('close_notes') || '';
gr.setValue('close_notes', (notes ? notes + '\n' : '') + msg);
gr.update();
gs.print(msg);
}
},
_closeIncident: function (sysId, fromNumber) {
var gr = new GlideRecord('incident');
if (gr.get(sysId)) {
var msg = 'Incident ' + gr.getValue('number') + ' closed based on closure of task ' + fromNumber;
gr.setValue('state', 7); // confirm "7" is your Closed state
gr.setValue('active', false);
gr.setValue('comments', msg);
gr.update();
gs.print(msg);
}
},
_closeChange: function (sysId, fromNumber) {
var gr = new GlideRecord('change_request');
if (gr.get(sysId)) {
var msg = 'Change ' + gr.getValue('number') + ' closed based on closure of task ' + fromNumber;
var notes = gr.getDisplayValue('close_notes') || '';
gr.setValue('close_notes', (notes ? notes + '\n' : '') + msg);
gr.setValue('active', false);
gr.update();
gs.print(msg);
}
},
type: 'RelatedTaskCloseUtil'
};
2) Create an “individual” Business Rule on the specific parent table (recommended)
Create a BR on the KB Submission table (example: kb_submission) instead of task.
When: After Update (or After + Async if volume is high)
Condition (example): when it is being closed
current.active.changesTo(false) OR current.state.changesTo(<your closed value>)
JavaScript// Code Generated by Sidekick is for learning and experimentation purposes only.
(function executeRule(current, previous /*null when async*/) {
new RelatedTaskCloseUtil().closeChildren(current.getUniqueValue(), current.getValue('number'));
})(current, previous);
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a month ago
Jira Bi-directional Integration development notes
Outbound Integration(ServiceNow to Jira, create and update)
Purpose: Automatically sync stories, epics, and initiative requests from ServiceNow into Jira issues so IT and engineering teams stay aligned—without manual escalation or status chasing.
Custom tables involved in integration:
JIRA System Properties(x_finfg_sno_jci_jci_system_properties) : This table stores values like environment, servicenow and jira links, etc.. . Those values we used in the flow actions and sub flows and we have to update the values in this table based on environment.
JIRA Custom Fields(x_finfg_sno_jci_jira_custom_fields) : This table stores backend names of jira fields. That we used to construct the payload.
JIRA Issue Type(x_finfg_sno_jci_jira_issue_type) : This table stores the Issue type ids of jira.
JIRA Workflow(x_finfg_sno_jci_jira_workflow) : This table used to sync the state or status between servicenow and jira.
JIRA Epic(x_finfg_sno_jci_jira_epic) : This table used to stores the records that are created through integration. Each record in this table linked to the epic(rm_epic) table record that’s the source to create the record in this table.
JIRA Capabilities(x_finfg_sno_jci_jira_capabilities) : This table used to stores the records that are created through integration. Each record in this table linked to the Initiative(x_finfg_sit_initiative) table record that’s the source to create the record in this table.
JIRA Stories(x_finfg_sno_jci_jira_stories) : This table used to stores the records that are created through integration. Each record in this table linked to the story(rm_story) table record that’s the source to create the record in this table.
JIRA Bugs(x_finfg_sno_jci_jira_bugs) : This table used to stores the records that are created through integration. Each record in this table linked to the Incident(incident) table record that’s the source to create the record in this table.
JIRA Project Mappings(x_finfg_sno_jci_jira_project_mappings) : Stores project mapping details for bug. That we used in flow actions.
Jira Epic Project Mappings(x_finfg_sno_jci_jira_epic_project_mappings) : Stores project mapping details for epic. That we used in flow actions.
Jira Capabilities Project Mappings(x_finfg_sno_jci_jira_capabilities_project_mappings) : Stores project mapping details for capability. That we used in flow actions.
Jira Stories Project Mapping(x_finfg_sno_jci_jira_stories_project_mapping) : Stores project mapping details for story. That we used in flow actions.
Initiative(x_finfg_sit_initiative) : We used this table to trigger the jira capability creation and updating integration.
Tables involved in integration:
Incident(incident)
Epic(rm_epic)
Stoty(rm_story)
We used Business Rules to trigger the custom actions those we created for integration based on insert or update of the record.
In the custom actions we are constructing the payload of inputs and used it in the trigger of out of the box actions(Create Issue, Update Issue and Do Transition) those will take care of issue creation, update and state sync.
Business Rules used:
SNO_SNO_JCI EPIC Creation
SNO_SNO_JCI Epic Update
SNO_SNO_JCI Capability Creation
SNO_SNO_JCI Capability Update
SNO_SNO_JCI Story Creation
SNO_SNO_JCI Story Update
SNO_SNO_JCI Assigned To Update on Story
Custom Actions used:
SNO_SNO_JCI Create EPIC
SNO_SNO_JCI Update Epic
SNO_SNO_JCI Create Capability
SNO_SNO_JCI Update Capability
SNO_SNO_JCI Create Story
SNO_SNO_JCI Update Story
Script includes used:
SNO_SNO_JCIFieldMapping : Used to get the backend names of jira fields by passing environment and
issue type.
SNO_SNO_JCIIssueType : Used to get the issue type id of jira by passing issue type(bug, story, epic,
Initiative).
SNO_SNO_JCISystemProperties : Used to get the values of the records by passing key.
SNO_SNO_JCIUtils : Used to get the results that we used in the integration like input values,
Jira states, etc.. .
Inbound Integration (Jira to ServiceNow, create and update)
Purpose: Automatically sync stories, epics, and initiative requests from Jira issues into ServiceNow Records so IT and engineering teams stay aligned—without manual escalation or status chasing.
The bi-directional webhooks require separate setup and can be used independently without using the spoke actions. By default, the Jira Webhooks application is available in the Jira spoke and has the following modules:
Jira Webhook Registries
Jira WebHook Routing Policies
Routing policy defines conditions that must be met to notify the ServiceNow app. These conditions are based on the events in Jira that you want to be notified about. When the conditions are met, routing policy triggers the associated subflow, which in turn automates the Jira tasks.
Use the Jira Webhook Registries module to assign a token and provide the API path. You must generate a Callback URL here and provide this URL in Jira. A default routing policy is provided in the Jira WebHook Routing Policies module.
Detailed steps on how to configure Jira bi-directional webhooks are as follows:
Create a token to embed in the Jira webhook URL
In the navigation filter type: token_verification.LIST
b.Create a name and a token
Register a Jira webhook in ServiceNow
Navigate to Jira Webhooks > Jira Webhook Registries.
Token populates with the record created at step 1.
Click Callback URL. Note it down
Create a webhook in your Atlassian account
Go to Jira administration console > System > Webhooks (in the Advanced section).
You can also use the quick search (keyboard shortcut is .), then type 'webhooks'.
Click Create a webhook.
In the form that is shown, enter the details for your new webhook. For more information on this, see Configuring a webhook later on this page.
To register your webhook, click Create.
For the URL section use the recently copied Callback URL
Select the type of events you want to be sent from Jira
Customize your webhook
Find ”Process Jira Webhook” subflow and make a copy of it
Customize the copied subflow
Go to Jira WebHook Routing Policies and configure your conditions
Jira Webhook Registries:
Created a “SNO_SNO_JCI Story Epic Capability Webhook” in Jira Webhook Registries(sn_jira_spoke_jira_webhook_registry) and generated a Call back url that we have use in webhook creation in jira. This will build a connection between jira and servicenow.
Jira WebHook Routing Policies:
Created “Epic Story Capability sync” in Jira WebHook Routing Policies.
Updated the fields as following:
Label: Epic Story Capability sync
Condition: Webhook Event is Issue Created and Webhook Event is Issue Updated.
Answer(reference to sub flow): SNO_SNO_JCI Process Jira Webhooks For Story Epic Capability.
Webhook creation in Jira:
Name: ServiceNow Stroy Epic Capability Sync
URL(callback url created in servicenow): https://keybankdev.service-now.com/api/sn_jira_spoke/jira_webhook_callbacks/wh_entry?ni.nolog.id=410dc3c9330b7610b789125c2d5c7b6a&ni.nolog.token=%EF%B7%9E%EF%B7%9F%EF%B7%9280f38178474fb210c3438a74116d4387%EF%B7%AC%EF%B7%941%EF%B7%AC%EF%B7%ADL4th6SWu4u0pb7gnbb4dDw%3D%3DAZbOHpUUESXyRLYeg_D216wjH_vm2-ZYxg8J%EF%B7%AE%EF%B7%AF
Issue related events
You can specify a JQL query to send only events triggered by matching issues. The JQL filter does not apply to events under the Issue link and Filter columns.
"Tracked in SNOW" = Yes AND issuetype in (Feature, Capability, Story)
Marked Issue created and updated as true means webhook event will send the payload to servicenow when the issue is created or updated.
Once servicenow receives the payload from webhook, the subflow associated with Jira WebHook Routing Policies recoed executed.
When Jira issue created the sub flow will check the custom table with Jira id. If the record did not find the sub flow procced with ServiceNow record creation.
When Jira issue updated the sub flow will check the custom table with Jira id. If the record found the sub flow procced with ServiceNow record update.
Sub flow used to update and created records from Jira into ServiceNow:
SNO_SNO_JCI Process Jira Webhooks For Story Epic Capability.
Deployment notes:
Import the data of mentioned tables.
JIRA System Properties(x_finfg_sno_jci_jci_system_properties) : update the property values based on environment
JIRA Custom Fields(x_finfg_sno_jci_jira_custom_fields)
JIRA Issue Type(x_finfg_sno_jci_jira_issue_type)
JIRA Workflow(x_finfg_sno_jci_jira_workflow)
JIRA Project Mappings(x_finfg_sno_jci_jira_project_mappings)
Jira Epic Project Mappings(x_finfg_sno_jci_jira_epic_project_mappings)
Jira Capabilities Project Mappings(x_finfg_sno_jci_jira_capabilities_project_mappings)
Jira Stories Project Mapping(x_finfg_sno_jci_jira_stories_project_mapping)
Deploy the changes of SNO_SIT_Initiative Tracker application
Deploy the changes of SNO_SNO_Jira Core Integration
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a month ago
Jira Bi-directional Integration — Development Notes
Scope
This integration supports bi-directional synchronization between ServiceNow and Jira for the following work items:
Epics (ServiceNow rm_epic ↔ Jira Epic)
Stories (ServiceNow rm_story ↔ Jira Story)
Initiatives / Capabilities (ServiceNow x_finfg_sit_initiative ↔ Jira Capability/Feature — confirm exact Jira issue type used)
Incidents / Bugs (ServiceNow incident ↔ Jira Bug) (outbound tables exist; inbound flow described currently covers epic/story/capability only)
1) Outbound Integration (ServiceNow → Jira: create/update/transition)
Purpose
Automatically create and update Jira issues from ServiceNow records so IT and engineering teams stay aligned without manual escalation, re-keying, or status chasing.
High-level design
Trigger: ServiceNow Business Rules on insert/update for source tables (Epic, Story, Initiative, Incident).
Processing: Business Rules invoke custom Flow Actions.
Payload: Custom actions build the Jira payload using:
environment-specific system properties
issue type IDs
Jira custom field backend names
project mapping tables
Execution: Custom actions call Jira Spoke out-of-box actions:
Create Issue
Update Issue
Do Transition (status sync)
Custom tables (integration configuration & cross-reference)
Configuration / reference data
JIRA System Properties (x_finfg_sno_jci_jci_system_properties)
Stores environment-specific values (e.g., environment name, ServiceNow/Jira base settings).
Must be updated per environment and is referenced by flow actions/subflows.
JIRA Custom Fields (x_finfg_sno_jci_jira_custom_fields)
Stores Jira field backend names (e.g., customfield_12345) used to construct request payloads.
JIRA Issue Type (x_finfg_sno_jci_jira_issue_type)
Stores Jira issue type IDs used by create/update actions.
JIRA Workflow (x_finfg_sno_jci_jira_workflow)
Defines status/state mappings for syncing ServiceNow state ↔ Jira status via transitions.
Integration tracking / “created by integration” tables
These tables store the ServiceNow↔Jira relationship and are used for “find existing vs create new” logic.
JIRA Epic (x_finfg_sno_jci_jira_epic)
Cross-reference for epics created/managed by the integration; linked to rm_epic.
JIRA Capabilities (x_finfg_sno_jci_jira_capabilities)
Cross-reference for capability/initiative items; linked to x_finfg_sit_initiative.
JIRA Stories (x_finfg_sno_jci_jira_stories)
Cross-reference for stories; linked to rm_story.
JIRA Bugs (x_finfg_sno_jci_jira_bugs)
Cross-reference for bugs created/managed by integration; linked to incident.
Project mapping tables
Used to determine the Jira project, issue type variants, and/or routing rules by record attributes.
JIRA Project Mappings (Bug) (x_finfg_sno_jci_jira_project_mappings)
Jira Epic Project Mappings (x_finfg_sno_jci_jira_epic_project_mappings)
Jira Capabilities Project Mappings (x_finfg_sno_jci_jira_capabilities_project_mappings)
Jira Stories Project Mapping (x_finfg_sno_jci_jira_stories_project_mapping)
ServiceNow source tables (outbound)
Incident (incident) → Jira Bug
Epic (rm_epic) → Jira Epic
Story (rm_story) → Jira Story
Initiative (x_finfg_sit_initiative) → Jira Capability/Feature (as configured)
Business Rules (triggers)
SNO_SNO_JCI EPIC Creation
SNO_SNO_JCI Epic Update
SNO_SNO_JCI Capability Creation
SNO_SNO_JCI Capability Update
SNO_SNO_JCI Story Creation
SNO_SNO_JCI Story Update
SNO_SNO_JCI Assigned To Update on Story
Trigger behavior (recommended to document in each BR):
When to fire (insert vs update)
Filter conditions (e.g., only when a “Sync to Jira” flag is true; only on relevant field changes)
Loop prevention (avoid update-chatter when inbound updates write back)
Custom Flow Actions (payload + execution)
SNO_SNO_JCI Create EPIC
SNO_SNO_JCI Update Epic
SNO_SNO_JCI Create Capability
SNO_SNO_JCI Update Capability
SNO_SNO_JCI Create Story
SNO_SNO_JCI Update Story
These actions:
Resolve environment/system settings
Resolve Jira issue type ID
Resolve Jira custom field backend names
Build the request payload
Call Jira Spoke actions (Create/Update/Transition)
Persist the Jira keys/IDs into the appropriate cross-reference table
Script Includes (shared services)
SNO_SNO_JCIFieldMapping
Returns Jira field backend names based on environment + issue type.
SNO_SNO_JCIIssueType
Returns Jira issue type ID based on logical type (bug/story/epic/initiative).
SNO_SNO_JCISystemProperties
Returns configured values by property key.
SNO_SNO_JCIUtils
Shared utilities (input normalization, state mapping lookup, etc.).
2) Inbound Integration (Jira → ServiceNow: create/update)
Purpose
Automatically create/update ServiceNow records when Jira issues are created/updated so both platforms remain aligned with minimal manual coordination.
Architecture (Jira Webhooks + ServiceNow routing policies)
Inbound sync uses the Jira Spoke Webhooks framework and can operate independently of the outbound spoke actions.
Key components:
Jira Webhook Registries (sn_jira_spoke_jira_webhook_registry)
Stores the webhook registration metadata in ServiceNow and generates a Callback URL that you register in Jira.
Jira WebHook Routing Policies
Defines conditions (events/types/JQL filters) and maps matching webhook events to a subflow.
Subflow
Performs “lookup existing mapping → create or update ServiceNow record.”
Configuration steps (clean runbook version)
A) Create token used by callback verification
Navigate to token_verification.LIST
Create a token record (name + token value)
B) Register the webhook in ServiceNow
Go to Jira Webhooks → Jira Webhook Registries
Create registry record (example: SNO_SNO_JCI Story Epic Capability Webhook)
Select the token from step A
Click Callback URL and copy it (store it securely; do not email tokens)
C) Create the webhook in Jira
Jira Admin → System → Webhooks
Create a webhook:
URL: use the ServiceNow-generated Callback URL (do not hardcode tokens in documentation)
Events: enable at minimum Issue Created and Issue Updated
JQL filter (example): "Tracked in SNOW" = Yes AND issuetype in (Feature, Capability, Story)
(confirm issue types and field names match your Jira config)
D) Configure routing policy in ServiceNow
Go to Jira WebHook Routing Policies
Create/update policy (example: Epic Story Capability sync)
Conditions:
Webhook Event is Issue Created
Webhook Event is Issue Updated
Subflow target:
SNO_SNO_JCI Process Jira Webhooks For Story Epic Capability
E) Customize subflow (recommended pattern)
Copy the OOTB Process Jira Webhook subflow (do not modify baseline)
In your custom subflow:
Determine issue type (Epic/Story/Capability)
Check the relevant cross-reference table by Jira Issue ID/Key
If not found → create ServiceNow record + create cross-reference row
If found → update ServiceNow record fields and/or state
Apply state/status mapping via x_finfg_sno_jci_jira_workflow
Ensure loop prevention (e.g., ignore updates with “updated_by = integration” markers)
3) Operational behavior (what happens at runtime)
Jira → ServiceNow (Inbound)
Jira issue created/updated → webhook fires → ServiceNow receives payload
Routing policy matches → subflow executes
Subflow checks cross-reference table:
Not found → create ServiceNow record
Found → update ServiceNow record
ServiceNow → Jira (Outbound)
ServiceNow record inserted/updated → Business Rule fires
Custom action builds payload → Jira issue create/update/transition
Cross-reference table updated with Jira identifiers
4) Deployment notes (environment-ready checklist)
Data to migrate/import (configuration tables)
Import/update records for:
x_finfg_sno_jci_jci_system_properties (update values per environment)
x_finfg_sno_jci_jira_custom_fields
x_finfg_sno_jci_jira_issue_type
x_finfg_sno_jci_jira_workflow
x_finfg_sno_jci_jira_project_mappings
x_finfg_sno_jci_jira_epic_project_mappings
x_finfg_sno_jci_jira_capabilities_project_mappings
x_finfg_sno_jci_jira_stories_project_mapping
Application deployment
Deploy changes for SNO_SIT_Initiative Tracker application
Deploy changes for SNO_SNO_Jira Core Integration application
Post-deploy validation (recommended)
Verify system properties point to correct environment endpoints/config
Confirm Jira issue type IDs and custom field backend names are correct for the target Jira project(s)
Validate outbound: create/update epic/story/capability from ServiceNow
Validate inbound: create/update issue in Jira that matches JQL filter and confirm ServiceNow record is created/updated
Confirm state transitions map correctly both directions
Confirm loop-prevention works (no ping-pong updates)
A) ServiceNow → Jira (Outbound) field mappings
1) Add/maintain the Jira field “backend names”
Table: x_finfg_sno_jci_jira_custom_fields (JIRA Custom Fields)
Add a new row for the field you want to populate (per environment and issue type, based on how your SNO_SNO_JCIFieldMapping lookup is designed).
This is where you store the Jira backend field id like customfield_#### (and any key/name your script include expects).
2) Map ServiceNow values into the Jira payload
Where: the Custom Flow Action that builds the payload for that record type:
SNO_SNO_JCI Create EPIC / Update Epic
SNO_SNO_JCI Create Story / Update Story
SNO_SNO_JCI Create Capability / Update Capability
(and Bug actions, if implemented)
What to change: the step/script that constructs the JSON payload—add the new field using the backend name returned by SNO_SNO_JCIFieldMapping and set it to the desired ServiceNow value.
3) (If needed) extend the mapping helper
Script Include: SNO_SNO_JCIFieldMapping
Update only if your current lookup logic doesn’t support the new mapping pattern (e.g., missing “issue type + env” support, missing key structure, etc.).
B) Jira → ServiceNow (Inbound) field mappings
1) Update the inbound subflow mapping logic
Subflow: SNO_SNO_JCI Process Jira Webhooks For Story Epic Capability
What to change: in the “create ServiceNow record” and “update ServiceNow record” parts:
read the field from the webhook payload (issue.fields.<field> / issue.fields.customfield_####)
map it into the correct ServiceNow table/field (rm_epic, rm_story, x_finfg_sit_initiative, etc.)
2) (Optional but recommended) reuse the same custom field registry
If you want inbound mapping to be configurable (not hardcoded), you can also reference x_finfg_sno_jci_jira_custom_fields from the subflow/script so the subflow looks up customfield_#### by name instead of embedding it.
Practical “where exactly do I add it?” shortcut
If you’re adding a new Jira custom field to sync:
Add it to x_finfg_sno_jci_jira_custom_fields
Add it to the payload builder inside the relevant Create/Update custom action (outbound)
Add it to the webhook subflow mapping (inbound) if you need the reverse sync
