As a Product Owner, introducing new functionalities like Digital Portfolio Management and Service Builder is exciting. These tools empower organizations to manage services and offerings more effectively.
However, with innovation comes complexity. Suddenly, you have multiple stakeholders creating services and offerings—many of whom are unfamiliar with the process. Granting direct access to production is risky because mistakes can lead to serious disruptions without proper governance. I was in a similar situation.
To maintain control and reduce errors, I enforced the DTAP flow (Development, Test, Acceptance, Production). This means every service and offering must first be created in Development instance. Then, a system administrator (or a dev) manually collects all related resources and moves them through the environments. While this approach ensures stability, it’s time-consuming and prone to human error.
Here’s where a technical Product Owner can make a difference. Instead of relying on manual migration, I wrote a script that automatically adds all Service Builder assets to an update set. This simple automation keeps the DTAP process intact while giving the Product Owner full control over what moves to higher environments. I took help from the Add to Update Set Utility.
Note: You can execute this script in Global but Service Builder runs in the DPM scope. You might have to declare Application Cross-scope access to be able to run this in the DPM scope. You can also run the script twice as a fix script in multiple application scope.
The result?
• Fewer mistakes
• Faster deployments
• Better governance
initiateUpdateSetAddition();
function initiateUpdateSetAddition() {
// All the tables involved in the Service Builder usage
var tableNames = [
"cmdb_ci_service",
"cmdb_ci_service_business",
"cmdb_ci_service_technical",
"service_offering",
"cmdb_rel_ci",
"sc_cat_item_subscribe_mtom",
"service_offering_commitment",
"service_subscribe_company",
"service_subscribe_department",
"service_subscribe_location",
"service_subscribe_sys_user",
"service_subscribe_sys_user_grp",
"contract_rel_ci",
"sn_dpm_kpi_group_m2m_spm_nodes",
];
for (var i = 0; i < tableNames.length; i++) {
getRecordsToaddToUpdateSet(tableNames[i]);
}
}
function getRecordsToaddToUpdateSet(tableName) {
var gr = new GlideRecord(tableName);
// update this query to what you wish
// You can also avoid the query to get all the asset
// If you know or are in doubt that no query will result in a heavy transaction, then do it periodically. For e.g. update the query to have everything created in the last week.
//updated this month
gr.addEncodedQuery(
"sys_created_onONLast 30 days@javascript:gs.beginningOfLast30Days()@javascript:gs.endOfLast30Days()"
);
gr.query();
while (gr.next()) {
addToUpdateSet(gr);
}
}
function addToUpdateSet(current) {
current.setForceUpdate(true);
current.update();
var updateManager = new GlideUpdateManager2();
var currTable = current.getTableName();
if (
currTable.startsWith("wf_") ||
currTable.startsWith("sys_ui_") ||
currTable == "sys_choice" ||
current.getED().getAttribute("update_synch") == "true" ||
current.getED().getAttribute("update_synch_custom") == "true"
) {
return;
} else {
updateManager.saveRecord(current);
}
}

Leave a Reply