12

We have an old field referenced in older flow versions.
We want to remove all older versions using SFDX and only upload the newest version without the field.
Is it possible to do this without manually deleting older flow versions ?
Thanks

1
  • I don't have the full details currently. You could probably use the FlowDefinitionView to find the ActiveVersionId (301) for each FlowDefinitionView.DurableId (300). Then query FlowVersionView for anything else that references the same FlowDefinitionViewId. That would indicate the older inactive versions that could be deleted. Sep 2, 2019 at 23:06

7 Answers 7

17

We had the same issue in our project. we created a script to delete all obsolete flow before/after deployment.

sfdx force:data:soql:query --query "SELECT Id FROM Flow WHERE Status = 'Obsolete'" --target-org $USERNAME --use-tooling-api --result-format csv > flowTodelete.csv

while read c; do
    if [[ "$c" != "Id" && "$c" != "Your query returned no results." ]]
        then
            sfdx force:data:record:delete --sobject Flow --record-id $c --target-org $USERNAME --use-tooling-api
    fi
done < flowTodelete.csv

rm flowTodelete.csv
5
  • Hello Milan, does this work for you? I always get the following error: ERROR running force:data:record:delete: unable to obtain exclusive access to this record or 1 records: 3001w0000000iziAAA And this record is a FlowDefinition. Any idea on how to solve this? Jan 13, 2021 at 14:22
  • Hi joern, Yes this works quite well in my org.
    – Milan
    Feb 18, 2021 at 15:43
  • It is working well for me today - very useful! Followed some basic tutorials re writing a shell script and making it executable, and I hard coded my username in the script as i did not have a default username set in sfdx
    – gorav
    Aug 29, 2022 at 15:24
  • one note, I had to change the query from Status = 'Obsolete' to Status != 'Active' as i had a bunch of flows with status of Draft and InvalidDraft after the initial purge.
    – gorav
    Aug 29, 2022 at 18:17
  • to exclude flows in managed packages, add and Definition.NamespacePrefix = '' to the query
    – gorav
    Sep 14, 2022 at 19:03
6

From my tests in api version 46 (Summer'19), it seems the procedure described here still works despite sfdx handling flows differently since api version 43.

  1. Find the version numbers of the flow you want to delete by querying FlowDefinitionView

  2. pack them all into your destructiveChanges.xml which will look something like this:

    <?xml version="1.0" encoding="UTF-8"?>
        <Package xmlns="http://soap.sforce.com/2006/04/metadata">
          <types>
            <members>Process_To_Delete-2</members>
            <members>Process_To_Delete-1</members>
            <name>Flow</name>
          </types>
          <version>46.0</version>
        </Package>
    
  3. use the sfdx force:mdapi:deploy -d packageLocation to deploy the deletion

  4. deploy the version of the flow you want to keep

Note: The new way of handling flows since api version 43 means you should technically just put <members>Process_To_Delete</members> but this will systematically give you a insufficient access rights on cross-reference id as will the sfdx force:source:delete command.

Edit So far, it doesn't seem possible to do this with an sfdx command, since only the metadata api allows deleting flow versions.

1
  • 1
    This works with SFDX per above and should be marked as answer.
    – ddeve
    Dec 14, 2019 at 15:41
3

You can use sfdx-hardis plugin to purge flows. It is also possible to connect to the org via JWT if you want to integrate such process within your CI pipelines

sfdx hardis:org:purge:flow --name NAMEOFYOURFLOW

Example:

$ sfdx hardis:org:purge:flow --name TestFlow
[sfdx-hardis] You must be connected to an org to perform this command. Please login in the open web browser
Successfully authorized [email protected] with org ID 00D09000007FRNzEAO
You may now close the browser
[sfdx-hardis] Successfully logged to https://login.salesforce.com with username [email protected]
[sfdx-hardis] Found 2 records:
ID                 MASTERLABEL VERSIONNUMBER DESCRIPTION  STATUS  
30109000000kX8GAAU TestFlow    8             test flowwww Obsolete
30109000000kY2JAAU TestFlow    10            test flowwww Obsolete
[sfdx-hardis] Are you sure you want to delete this list of records in [email protected] (y/n)?: y
Successfully deleted record: 30109000000kX8GAAU.
Successfully deleted record: 30109000000kY2JAAU.
[sfdx-hardis] Deleted the following list of records:
ID                 MASTERLABEL VERSIONNUMBER DESCRIPTION  STATUS
30109000000kX8GAAU TestFlow    8             test flowwww Obsolete
30109000000kY2JAAU TestFlow    10            test flowwww Obsolete
1

Remove all inactive flows using a bash script:

#!/bin/bash

#Script to delete all obsolete flow versions from specified org
#The format: deleteInactiveFlows.sh <your_org_alias or username>

FILE="flowsToDelete.csv"
USERNAME="$1"

QUERY="SELECT Id, Definition.DeveloperName, VersionNumber \
FROM Flow \
WHERE Status = 'Obsolete' \
ORDER BY Definition.DeveloperName, VersionNumber"

RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
RESET="\e[0m"

function query_flow_versions {
    #Query flow versions from specified org using tooling api, add rows to csv file
    sfdx force:data:soql:query --query "${QUERY}" --targetusername "${USERNAME}" --usetoolingapi --resultformat csv > "${FILE}"
}

function delete_flow_versions {
    deleted=0
    while read -r flow;
    do
      #Delete flow version by id (cannot use bulk with tooling api enabled)
      IFS=',' read -ra properties <<< "$flow"
        echo "Processing flow ${properties[1]}, version ${properties[2]}"
        result=$(sfdx force:data:record:delete --sobjecttype Flow --sobjectid ${properties[0]} --targetusername "${USERNAME}" --usetoolingapi) || true
        if [[ "${result}" == "Successfully deleted record"* ]]
        then
            deleted=$((deleted+1))
        fi
    done <"${FILE}"

    echo -e "${GREEN}Deleted flow versions: ${deleted}${RESET}"
}

if [ -z "${USERNAME}" ];
then
    echo -e "${RED}Username should be provided as a parameter${RESET}"
else
    query_flow_versions

    if [ -s "${FILE}" ]
    then
        sed -i -e '1d' ${FILE}

        if [ -s "${FILE}" ]
        then
            queried=$(wc -l < "${FILE}")
            echo -e "${YELLOW}Inactive flow versions queried: ${queried}${RESET}"
            delete_flow_versions
        else
            echo -e "${GREEN}No flow versions to delete${RESET}"
        fi
    else
        echo -e "${RED}Some error occurred during retrieving flow versions${RESET}"
fi

    rm "${FILE}"
fi

read -r -p $'\n'"Window can be closed"
0

In PowerShell you can do it this way to get a members list to remove, so you can copy and paste into your destructive changes file. Basically, it queries the the flows to remove and uses a custom expression to join flow API name and the version number.

$username = "<your alias or username>"
sfdx force:data:soql:query --query "SELECT Id, Definition.DeveloperName, VersionNumber FROM Flow WHERE Status = 'Obsolete'" -u $username -t --json |
 ConvertFrom-Json | Select-Object -ExpandProperty result | Select-Object -ExpandProperty records |
 Select-Object -Property @{n="Members";e={"<members>$($_.Definition.DeveloperName)-$($_.VersionNumber)</members>"}} | Sort-Object Members | Out-Host
0

If you want to delete an inactive version of flow, then you have to first of all remove all the Paused And Failed Flow Interviews, then only you will be able to delete it.

0

I have encountered the same situation and used the query below with 'Tooling API' to extract all obsolete flow versions. Please Note: I have used Data export option on the Salesforce Inspector browser extension

select id, masterlabel  from Flow where status='Obsolete' and processType = 'Flow' order by masterlabel

filter the records you want to delete on Excel or any spreadsheet app, Use the Data import option on Salesforce Inspector. Select Delete, and Use Tooling API. copy the filtered spreadsheet content and Delete.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .