Essential recipes for every ServiceNow developer chef.
(Last updated November 2025)
Consult this blog post for scripts that you can use to automate common ServiceNow admin and developer tasks.
Records
Quick scripts for managing records.
Duplicate Record
Make a copy (or copies) of a record.
function dupeRecord() {
// script parameters
var table_name = 'TABLE_NAME_HERE';
var target_record_id = 'TARGET_RECORD_SYS_ID';
var dupes_count = 1;
var orig_gr = new GlideRecord(table_name);
if(orig_gr.get(target_record_id)) {
var new_gr = new GlideRecord(table_name);
new_gr.initialize();
var fields = orig_gr.getFields();
for(var i=0; i<fields.size(); i++) {
var field_name = fields.get(i).getName();
if(field_name !== 'sys_id' && field_name !== 'number') {
new_gr.setValue(field_name, orig_gr.getValue(field_name));
}
}
var new_sys_id = new_gr.insert();
gs.info('New record created with sys_id: ' + new_sys_id);
}
else {
gs.error('Original record not found');
}
}
for(var i=0; i<dupes_count; i++) {
dupeRecord();
}
Fields
Scripts for field operations.
Currency Formatting
Format string fields as USD.
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
// remove decimal point if not required
if(newValue.charAt(newValue.length-1) == ".") {
newValue = newValue.replace(".", "").replaceAll("$", "");
}
// check format
var regex = /^(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$/g;
if(!newValue.replaceAll("$", "").match(regex)) {
g_form.clearValue("amount");
g_form.addErrorMessage("Please enter a dollar amount");
return;
}
// format as currency
var inputAsCurrency = new Number(newValue).toLocaleString("en-US", {
style: "currency",
currency: "USD"
});
// prevent running this script recursively
if(newValue.startsWith("$")) {
return;
}
else {
// write formatted value to form field
g_form.setValue('amount', inputAsCurrency);
}
}
Workflows
Scripts for manipulating legacy workflows.
Restart Workflow
Restart a legacy workflow.
var target_table_name = "TABLE_NAME"; // table name here
var target_record_id = "TARGET_RECORD_SYS_ID" // target record sys id here
var target_record_gr = new GlideRecord(target_table_name);
target_record_gr.get(target_record_id);
gs.info("Target record: " + target_record_gr.number);
// restart workflow
var wf = new Workflow();
var context = wf.getContexts(target_record_gr);
context.next();
wf.restartWorkflow(target_record_gr, false);
wf.broadcastEvent(context.getUniqueValue(), 'update');
Flows
Scripts for manipulating with modern flows.
Restart Flow
Restarting a flow will not cancel the existing context(s), so that must be handled as well.
var target_record_id = 'TARGET_RECORD_SYS_ID'; // target record sys id here
var context = new GlideRecord('sys_flow_context');
context.addEncodedQuery('source_recordSTARTSWITH'+target_record_id+'^state!=COMPLETE^state!=CANCELLED^state!+ERROR^ORDERBYsys_created_on');
context.query();
gs.info('Found ' + context.getRowCount() + ' contexts');
if(context.next()) {
sn_fd.FlowAPI.getRunner().restartFlowFromContext(context.getUniqueValue(), null);
cancelFlow(context.getUniqueValue());
// cancel any other remaining contexts
while(context.next()) {
cancelFlow(context.getUniqueValue());
}
}
else {
gs.info("Nothing to restart");
}
function cancelFlow(id) {
sn_fd.cancel(id, 'cancelled by script');
}
Automated Test Framework (ATF)
Useful test step scripts (may require creation of custom step configs).
ATF Test User Context
Get the Sys ID of the user whose context the test is currently running in.
(function executeStep(inputs, outputs, stepResult, timeout) {
var uid = gs.getUserID();
if(uid) {
stepResult.setOutputMessage("Current test user's sys id is " + uid);
stepResult.setSuccess();
}
else {
stepResult.setOutputMessage("Could not get user's sys id with gs.getUserID()");
stepResult.setFailed();
}
}(inputs, outputs, stepResult, timeout));
Update Sets
Scripts for managing update sets within an instance.
Conflict Checking
Check a target update set for conflicts with other update sets.
var update_set_id = "" // sys_id of update set to run conflict check against
var usx = new GlideRecord("sys_update_xml");
usx.addEncodedQuery("update_set="+update_set_id);
usx.query();
gs.info(usx.getRowCount());
var names = [];
while(usx.next()) {
var name_parts = usx.split("_");
var end = name_parts[name_parts.length-1];
// only select updates that end with a sys_id
if(end.match(/[a-fA-F0-9]{32}/)) {
names.push(end);
}
}
var conflicts = [];
for(var i=0; i<names.length; i++) {
var update_gr = new GlideRecord("sys_update_xml");
update_gr.addEncodedQuery("nameLIKE"+names[i]);
update_gr.query();
if(update_gr.getRowCount() > 1) {
conflicts.push(names[i]);
}
}
gs.info("Potential conflicts:");
gs.info(conflicts);
Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.