{"id":1018,"date":"2024-08-16T11:39:00","date_gmt":"2024-08-16T16:39:00","guid":{"rendered":"https:\/\/automatethemundane.com\/index.php\/2024\/08\/16\/power-pipelines-and-enhanced-alm-part-8a-solution-watcher\/"},"modified":"2024-08-16T11:39:00","modified_gmt":"2024-08-16T16:39:00","slug":"power-pipelines-and-enhanced-alm-part-8a-solution-watcher","status":"publish","type":"post","link":"https:\/\/automatethemundane.com\/index.php\/2024\/08\/16\/power-pipelines-and-enhanced-alm-part-8a-solution-watcher\/","title":{"rendered":"Power Pipelines and Enhanced ALM Part 8a &#8211; Solution Watcher"},"content":{"rendered":"\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">With the solution register in place, we still face the risk of people (with the correct permissions) importing solutions that are not being tracked. This could be everything from PCF controls to solutions from developer\/sandbox environments. This does not mean there is something nefarious happening, but to be a good steward of governance we need to monitor what solutions are being installed. <\/p>\n\n\n<h1 class=\"wp-block-heading\">Diagram<\/h1>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-1024x634.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">This diagram is the core of what is going to be happening with the project. In the next post we will break it down further. <\/p>\n\n\n<h1 class=\"wp-block-heading\">Create new table for current PPM<\/h1>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The first step is to create a new Dataverse table that will be used to store approved solutions. It will consist of the following<\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>Solution ID<\/li>\n\n\n\n<li>Name (string)<\/li>\n\n\n\n<li>If the solution is tracked (boolean)<\/li>\n\n\n\n<li>Environment Name (String)<\/li>\n\n\n\n<li>Environment ID (string)<\/li>\n\n\n\n<li>Purpose (text area)<\/li>\n\n\n\n<li>ALM Solution (boolean)<\/li>\n\n\n\n<li>Who created the solution (email)<\/li>\n\n\n\n<li>When it was created (date time)<\/li>\n\n\n\n<li>Who approved the solution (email)<\/li>\n\n\n\n<li>When it was approved (date time)<\/li>\n<\/ul>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\"> The Environment Name and ID will only be used if the solution is added manually to an Environment. <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-1.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">View<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The main view will be as follows<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-2.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">Form<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The Main form will be as follows. Each of the fields will be set to read only. This is being done because at no time should people be adding or updating the data in the form itself. <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-3-1024x681.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">Business Rules<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Since the Environment ID and Name will not be used if the solution is apart of the ALM pipeline, we will want to hide them. The easiest way to do this is to create a business rule. <\/p>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The properties of the first condition will be if ALM solution is Yes<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-4.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Then components to set the visibility to No for the Environment ID, the Environment Name, Solution Created By, Solution Created on, Solution Approved by, and Solution Approved on.<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-5-1024x96.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">Security Role Updates<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">For both security roles (Admin and Developers), we will set the Tracking&#039;s table to Read Only. Updates will be coming via the Power Automate flows. The Form view is simply to see what is going on. <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-6-1024x159.png\" alt=\"\"\/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-7-1024x184.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">Ribbon Updates<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">In addition to the security role updates, we will remove the Add button from the ribbon of the Tracking&#039;s table. <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-8.png\" alt=\"\"\/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-9.png\" alt=\"\"\/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-10-1024x176.png\" alt=\"\"\/><\/figure>\n\n\n<h1 class=\"wp-block-heading\">Update current flows<\/h1>\n\n\n<h2 class=\"wp-block-heading\">1.1 Flow<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The 1.1 flow needs to be updated to add the row to the tracking table if it is coming via the pipeline. We will use the same output of the solution name as seen in LINK, mark the solution as tracked and set the purpose to, \u201cFrom Pipeline\u201d, then set the ALM Solution to Yes. <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-11.png\" alt=\"\"\/><\/figure>\n\n\n<h1 class=\"wp-block-heading\">Update MDA<\/h1>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Within the PPPM MDA, we will add the table to the Backend area.<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-12-1024x547.png\" alt=\"\"\/><\/figure>\n\n\n<h2 class=\"wp-block-heading\">Update Project Table<\/h2>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The last portion to update will be the project table. We will create a relationship between the watcher table and the Projects table.<\/p>\n\n\n<h3 class=\"wp-block-heading\">Relationships<\/h3>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-13.png\" alt=\"\"\/><\/figure>\n\n\n<h3 class=\"wp-block-heading\">Form<\/h3>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Within the Main form of the Projects table, we will add the subgrid of the Solutions Watcher Table<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-14-1024x653.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">With all these updates in order, we can push them all to Production to update the orchestrator flow. <\/p>\n\n\n<h1 class=\"wp-block-heading\">Updating the orchestrator flow<\/h1>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">This should be done after all other updates are in production and watcher table has been updated.<\/p>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">First, we need to search against the new solutions tracking table<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-15-1024x444.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Then, we need to look up the associated project<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-16.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Finally, update the get customer and lead info with the proper values<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-17-1024x417.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The pipeline will now be able to run as it did before with the updated table<\/p>\n\n\n<h1 class=\"wp-block-heading\">Building Watcher Solution<\/h1>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Since the purpose of this solution is to live in each of our Environments as a managed solution, we can not add this to our current solution or build it in our current Environment. We will need to build the solution in a separate development environment then export it as a managed solution. <\/p>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">In our personal dev Environment, we will create a solution called Solution Watcher and Environment Variable called Production Environment then create a flow called SW - 1.1 - When a new solution is created in the Environment <\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-18-1024x212.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The SW - 1.1 - When a new solution is created in the Environment it will be built as follows<\/p>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The trigger will be when a solution is added to the environment solutions table.<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-19.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">The first step is to filter out if the solution is coming in via Microsoft as part a built in feature. To do this, find the GUID of the user \u201cSYSTEM\u201d in the user table. If that matches the user that created the solution, we will terminate the flow.<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-20.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Using a FetchXML to find the user \u201cSYSTEM\u201d<\/p>\n\n\n<pre class=\"wp-block-code\"><code>&lt;fetch top=&quot;1&quot;&gt;\n  &lt;entity name=&quot;systemuser&quot;&gt;\n    &lt;filter&gt;\n      &lt;condition attribute=&quot;fullname&quot; operator=&quot;eq&quot; value=&quot;SYSTEM&quot; \/&gt;\n    &lt;\/filter&gt;\n  &lt;\/entity&gt;\n&lt;\/fetch&gt;<\/code><\/pre>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">If the created by equals the \u201cSYSTEM\u201d user then we will stop the flow<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-21-1024x353.png\" alt=\"\"\/><\/figure>\n\n\n<pre class=\"wp-block-code\"><code>outputs(&#039;List_rows_-_Users_Table&#039;)?[&#039;body\/value&#039;]?[0]?[&#039;systemuserid&#039;]<\/code><\/pre>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Now, we will look up who created the solution and write it to a compose<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-22.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Then, to get the current Environments Name and ID, we will need to run the workflow() expression (<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/logic-apps\/workflow-definition-language-functions-reference#workflow\">Reference guide for expression functions - Azure Logic Apps | Microsoft Learn<\/a>), then parse the JSON of the output, use the Power Apps for Makers Environments Action then filter it by the output of the workflow().<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-23.png\" alt=\"\"\/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-24.png\" alt=\"\"\/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-25.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">Next, we will list all rows in the Solutions tracking table in the Production Environment and filter it based on the Name<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-26.png\" alt=\"\"\/><\/figure>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">We will now add a condition that if no record is found, it will add a row to the Tracking table in Production<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-27.png\" alt=\"\"\/><\/figure>\n\n\n<pre class=\"wp-block-code\"><code>length(outputs(&#039;List_rows_from_selected_environment_-_Tracking_Table&#039;)?[&#039;body\/value&#039;])<\/code><\/pre>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">If it does not match, we need to add it to the production table Solutions Tracking<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/Untitled-28.png\" alt=\"\"\/><\/figure>\n\n\n<h1 class=\"wp-block-heading\">Closeout<\/h1>\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color: rgb(0, 0, 0)\">We will end here at the risk of exercising too much new information. In the next post, we will go over how to install the solutions and the actions that happens when a solution is added. <\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>With the solution register in place, we still face the risk of people (with the correct permissions) importing solutions that are not being tracked. This could be everything from PCF controls to solutions from developer\/sandbox environments. This does not mean there is something nefarious happening, but to be a good steward of governance we need [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1016,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,43,6,30,42,45,37,35],"tags":[],"class_list":["post-1018","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dataverse","category-environments","category-model-driven-app","category-power-automate","category-power-pipelines","category-pppm","category-security","category-tables","entry","has-media"],"jetpack_featured_media_url":"https:\/\/automatethemundane.com\/wp-content\/uploads\/2024\/08\/photo-1495125175509-8fddf00e56cd-1-scaled.jpg","_links":{"self":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts\/1018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/comments?post=1018"}],"version-history":[{"count":0,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts\/1018\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/media\/1016"}],"wp:attachment":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/media?parent=1018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/categories?post=1018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/tags?post=1018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}