The Zurich release has arrived! Interested in new features and functionalities? Click here for more

How to search in Flow Action scripts

peter_repan
Tera Guru

Hi all, we have a Flows and Subflows with many custom actions. These custom actions often have script step. I need to search within all script steps for a specific keyword. Does anyone know what's the most efficient way?

 

I found tables like: sys_variable_value_list.do where I see scripts, but I can't easily identify the "latest" version of the script. Or table sys_hub_step_instance_list.do where I see script in record view, but I cannot filter by script in list view. Any ideas please ?

1 ACCEPTED SOLUTION

lucasp
Tera Expert

Hi Peter,

 

I agree with your findings - the supporting table structure for Flow Designer is rather complex. I would suggest going through the Customer Update [sys_update_xml] table instead, looking for your code snippet in the 'Payload' field.

 

By querying the Customer Update [sys_update_xml] table for records where the type is 'Action Type,' we can identify all custom or customized Flow Actions. The payload will include the attributes for all steps in the Flow Action. By using some regex magic, we can look for our searchTerm within the <value> tag specifically for the script steps.

 

Here is a script you can run which should give you the desired result. Simply replace the searchTerm with the code snippet you want to find. Since some special characters are HTML encoded in the payload, you may have to modify what characters are encoded in the htmlEncode function if you are using a very complex searchTerm. 

 

If this resolves your issue, please mark the answer as "Helpful" or "Correct". Thanks!

 

var searchTerm = 'MYSEARCHTERM';

function htmlEncode(input) {
    return input.replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/\n/g, '&#13;');
}

// HTML encode the search term, make lower-case
var encodedSearchTerm = htmlEncode(searchTerm.toLowerCase());

var customerUpdate = new GlideRecord('sys_update_xml');
customerUpdate.addEncodedQuery('type=Action Type');
customerUpdate.query();

while (customerUpdate.next()) {

    var payload = customerUpdate.payload.toLowerCase().toString();

    // Extract <sys_hub_step_instance> blocks and <sys_variable_value> blocks
    var stepInstanceRegex = /<sys_hub_step_instance[^>]*>([\s\S]*?)<\/sys_hub_step_instance>/g;
    var variableValueRegex = /<sys_variable_value[^>]*>([\s\S]*?)<\/sys_variable_value>/g;
    var matchStepInstance, matchVariable;

    // Parse all sys_hub_step_instance elements to map
    var stepInstanceMap = {};
    var cidMap = {};
    while ((matchStepInstance = stepInstanceRegex.exec(payload)) !== null) {
        var hubContent = matchStepInstance[1];

        // Step 1: sys_hub_step_instance
        var sysIdMatch = /<sys_id>([\s\S]*?)<\/sys_id>/.exec(hubContent);
        var labelMatch = /<label>([\s\S]*?)<\/label>/.exec(hubContent);
        var cidMatch = /<cid>([\s\S]*?)<\/cid>/.exec(hubContent); // Extract cid
        
        if (sysIdMatch && labelMatch && cidMatch) {
            var sysId = sysIdMatch[1].trim();
            var label = labelMatch[1].trim();
            var cid = cidMatch[1].trim();
            
            stepInstanceMap[sysId] = { label: label, cid: cid }; // Store sys_id to label and cid mapping
        }
    }

    // Step 2: sys_variable_value
    while ((matchVariable = variableValueRegex.exec(payload)) !== null) {
        var variableContent = matchVariable[1]; // Content inside <sys_variable_value>

        var documentKeyMatch = /<document_key>([\s\S]*?)<\/document_key>/.exec(variableContent);
        var valueMatch = /<value[^>]*>([\s\S]*?)<\/value>/.exec(variableContent);
        var variableMatch = /<variable[^>]*display_value="script"[^>]*>/.exec(variableContent); // Check for <variable display_value="script">

        if (documentKeyMatch && valueMatch && variableMatch) {
            var documentKey = documentKeyMatch[1].trim();
            var valueContent = valueMatch[1].trim();

            // Check if the valueContent contains the encoded search term
            if (valueContent.indexOf(encodedSearchTerm) !== -1 && stepInstanceMap[documentKey]) {
                var cid = stepInstanceMap[documentKey].cid;

                if (!cidMap[cid]) {
                    gs.info('Search term found in script step "' + stepInstanceMap[documentKey].label + '", in Flow Action "' +  customerUpdate.target_name.toString() + '"');
                    cidMap[cid] = true; // Mark to avoid duplicates of same script step printed
                }
            }
        }
    }
}

 script-step-search.png

View solution in original post

3 REPLIES 3

lucasp
Tera Expert

Hi Peter,

 

I agree with your findings - the supporting table structure for Flow Designer is rather complex. I would suggest going through the Customer Update [sys_update_xml] table instead, looking for your code snippet in the 'Payload' field.

 

By querying the Customer Update [sys_update_xml] table for records where the type is 'Action Type,' we can identify all custom or customized Flow Actions. The payload will include the attributes for all steps in the Flow Action. By using some regex magic, we can look for our searchTerm within the <value> tag specifically for the script steps.

 

Here is a script you can run which should give you the desired result. Simply replace the searchTerm with the code snippet you want to find. Since some special characters are HTML encoded in the payload, you may have to modify what characters are encoded in the htmlEncode function if you are using a very complex searchTerm. 

 

If this resolves your issue, please mark the answer as "Helpful" or "Correct". Thanks!

 

var searchTerm = 'MYSEARCHTERM';

function htmlEncode(input) {
    return input.replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/\n/g, '&#13;');
}

// HTML encode the search term, make lower-case
var encodedSearchTerm = htmlEncode(searchTerm.toLowerCase());

var customerUpdate = new GlideRecord('sys_update_xml');
customerUpdate.addEncodedQuery('type=Action Type');
customerUpdate.query();

while (customerUpdate.next()) {

    var payload = customerUpdate.payload.toLowerCase().toString();

    // Extract <sys_hub_step_instance> blocks and <sys_variable_value> blocks
    var stepInstanceRegex = /<sys_hub_step_instance[^>]*>([\s\S]*?)<\/sys_hub_step_instance>/g;
    var variableValueRegex = /<sys_variable_value[^>]*>([\s\S]*?)<\/sys_variable_value>/g;
    var matchStepInstance, matchVariable;

    // Parse all sys_hub_step_instance elements to map
    var stepInstanceMap = {};
    var cidMap = {};
    while ((matchStepInstance = stepInstanceRegex.exec(payload)) !== null) {
        var hubContent = matchStepInstance[1];

        // Step 1: sys_hub_step_instance
        var sysIdMatch = /<sys_id>([\s\S]*?)<\/sys_id>/.exec(hubContent);
        var labelMatch = /<label>([\s\S]*?)<\/label>/.exec(hubContent);
        var cidMatch = /<cid>([\s\S]*?)<\/cid>/.exec(hubContent); // Extract cid
        
        if (sysIdMatch && labelMatch && cidMatch) {
            var sysId = sysIdMatch[1].trim();
            var label = labelMatch[1].trim();
            var cid = cidMatch[1].trim();
            
            stepInstanceMap[sysId] = { label: label, cid: cid }; // Store sys_id to label and cid mapping
        }
    }

    // Step 2: sys_variable_value
    while ((matchVariable = variableValueRegex.exec(payload)) !== null) {
        var variableContent = matchVariable[1]; // Content inside <sys_variable_value>

        var documentKeyMatch = /<document_key>([\s\S]*?)<\/document_key>/.exec(variableContent);
        var valueMatch = /<value[^>]*>([\s\S]*?)<\/value>/.exec(variableContent);
        var variableMatch = /<variable[^>]*display_value="script"[^>]*>/.exec(variableContent); // Check for <variable display_value="script">

        if (documentKeyMatch && valueMatch && variableMatch) {
            var documentKey = documentKeyMatch[1].trim();
            var valueContent = valueMatch[1].trim();

            // Check if the valueContent contains the encoded search term
            if (valueContent.indexOf(encodedSearchTerm) !== -1 && stepInstanceMap[documentKey]) {
                var cid = stepInstanceMap[documentKey].cid;

                if (!cidMap[cid]) {
                    gs.info('Search term found in script step "' + stepInstanceMap[documentKey].label + '", in Flow Action "' +  customerUpdate.target_name.toString() + '"');
                    cidMap[cid] = true; // Mark to avoid duplicates of same script step printed
                }
            }
        }
    }
}

 script-step-search.png

Hello,

 

This did not work for me.   I am trying to find where a certain support group is being used.

Thanks,

Chad

Hi Chad - the script is designed specifically for Flow Actions. In what type of object are you trying to find a certain support group? Actions? Subflows? Flows?

 

Thanks