Skip to content

Commit ae60667

Browse files
authored
Utility to Fix Update Set Scoping Issues (#1071)
* Created readme.md * BR, SI and UI action JS files Added Business rule, UI action and Script Include JS files
1 parent b45fd85 commit ae60667

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
var util = new global.UpdateSetUtilCustom();
2+
var message = util.fixScopeBatch(current);
3+
gs.addInfoMessage(message);
4+
action.setRedirectURL(current);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(function executeRule(current, previous /*null when async*/) {
2+
var util = new global.UpdateSetUtilCustom();
3+
if (util.checkForScopeConflict(current)) {
4+
current.setAbortAction(true);
5+
gs.addErrorMessage('This update set has a scope conflict in it. Please click the "Fix Updates Scope" button to fix.');
6+
action.setRedirectURL(current);
7+
}
8+
})(current, previous);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
var UpdateSetUtilCustom = Class.create();
2+
UpdateSetUtilCustom.prototype = {
3+
initialize: function() {},
4+
5+
fixScopeBatch: function(grParent) {
6+
var grUpdate = new GlideRecord('sys_update_xml');
7+
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'));
8+
grUpdate.query();
9+
10+
var count = 0;
11+
var newUpdateSets = {};
12+
13+
while (grUpdate.next()) {
14+
if (!grUpdate.getValue('application')) { // No app, should be in a global update set
15+
if (grUpdate.update_set.application != 'global' && grUpdate.update_set.application.scope != 'global') {
16+
count++;
17+
18+
if (!newUpdateSets['global']) {
19+
newUpdateSets['global'] = {
20+
'name': 'Global',
21+
'updates': []
22+
};
23+
}
24+
newUpdateSets['global']['updates'].push(grUpdate.getValue('sys_id'));
25+
}
26+
}
27+
// We don't have the same scope for each update.
28+
else if (grUpdate.application != grUpdate.update_set.application) {
29+
count++;
30+
31+
if (!newUpdateSets[grUpdate.getValue('application')]) {
32+
newUpdateSets[grUpdate.getValue('application')] = {
33+
'name': grUpdate.getDisplayValue('application'),
34+
'updates': []
35+
};
36+
}
37+
newUpdateSets[grUpdate.getValue('application')]['updates'].push(grUpdate.getValue('sys_id'));
38+
}
39+
}
40+
41+
var parentName = grParent.getValue('name');
42+
var keys = Object.keys(newUpdateSets);
43+
for (i in keys) {
44+
var updates = newUpdateSets[keys[i]]['updates'];
45+
// Create new update set in the correct scope.
46+
var grNewSet = GlideRecord('sys_update_set');
47+
grNewSet.initialize();
48+
grNewSet.setValue('application', keys[i]);
49+
grNewSet.setValue('name', parentName + ' - ' + newUpdateSets[keys[i]]['name']);
50+
grNewSet.setValue('parent', grParent.getValue('sys_id'));
51+
var newSetSysId = grNewSet.insert();
52+
53+
for (ii in updates) {
54+
// Get each update and set the new update set.
55+
var updateSysId = updates[ii];
56+
var grUpdate = new GlideRecord('sys_update_xml');
57+
if (grUpdate.get(updateSysId)) {
58+
grUpdate.setValue('update_set', newSetSysId);
59+
grUpdate.update();
60+
}
61+
}
62+
}
63+
if (count > 0) {
64+
return count + ' updates were in the wrong scope. ' + keys.length + ' new update sets were created and associated with this parent update set.';
65+
}
66+
return 'No update scope issues were found.';
67+
},
68+
69+
checkForScopeConflict: function(grParent) {
70+
var application = grParent.getValue('application');
71+
var query = 'update_set=' + grParent.getValue('sys_id') + '^application!=' + application + '^ORapplication=NULL';
72+
if (grParent.application == 'global' || grParent.application.scope == 'global') {
73+
query = 'update_set=' + grParent.getValue('sys_id') + '^application!=' + application + '^applicationISNOTEMPTY^application.scope!=global';
74+
}
75+
76+
var grUpdate = new GlideRecord('sys_update_xml');
77+
grUpdate.addEncodedQuery(query);
78+
grUpdate.setLimit(1);
79+
grUpdate.query();
80+
81+
if (grUpdate.hasNext()) {
82+
return true;
83+
}
84+
return false;
85+
},
86+
87+
type: 'UpdateSetUtilCustom'
88+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
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.
2+
This utility will perform following and implement a way of taking in a parent/batch update set:
3+
4+
- Navigate all children, all updates in children.
5+
6+
- Determine scope issues with updates.
7+
8+
- Create new update set in correct scopes.
9+
10+
- Move updates to those new update sets.
11+
12+
- Associate them with parent/batch.
13+
14+
- 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.
15+
16+
17+
18+
This functionality has following:
19+
20+
- Business rule to abort transaction if scoping issues are found in batched update sets.
21+
- Script include which does job of scoping issues conflict as well as logic for fixing batch scope issues.
22+
- UI action which can be used by developers to fix scoping issues conflict.
23+
24+
![image](https://github.com/user-attachments/assets/0a7c5127-7c15-4bb6-bf96-17de3b81a334)
25+
26+
![image](https://github.com/user-attachments/assets/87872d20-f2c2-42ac-8c69-d095cc7ddaf3)
27+
28+
![image](https://github.com/user-attachments/assets/94890946-395c-476f-a9b9-b81e94a801c9)
29+
30+
![image](https://github.com/user-attachments/assets/96bcea79-a06e-4891-aace-3bbba81e9cb4)
31+
32+
33+
34+
35+

0 commit comments

Comments
 (0)