Listing all solution and non-solution flows in a tenant
Analyzing flows with flows has been an interesting endeavor for me lately. Like my previous post on listing SharePoint connectors used in flows, this blog post is also a governance related topic revolving around using Power Automate Management connectors to analyze a tenant’s flows. This time we’re going to look at listing solution and non-solution flows with… flow!
While listing solution flows as a Power Platform admin is straightforward, getting our hands on non-solution flows – i.e. “My Flows” – requires that I, as the user looping through all flows, am an owner of the flows I want to list. Generally, it might not be a bad idea to have an admin or a service account as an owner in personal flows. Remember that assigning ownership of a personal to a new user doesn’t mean that Power Platform requests are consumed from the new user’s quota. With non-solution flows, it’s always the creator owner whose account is taxed for Power Platform requests.
So why did we need to list all flows in our use case and segment them based on whether they’re solution flows or not? Good question. We had to not only list all owners of flows but to also prepare for the possibility that we need to move flows from tenant to tenant ourselves. As non-solution flows need to be exported as zip files as opposed to exporting solutions, the migration of such flows requires manual labor.
Before we dissect our solution, which is of course a flow that lists flows, I want to re-iterate that to list non-solution flows with the List flows as Admin connector, the connection (or rather connection reference since this administrative flow is of course built in a solution) must be an owner of a flow for its flow definition to be returned by the connector. This example doesn’t cover adding owners to flows so that’s something you have to Google and figure out yourself. This said, let’s dissect our flow!
Whatever the trigger you use, the first steps include initializing two variables: one to hold an array for solution flows and the other to hold an array for non-solution flows. Next, all environments are listed as we’re going to loop through all flows in each environment. This way we can narrow down what we have in each environment.
Looping through environments
Environments are looped through in a parallel branch that separates solution and non-solution flows for easier diagnosis and analysis of the flow. We could save some Power Platform requests by running everything in a single branch but as I’m not worried about API calls or throttling limits, I’ve created two branches to make the flow more easily readable. Let’s look at what the environment loops contain.
What I usually like to do in a loop is to compose relevant information as initial steps in a loop. In this case we’re talking about the Environment Display Name. This often times makes it easier for me to read what the flow is doing and where errors – which will happen when building – occur. The next step is to list all flows in the environment we’re looping through with the List flows as Admin connector. Remember to set pagination to return everything! I always set it to the max, which is 100 000.
Now that we have our hands on all flows in an environment, we need to filter the returned array for solution flows (left branch in image 2) and non-solution flows (right branch in image 2). The following filter conditions are crucial for getting the correct results in the filter arrays! But what do we filter on? Another good question! Before I answer, I want you to bookmark this blog post. It has fantastic information about admin connectors. Then to the answer. If a flow is a solution flow, its flow definition contains a property named workflowEntityId. If that property is not present in a flow definition, the flow in question is a non-solution flow. Not harder than that! That said, to filter solution flows, the filter array in the left branch has the following filter condition:
The filter array in the right branch has the following filter condition to weed out flows that are solution flows:
Processing the filtered arrays
Now that the arrays are filtered for solution and non-solution flows, each individual flow in the filtered arrays need to be processed. This creates a nested apply to each loop, which is fine for this use case. Inside the new loop, the display name of a flow is composed for easier diagnosis and readability, followed by a compose for the flow’s body. This way we’re able to copy past the body to VS Code to inspect what properties a flow definition has. The final action in the loop is to append the following properties to the array variables we initialized in the begging (example is from the non-solution side of the branch):
Appending the contents of the variables to Excel
As both variables now contain all solution and non-solution flows, they can be appended to an Excel table. Information about different flows can then be manipulated and transformed further in Excel. The Add a row into a table Excel action is used to add flows to an Excel table. The unexpanded Excel actions in image 4 are some of my test actions and can be disregarded. With flows appended to Excel, we now have a list of solution and non-solution flows ready for further processing.
And there we have it! We’ve now looped through all flows in a tenant and pushed some information about each of our solution and non-solution flows into an Excel table for further processing.