Skip to content

Utility to Fix Update Set Scoping Issues #1071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var util = new global.UpdateSetUtilCustom();
var message = util.fixScopeBatch(current);
gs.addInfoMessage(message);
action.setRedirectURL(current);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(function executeRule(current, previous /*null when async*/) {
var util = new global.UpdateSetUtilCustom();
if (util.checkForScopeConflict(current)) {
current.setAbortAction(true);
gs.addErrorMessage('This update set has a scope conflict in it. Please click the "Fix Updates Scope" button to fix.');
action.setRedirectURL(current);
}
})(current, previous);
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
var UpdateSetUtilCustom = Class.create();
UpdateSetUtilCustom.prototype = {
initialize: function() {},

fixScopeBatch: function(grParent) {
var grUpdate = new GlideRecord('sys_update_xml');
grUpdate.addEncodedQuery('update_set.parent.parent=' + grParent.getValue('sys_id') + '^ORupdate_set.parent=' + grParent.getValue('sys_id') + '^ORupdate_set=' + grParent.getValue('sys_id') + '^ORupdate_set.base_update_set=' + grParent.getValue('sys_id'));
grUpdate.query();

var count = 0;
var newUpdateSets = {};

while (grUpdate.next()) {
if (!grUpdate.getValue('application')) { // No app, should be in a global update set
if (grUpdate.update_set.application != 'global' && grUpdate.update_set.application.scope != 'global') {
count++;

if (!newUpdateSets['global']) {
newUpdateSets['global'] = {
'name': 'Global',
'updates': []
};
}
newUpdateSets['global']['updates'].push(grUpdate.getValue('sys_id'));
}
}
// We don't have the same scope for each update.
else if (grUpdate.application != grUpdate.update_set.application) {
count++;

if (!newUpdateSets[grUpdate.getValue('application')]) {
newUpdateSets[grUpdate.getValue('application')] = {
'name': grUpdate.getDisplayValue('application'),
'updates': []
};
}
newUpdateSets[grUpdate.getValue('application')]['updates'].push(grUpdate.getValue('sys_id'));
}
}

var parentName = grParent.getValue('name');
var keys = Object.keys(newUpdateSets);
for (i in keys) {
var updates = newUpdateSets[keys[i]]['updates'];
// Create new update set in the correct scope.
var grNewSet = GlideRecord('sys_update_set');
grNewSet.initialize();
grNewSet.setValue('application', keys[i]);
grNewSet.setValue('name', parentName + ' - ' + newUpdateSets[keys[i]]['name']);
grNewSet.setValue('parent', grParent.getValue('sys_id'));
var newSetSysId = grNewSet.insert();

for (ii in updates) {
// Get each update and set the new update set.
var updateSysId = updates[ii];
var grUpdate = new GlideRecord('sys_update_xml');
if (grUpdate.get(updateSysId)) {
grUpdate.setValue('update_set', newSetSysId);
grUpdate.update();
}
}
}
if (count > 0) {
return count + ' updates were in the wrong scope. ' + keys.length + ' new update sets were created and associated with this parent update set.';
}
return 'No update scope issues were found.';
},

checkForScopeConflict: function(grParent) {
var application = grParent.getValue('application');
var query = 'update_set=' + grParent.getValue('sys_id') + '^application!=' + application + '^ORapplication=NULL';
if (grParent.application == 'global' || grParent.application.scope == 'global') {
query = 'update_set=' + grParent.getValue('sys_id') + '^application!=' + application + '^applicationISNOTEMPTY^application.scope!=global';
}

var grUpdate = new GlideRecord('sys_update_xml');
grUpdate.addEncodedQuery(query);
grUpdate.setLimit(1);
grUpdate.query();

if (grUpdate.hasNext()) {
return true;
}
return false;
},

type: 'UpdateSetUtilCustom'
};
35 changes: 35 additions & 0 deletions Server Side/Update Sets Scopes Issues Fix Automation/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
ServiceNow Developers work with update set batching and many times it happens that customer updates gets captured in a wrong scope. As of Xanadu release, there is no way to fix these scoping issues in child updates.
This utility will perform following and implement a way of taking in a parent/batch update set:

- Navigate all children, all updates in children.

- Determine scope issues with updates.

- Create new update set in correct scopes.

- Move updates to those new update sets.

- Associate them with parent/batch.

- Stop action on completion of update sets if there are any scope issues found and direct the user to click on the Fix Scope button.



This functionality has following:

- Business rule to abort transaction if scoping issues are found in batched update sets.
- Script include which does job of scoping issues conflict as well as logic for fixing batch scope issues.
- UI action which can be used by developers to fix scoping issues conflict.

![image](https://github.com/user-attachments/assets/0a7c5127-7c15-4bb6-bf96-17de3b81a334)

![image](https://github.com/user-attachments/assets/87872d20-f2c2-42ac-8c69-d095cc7ddaf3)

![image](https://github.com/user-attachments/assets/94890946-395c-476f-a9b9-b81e94a801c9)

![image](https://github.com/user-attachments/assets/96bcea79-a06e-4891-aace-3bbba81e9cb4)





Loading