CI/CD - Testing https://dynamics-chronicles.com/ en Dataverse Dynamics 365 Load testing for Model-driven app https://dynamics-chronicles.com/article/dataverse-dynamics-365-load-testing-model-driven-app <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Dataverse Dynamics 365 Load testing for Model-driven app</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/julienbiedermann" lang="" about="/user/julienbiedermann" typeof="schema:Person" property="schema:name" datatype="" class="username">julien.biedermann</a></span> <span property="schema:dateCreated" content="2024-01-19T15:00:24+00:00" class="field field--name-created field--type-created field--label-hidden">Fri, 01/19/2024 - 16:00</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p>Dataverse Dynamics 365 Load testing for Model-driven app</p> <h2>Introduction</h2> <p>In today's digital landscape, where user expectations for seamless, high-performing applications are at an all-time high, ensuring the reliability and scalability of software systems is paramount. Performance testing emerges as a critical practice in the software development lifecycle, aimed at evaluating the responsiveness, stability, and scalability of applications under various conditions.</p> <p>Performance testing encompasses various types, each serving specific objectives in evaluating the performance characteristics of a system. Here are some common performance test types:</p> <ul> <li><strong>Load Testing:</strong> Determines how a system behaves under expected load conditions by subjecting it to a specific number of users or transactions, assessing its response times and resource utilization.</li> <li><strong>Stress Testing:</strong> Pushes the system beyond its normal operational capacity to identify its breaking point and understand how it behaves under extreme conditions, helping determine its resilience and stability.</li> <li><strong>Soak Testing (Endurance Testing):</strong> Evaluates the system's performance over an extended period under a consistent load to detect memory leaks, resource depletion, or degradation of performance over time.</li> <li><strong>Spike Testing:</strong> Assesses the system's ability to handle sudden increases or spikes in load, such as traffic surges, to ensure it can scale appropriately and maintain performance without crashing or slowing down.</li> <li><strong>Scalability Testing:</strong> Measures how well the system can scale up or down to accommodate changes in load or user demand, helping determine its capacity to handle growth or fluctuations in traffic.</li> </ul> <p>In this article, we will focus how to conduct a load testing of a Dynamics 365 Model-driven App.</p> <h2>What is Load Testing ?</h2> <p>Load testing is a crucial aspect of performance testing focused on evaluating how a system behaves under specific levels of concurrent user activity or workload. The primary objective of load testing is to assess the system's performance, reliability, and scalability by subjecting it to simulated loads that represent expected usage patterns in real-world scenarios.</p> <p>During load testing, the system is subjected to various levels of load, typically represented by a specific number of concurrent users, transactions, or requests per unit of time. By gradually increasing the load, testers can observe how the system responds and identify any performance issues, such as slow response times, errors, or system crashes.</p> <p>When performing a load test, several important factors should be considered to ensure its effectiveness and relevance to the application's performance goals. Here are some key considerations:</p> <ul> <li><strong>Define Clear Objectives:</strong> Clearly define the objectives and goals of the load test. Understand what aspects of the application's performance you are testing, such as response times, throughput, scalability, or resource utilization.</li> <li><strong>Identify Key Scenarios:</strong> Identify the critical user scenarios or workflows that are most representative of real-world usage patterns. Focus the load test on these scenarios to simulate realistic user behavior.</li> <li><strong>Set Realistic Load Levels:</strong> Determine the appropriate load levels based on expected traffic volumes, peak usage periods, and scalability requirements. Ensure that the load levels accurately reflect the anticipated production environment.</li> <li><strong>Simulate Production Environment:</strong> Mimic the production environment as closely as possible during the load test. Consider factors such as network latency, hardware configurations, and software dependencies to create a realistic testing environment.</li> <li><strong>Analyze Results:</strong> Analyze the results of the load test thoroughly to identify performance issues, bottlenecks, and areas for improvement. Look for patterns in system behavior and correlate performance metrics to identify root causes of performance degradation.</li> </ul> <h2>How to load test a model-driven app ?</h2> <p>Microsoft is providing the following documentation : <a href="https://learn.microsoft.com/en-us/dynamics365/guidance/resources/test-scale-dynamics-365-solution">https://learn.microsoft.com/en-us/dynamics365/guidance/resources/test-scale-dynamics-365-solution</a></p> <p>In this article, we're gonna walk through using those test samples from Microsoft, step by step.</p> <h2>Requirements</h2> <ul> <li>Microsoft Dynamics 365 Customer Service environment with Customer Service-Hub model-driven application</li> <li>At least one user account with multi-factor authentication disabled</li> <li>Sample data in Dataverse <ul> <li>Min. 10 active accounts</li> <li>Min. 10 active products</li> <li>Min. 10 active subjects</li> </ul> </li> <li>Azure subscription (optional): It's a requirement if you plan to load test in Azure Load Testing (<a href="https://azure.microsoft.com/en-us/products/load-testing">https://azure.microsoft.com/en-us/products/load-testing</a>).</li> </ul> <h3>1. Download samples files</h3> <p>You will find all the samples files here : <a href="https://github.com/microsoft/Dynamics-365-FastTrack-Implementation-Assets/tree/master/Customer%20Service/Testing/At%20Scale/Samples">https://github.com/microsoft/Dynamics-365-FastTrack-Implementation-Assets/tree/master/Customer%20Service/Testing/At%20Scale/Samples</a></p> <p>In this walkthrough, we will use the CreateCase sample. To start, you can download the following files :</p> <ul> <li>CaseCreate.csv</li> <li>CreateCase.docx</li> <li>CreateCase.jmx</li> </ul> <h3>2. Install Apache JMeter</h3> <p>First, you need to install Apache JMeter <a href="https://jmeter.apache.org/usermanual/get-started.html#lets_start">https://jmeter.apache.org/usermanual/get-started.html#lets_start</a>.</p> <p>Apache JMeter is an open-source, Java-based software designed for load testing, performance testing, and functional testing of web applications.</p> <div class="alert alert-primary" role="alert">JMeter is not a browser, it works at protocol level. As far as web-services and remote services are concerned, JMeter looks like a browser (or rather, multiple browsers); however JMeter does not perform all the actions supported by browsers. In particular, JMeter does not execute the Javascript found in HTML pages. Nor does it render the HTML pages as a browser does (it's possible to view the response as HTML etc., but the timings are not included in any samples, and only one sample in one thread is ever displayed at a time).</div> <p>Apache JMeter has two modes, GUI mode and CLI mode.</p> <ul> <li>Use GUI mode for test creation, editing, and debugging.</li> <li>Use CLI mode to run a load test.</li> </ul> <h3>3. Populate CSV file</h3> <p>The file CaseCreate.csv contains the test user's information (username and password). Open the file and add your test user's credentials.</p> <p>Be careful, if the passwords contain special characters like <strong>% or #,</strong> it can be misinterpreted during test execution and generate errors.</p> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="2031403a-9172-4e58-8f99-1d7e215286a7" src="/sites/default/files/inline-images/casecreate_csv.png" /></p> <h3>4. Edit load test script</h3> <p>Run Apache JMeter in GUI mode by opening jmeter.bat in the bin folder.</p> <p>Open the <strong>CreateCase.jmx</strong> file.</p> <ol> <li>In Apache JMeter, click File – Open</li> <li>Use the explorer window to navigate to file or repository containing the CreateCase.jmx file.</li> <li>Select the CreateCase.jmx file and click Open.</li> </ol> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="515fb8ae-e691-4f51-81f2-d000c3ac5f89" src="/sites/default/files/inline-images/jmeter-1.png" /></p> <p>Update <strong>User Defined Variables</strong></p> <ol> <li>Click on the User Defined Variables element</li> <li>Update the following values <ol> <li>host – your Microsoft Dataverse environment url (e.g., yourorg.crm.dynamics.com)</li> <li>tenantId - your Microsoft 365 tenantid.</li> <li>cshAppId - the GUID of your Customer Service Hub model-driven application</li> </ol> </li> </ol> <p>Update the <strong>Thread Group Properties</strong></p> <ol> <li>Click on the CreateCase element</li> <li>Update the following values <ol> <li>Number of Threads (users) – total concurrent users to simulate.</li> <li>Ramp up period (seconds) – duration to increase the threads to the total number of threads.</li> <li>Loop Count – number of times to execute a single thread.</li> </ol> </li> </ol> <p>Configure the <strong>CSV Data Source</strong></p> <ol> <li>Click on the CSV Data Set Config</li> <li>Update the filename value with your updated csv file</li> </ol> <h3>5. Execute in GUI mode</h3> <p>Test can be started in GUI mode using one of the following methods:</p> <ol> <li>In the Run menu, click Start</li> <li>Click the Start button in the toolbar</li> <li>Right-click on CreateCase element and click Start</li> </ol> <div class="alert alert-warning" role="alert">Before running the test in GUI mode, ensure to reduce the number of threads (users). GUI mode should only be used for test creation, editing and debugging.</div> <p>You can use the View Results Tree to monitor the progress of the test and to debug, checking the request and response of the calls.</p> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="faf64260-d9b8-4792-a205-fa1310476b8e" src="/sites/default/files/inline-images/jmeter-2.png" /></p> <h3>6. Execute in CLI mode</h3> <p>GUI mode has limitations that might impact the performance of a load test. Use CLI mode when executing a load test at full scale.</p> <p>Test can be started in CLI mode following the steps below:</p> <ol> <li>Open CMD and change the directory to the jmeter bin folder</li> <li>Enter the following command</li> </ol> <pre> <code>jmeter -n -t path\CreateCase.jmx -l path\testresults.csv -e -o path\Results</code></pre> <table border="1" cellpadding="1" cellspacing="1" style="width: 500px;"> <thead> <tr> <th scope="col">Option</th> <th scope="col">Definition</th> </tr> </thead> <tbody> <tr> <td>-n</td> <td>This specifies JMeter is to run in cli mode.</td> </tr> <tr> <td>-t</td> <td>Name of JMX file that contains the Test Plan</td> </tr> <tr> <td>-l</td> <td>Name of JTL or CSV file to log sample results to</td> </tr> <tr> <td>-e</td> <td>Generate report dashboard after load test</td> </tr> <tr> <td>-o</td> <td>Output folder where to generate the report dashboard after load test. The folder must not exist or be empty.</td> </tr> </tbody> </table> <p>Sometimes, JMeter throws a heap dump along with an ‘out of memory’ error while executing the load test. In this case, you need to increase the heap size by editing the jmeter.bat file. The size has been updated to 8 GB in the example below:</p> <pre> <code>if not defined HEAP ( rem See the unix startup file for the rationale of the following parameters, rem including some tuning recommendations set HEAP=-Xms1g -Xmx8g -XX:MaxMetaspaceSize=256m )</code></pre> <h4>6.1 Report</h4> <p>After running the load test using CLI mode with the command above, a HTML report is generated in the folder defined.</p> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="ae0cf0c7-fc50-439e-9244-943ce72a9997" src="/sites/default/files/inline-images/report.png" /></p> <p>This report offers valuable insights into all requests conducted during the testing phase, presenting a comprehensive overview of the test execution. Additionally, it includes a detailed table illustrating the APDEX.</p> <p>APDEX (Application Performance Index) is a metric used to evaluate the user satisfaction of an application based on its response times. APDEX is a standardized method for measuring and reporting the satisfaction level of users with the responsiveness of web applications or services.</p> <p>APDEX categorizes response times into three zones:</p> <ul> <li>Satisfied: Response times that meet or exceed the user's expectations.</li> <li>Tolerating: Response times that are acceptable but not ideal.</li> <li>Frustrated: Response times that are considered unacceptable by users.</li> </ul> <p>The APDEX score is calculated based on the following formula:</p> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="38b1c812-45ed-48ee-93ca-8c2312d30a44" src="/sites/default/files/inline-images/apdex.png" /></p> <p>In JMeter, APDEX can be calculated using the following steps:</p> <ol> <li>Define the thresholds for response times that determine whether a sample is categorized as satisfied, tolerating, or frustrated. These thresholds are typically defined based on the application's performance goals and user expectations.</li> <li>Configure JMeter to track the response times of requests during the test execution.</li> <li>After the test execution, JMeter calculates the APDEX score based on the collected response times and the defined thresholds.</li> <li>The APDEX score provides a standardized measure of user satisfaction with the application's performance, helping testers and developers assess whether the application meets its performance goals and user expectations.</li> </ol> <p>By using APDEX in JMeter, testers can quantitatively measure and report the user satisfaction level of web applications or services, allowing them to identify performance issues and prioritize improvements to enhance the overall user experience.</p> <h3>7. Execute in Azure Load Testing</h3> <p>First, you need to deploy Azure Load Testing using your Azure subscription.</p> <p>Now, before diving into creating a load test in Azure Load Testing with a JMeter script, there are a few configurations we need to tweak:</p> <h4>7.1 Update CSV Data Set Config</h4> <p>In Azure Load Testing the JMX file and all related files are uploaded in a single folder. When you reference an external file in your JMeter script, verify that you only use the file name and remove any file path references.</p> <ol> <li>Remove any file path and reference the filename only in the filename field</li> <li>Set "Ignore first line" to False</li> <li>Remove the header row (userName,password) from CreateCase.csv</li> </ol> <p><img alt="CSV Configuration Azure Load Testing" data-entity-type="file" data-entity-uuid="be1d0bce-e2ed-4eda-8e24-37960957cd83" src="/sites/default/files/inline-images/alt1_0.png" /></p> <h4>7.2 Update User Defined Variables</h4> <ol> <li>Replace User Defined Variables with the following values :</li> </ol> <pre> <code>${__BeanShell(System.getenv("host"))} ${__BeanShell(System.getenv("tenantId"))} ${__BeanShell(System.getenv("cshAppId"))}</code></pre> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="800d329d-28c1-4b5e-a28f-41ea50af0325" src="/sites/default/files/inline-images/alt2.png" /></p> <h4>7.3 Create and run the test in Azure Load Testing</h4> <ol> <li>In Microsoft Azure, navigate to and open your Azure Load Testing resource.</li> <li>From "Get started" dashboard, select "Create" with the option "Upload a JMeter script" or create it from Tests menu.</li> <li>On the Basic tab, enter a test name and description</li> <li>On the Test plan tab, upload both CreateCase.jmx (the one adapted for Azure Load Testing) and CreateCase.csv (without header row) <ol> <li>Uncheck "Run test after create" if you don't want to run it directly after creation</li> </ol> </li> <li>On the Parameters tab <ol> <li> Add the correct values for the variables <strong>host</strong>, <strong>tenantId </strong>and <strong>cshAppId</strong></li> </ol> </li> <li>On the Load tab <ol> <li>Configure the test engine instances to a meet the target load for the test. The number of threads specified in the jmx file represents the number of thread (virtual users) executed by one test engine instance.</li> <li>Network traffic to Power Platform applications will be routed through Public networks.</li> </ol> </li> <li>On the Test criteria tab <ol> <li>(Optional) Define the criteria to specify the performance expectations of the system under test. Use the defined criteria to determine the failure conditions for the test when the criteria evaluate to true.</li> </ol> </li> <li>On the Monitoring tab <ol> <li>(Optional) Configure application components to monitor server-side metrics during the test run.</li> </ol> </li> <li>Once all tabs completed, you can review and create your test.</li> <li>Then, if you have unchecked the box at point 4.1, you need to open and run your test manually</li> <li>Once the test is executed, you can open it to see the load test results</li> </ol> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="676179a3-f2cd-4b85-883a-46e6b063b861" src="/sites/default/files/inline-images/alt_setup1.png" /></p> <p><img alt="Upload files" data-entity-type="file" data-entity-uuid="7d47373a-d0e8-4c07-bf5b-34dd9c2c0101" src="/sites/default/files/inline-images/alt_setup2.png" /></p> <p><img alt="Azure Load Testing Parameters" data-entity-type="file" data-entity-uuid="27143bc3-8bbb-4258-be8d-38eafce28f00" src="/sites/default/files/inline-images/alt_setup3.png" /></p> <p><img alt="Dataverse Dynamics 365 Load testing for Model-driven app" data-entity-type="file" data-entity-uuid="104141ef-e259-4064-9d92-74af6cbc66d8" src="/sites/default/files/inline-images/alt_results.png" /></p> <div class="alert alert-warning" role="alert">I'd like to note that I conducted the load test within a trial environment. This could account for the observed performance not meeting expected standards.</div> <h2>Conclusion</h2> <p>I hope you enjoyed this tutorial on running a load test sample in a model-driven app. This article provided an overview of load testing using JMeter and Azure Load Testing, and perhaps it will inspire other bloggers to delve into topics such as:</p> <ul> <li>How to build his own test case in JMeter ?</li> <li>How to analyze the results ?</li> </ul> <p>In conclusion, it's crucial to recognize that JMeter has limitations when it comes to measuring user experience elements occurring at the client side, such as load time or page rendering. JMeter functions as a performance testing tool but does not emulate a real browser. If we aim to test the user interface (UI) using JMeter, we'd need to incorporate tools like the WebDriver Sampler. This component facilitates integration with the Selenium browser automation framework, enabling more comprehensive UI testing capabilities within the performance testing context. Essentially, JMeter, while proficient at server-side performance assessments, requires additional tools like WebDriver Sampler for thorough evaluation of user interface aspects.</p> <h2 class="title">Dataverse Dynamics 365 Load testing for Model-driven app</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2024-02/article1.png</div> </div> </div> </div> </div> Fri, 19 Jan 2024 15:00:24 +0000 julien.biedermann 742 at https://dynamics-chronicles.com PowerApps Model Driven UI Testing with Playwright https://dynamics-chronicles.com/article/powerapps-model-driven-ui-testing-playwright <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">PowerApps Model Driven UI Testing with Playwright</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/zsoltzombik" lang="" about="/user/zsoltzombik" typeof="schema:Person" property="schema:name" datatype="" class="username">zsoltzombik</a></span> <span property="schema:dateCreated" content="2023-12-07T15:16:37+00:00" class="field field--name-created field--type-created field--label-hidden">Thu, 12/07/2023 - 16:16</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>PowerApps Model Driven UI Testing with Playwright</em></p> <h2>Introduction</h2> <p>In the ever-evolving landscape of software development, test automation has emerged as a pivotal trend, revolutionizing the way we build and deploy software. For businesses embracing Agile and DevOps methodologies, automated testing has become a cornerstone practice, enabling faster development and deployment cycles. In this article, we embark on a journey to explore the profound benefits of automated testing and why it holds such paramount importance in the context of software development, particularly within Dynamics 365 Model Driven Apps. We'll also touch upon the pivotal role of Playwright in automating UI testing within this environment. So, let’s discover the major benefits of automated testing and why automation in software testing matters:</p> <ul> <li><strong>Accelerated Development and Delivery:</strong> UI Test automation significantly reduces testing time, as automated tests can be executed rapidly and repeatedly. This results in shorter software development cycles, more frequent releases, quicker updates, and faster time-to-market delivery. The integration of automation, particularly with Playwright, expedites the testing process within Dynamics 365 Model Driven Apps, enhancing the development speed.</li> <li><strong>Enhanced Productivity:</strong> Automated tests operate without human intervention, enabling testing at any time, even during non-working hours. This autonomy minimizes the time software developers and quality assurance teams spend on testing, allowing them to focus on critical tasks. With automation, engineers can prioritize the creation of new features and improvements, ultimately boosting productivity.</li> <li><strong>Precision and Accuracy:</strong> Automated testing reduces the risk of human errors during the testing process. Unlike human testers who may make mistakes, automated tests execute precisely according to predefined criteria. This precision contributes to more reliable and error-free releases, minimizing the risk of failure.</li> <li><strong>Superior App Quality and Performance:</strong> Automated testing offers extensive test coverage, ensuring high-quality and high-performance applications. It allows for simultaneous testing of thousands of test cases across multiple platforms and devices, a feat difficult to achieve manually. With automation, complex and lengthy test cases can be created quickly, elevating the overall quality of applications.</li> <li><strong>Immediate Feedback:</strong> Automated testing provides instant feedback to developers, enabling quick response to failures. This immediate feedback accelerates the bug-fixing process and ensures a better user experience, leading to higher customer satisfaction. In contrast, manual testing can slow down the development and update process.</li> <li><strong>Enabling CI/CD and DevOps:</strong> Test automation is pivotal for implementing Continuous Integration (CI) and Continuous Delivery (CD) practices. In the CI/CD pipeline, every code commit needs to be tested swiftly and efficiently, a task perfectly suited for automation. Automation, including Playwright for UI testing, streamlines the transition to Continuous Testing and Delivery.</li> </ul> <p>Incorporating test automation, especially within the context of Dynamics 365 Model Driven Apps, is not just a trend; it's a necessity. The benefits of automated testing continue to expand as tools and testing frameworks evolve. Beyond traditional automated testing, new areas like model-based testing, predictive analysis, robotics automation, and API test-case automation are emerging. To stay at the forefront of technological evolution, implementing test automation is imperative. It accelerates development, enhances efficiency, accuracy, and productivity, all while maintaining the highest standards of app quality and performance. Partnering automation with a robust testing solution and integrating it with your CI/CD tools ensures that you harness its full potential efficiently on real devices, propelling your software development to new heights without compromising on quality or performance.</p> <ul> </ul> <h2>Setting Up Your Environment for Playwright in Dynamics 365</h2> <h3>Prerequisites for Playwright Setup</h3> <p>Before diving into using Playwright for UI testing, ensure you have the following prerequisites in place:</p> <h4><strong>Native Installation</strong></h4> <ul> <li>Playwright Test for Visual Studio Code: This is available on Visual Studio Marketplace. Make sure you have version 1.19 or newer to leverage the full capabilities of Playwright in Visual Studio Code.</li> </ul> <h4><strong>Playwright NPM Package</strong></h4> <ul> <li><strong>Cross Platform Support:</strong> Playwright is designed for versatility, supporting Windows, Linux, and macOS. It can be used for testing both locally and on Continuous Integration (CI) platforms such as Azure DevOps, GitHub. </li> <li><strong>Browser Testing Flexibility:</strong> It offers extensive testing capabilities, including both headless and headed modes. For mobile testing, Playwright provides native mobile emulation for Google Chrome on Android and Mobile Safari, ensuring comprehensive coverage across devices.</li> </ul> <h4><strong>Azure Subscription (Optional)</strong></h4> <ul> <li><strong>Enhanced Testing with Microsoft Azure:</strong> While not mandatory, an active Microsoft Azure subscription is recommended for a more robust testing framework. It becomes essential if you're planning to conduct automated tests within Azure or integrate load testing into your CI/CD pipelines. Utilizing Azure enhances your testing scope and efficiency, particularly for complex Dynamics 365 environments.</li> </ul> <p>Having these prerequisites in place sets a solid foundation for effective and efficient use of Playwright in your Dynamics 365 UI testing projects.</p> <h3>Installation and Configuration</h3> <p>Before you start, you will need install the following:</p> <ul> <li><strong>NodeJS </strong>- <a href="https://bit.ly/getnodejs">https://bit.ly/getnodejs</a></li> <li><strong>VSCode </strong>- <a href="https://bit.ly/downloadvscode">https://bit.ly/downloadvscode</a></li> </ul> <p>When installing Node, select the LTS version and accept the defaults.</p> <p>After installation, you should check you have Node installed correctly, at command line type:</p> <pre> <code class="language-javascript">npm</code></pre> <p><img alt="PowerApps Model Driven UI Testing with Playwright" data-entity-type="file" data-entity-uuid="1298b6e6-812f-451d-8d07-63fc3d4fc08c" src="/sites/default/files/inline-images/Playwright_extension0.png" /></p> <p>You should see the npm command help information displayed.</p> <p>To check you had the VSCode installed correctly, at the command line type:</p> <pre> <code class="language-javascript">Code .</code></pre> <p>This should open VSCode at the code folder location you are currently in.</p> <h3>UI Test Project folder setup</h3> <p>Playwright UI Test project do not have a project file like C# (.csproj)  so you can simply create a new folder with the name of your project. I will use UITest.</p> <p>At the command line, type:</p> <pre> <code class="language-javascript">Mkdir UITest Cd UITest</code></pre> <h3>Install Playwright Test for Visual Studio Code</h3> <p>Open Visual Studio Code.</p> <p>Select Extension, then search for Playwright Test for VSCode.</p> <p><img alt="Introduction to Dynamics 365 Model Driven Apps UI Testing with Playwright" data-entity-type="file" data-entity-uuid="6234db30-87a2-4e8e-ba5a-75b7bb7e60fd" src="/sites/default/files/inline-images/Playwright_extension1.png" /></p> <p>Then click on Install.</p> <p>Open the command panel (Ctrl + Shift + P), and then enter the following command: <strong>Install Playwright</strong>.</p> <p><img alt="PowerApps Model Driven UI Testing with Playwright" data-entity-type="file" data-entity-uuid="cd701b6a-de78-435f-92bd-4027e24a0191" src="/sites/default/files/inline-images/Playwright_extension2.png" /></p> <p>On the next screen, select the browser(s) you want to run your tests in. You can change the setting later in the <em>playwright.config</em> file.</p> <p>Finally you created your first Playwright test project.</p> <h3>Get a Test Environment</h3> <p>Next, you need a Dynamics 365 environment that you can run tests in. If you're finalizing an implementation project, you probably have a test environment already. If you don't, you can get a free 30-day trial (for this article, we provisioned a trial Dynamics 365 Customer Service Environment.</p> <h3>Setting up Test Environment</h3> <p>To optimize the test environment for automated testing, especially when using Playwright with a model driven app, follow these steps:</p> <h4>Disable Security Defaults</h4> <ul> <li><strong>Adjust Security Defaults:</strong> For the purpose of automated testing it's necessary to turn off security defaults. This ensures that the automated tests can run without unnecessary interruptions interruptions or blocks, which are typically in place for security reasons. Please follow this link: <a href="https://learn.microsoft.com/en-us/entra/fundamentals/security-defaults">https://learn.microsoft.com/en-us/entra/fundamentals/security-defaults</a></li> </ul> <h4>Create and Configure User Accounts</h4> <ul> <li><strong>Access Microsoft 365 Admin Center:</strong> Utilize the Microsoft 365 admin center to set up the required user account(s) for testing.</li> <li><strong>Assign Security Roles:</strong> Properly assign the necessary security roles to these accounts to ensure they have the appropriate access levels for testing.</li> </ul> <p>By carefully configuring the test environment as described, you create a more controlled and effective setting for conducting automated tests using Playwright in Dynamics 365.</p> <h3>First Playwright Test</h3> <p>Let's create our first test! Playwright provides convenient utilities for capturing your browser interactions and generating test scripts. To accomplish this, simply execute the Playwright Node command with the <em>codegen </em>argument. When you include the URL of your model-driven Power App as a parameter, it initiates a browser session that records the user's actions within the Playwright Inspector.</p> <p>To inititate the recording a new test, type this command on Visual Studio Code Terminal window:</p> <pre> <code class="language-javascript">npx playwright codegen https://&lt;you-crm-org&gt;.crm4.dynamics.com/main.aspx?appid=&lt;app guid&gt;</code></pre> <p>Playwright open a new browser instance and launch Playwright Inspector:</p> <p><img alt="PowerApps Model Driven UI Testing with Playwright" data-entity-type="file" data-entity-uuid="88710191-fcb5-4d9f-8fc3-5526f4f57302" src="/sites/default/files/inline-images/First%20Test.png" /></p> <p><img alt="Introduction to Dynamics 365 Model Driven Apps UI Testing with Playwright" data-entity-type="file" data-entity-uuid="61f95da0-e58e-4472-bb23-14bcd03eae3e" src="/sites/default/files/inline-images/First%20Test2.png" /></p> <p>Enter the credentials.</p> <p>Then select <strong>Service </strong>-&gt; <strong>Cases</strong>.</p> <p>Click on <strong>New Case</strong> button.</p> <p>Fill the form, then click on the <strong>Save</strong> button.</p> <p>Finally, take a look at the Playwright inspector window, it generated the code of our test.</p> <p>After the test script generated, we need to create a new test file under the tests folder such as and copy the code generated by Playwright Inspector.</p> <p> </p> <p><img alt="Introduction to Dynamics 365 Model Driven Apps UI Testing with Playwright" data-entity-type="file" data-entity-uuid="da431062-f6a9-447a-978f-9fa576746f59" src="/sites/default/files/inline-images/Runnimgtest_2.png" /></p> <p>Select the Test icon on Visual Studio Code.</p> <p>Find the test we created previously.</p> <p>Click in <strong>Debug Test</strong> button.</p> <p><img alt="PowerApps Model Driven UI Testing with Playwright" data-entity-type="file" data-entity-uuid="f0577589-e636-4f10-9a0e-e017f7137ff9" src="/sites/default/files/inline-images/Runnimgtest3.png" /></p> <p>It kicks off by running tests in debug mode, and eventually, you'll spot the test results right in the terminal window.</p> <p><img alt="Running Playwright Tests" data-entity-type="file" data-entity-uuid="afd50dc2-7238-4525-9e5f-d99facf81e61" src="/sites/default/files/inline-images/Runnimgfinal.png" /></p> <h2>Here's a small preview of the upcoming articles on Playwright.</h2> <ul> <li>The upcoming article, <strong>Writing Effective UI Tests with Playwright in Dynamics 365</strong> will focus on mastering Playwright's testing capabilities, including automated browser testing and managing dynamic content. It will provide a step-by-step guide to developing test scripts specifically tailored for Dynamics 365 UI, complete with example scripts and scenarios, and conclude with strategies for debugging and troubleshooting these tests.</li> <li>Third article <strong>Advanced Playwright Features for Dynamics 365 Testing</strong> will cover sophisticated techniques for working with multiple browsers and devices, including cross-browser and responsive testing. It will also delve into Playwright's advanced capabilities like network interception, mocking, and visual regression testing, along with their integration in CI/CD pipelines.</li> <li>Fourth article titled <strong>Best Practices and Optimizing Test Performance</strong> focuses on creating maintainable test code with well-organized structure and reusable components. It will discuss strategies to enhance test performance, such as parallel testing and methods to reduce test flakiness, and will conclude with approaches for monitoring and reporting test results.</li> </ul> <h2 class="title">PowerApps Model Driven UI Testing with Playwright</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2023-11/1970%27s%20sci%20robot%20testing%20software%2C%20studio%20light%2C%20on%20an%20emerald%20colored%20background.jpg</div> </div> </div> </div> </div> Thu, 07 Dec 2023 15:16:37 +0000 zsoltzombik 634 at https://dynamics-chronicles.com Error handling in Power Automate flows https://dynamics-chronicles.com/article/error-handling-power-automate-flows <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Error handling in Power Automate flows</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/sergio-ferraresi" lang="" about="/user/sergio-ferraresi" typeof="schema:Person" property="schema:name" datatype="" class="username">Sergio Ferraresi</a></span> <span property="schema:dateCreated" content="2023-05-30T08:22:56+00:00" class="field field--name-created field--type-created field--label-hidden">Tue, 05/30/2023 - 10:22</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Error handling in Power Automate flows</em></p> <p><span><span><span>Low Code solutions using Power Automate flows are becoming more and more popular in CRM Dynamics projects. But often low code solutions show maintenance issues because of the tendency of the developers (myself included of course) to neglect the exception </span></span></span><span><span><span>handling aspects of the power automate flows under the assumption that</span></span></span><span><span><span> "low code" also means "low error handling". </span></span></span></p> <h3>Our objectives</h3> <p>With this article I will cover the topic of how to handle errors in Power Automate flows and how to track them for a later analysis of them. What we need to achieve is a way of:</p> <ol> <li>capturing the errors that have been raised</li> <li>identifying the action that has failed</li> <li>getting a description of the reason for this failure</li> </ol> <p>Let's get started.</p> <h3>Out-of-the-box features: some limitations</h3> <p>We will first have a look at the out-of-the-box features offered by Power Automate to check the flow executions.</p> <p>When you need to verify when a flow has run and whether the flow execution was successful or not, you open the flow and you are presented a run history reporting the flow executions of the flow in the last 28-days:</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="ca4bd658-64a5-444f-9d70-6fc6f79ffb27" src="/sites/default/files/inline-images/2023-05-07%2015_57_06-Remote%20Desktop%20Web%20Client.png" /></p> <p>In this view you do not get any details about the reason for the failure. You need to open the specific execution that failed by double clicking on it and you get the reason for the failure in the "Error Details" pane on the right hand side of the run view.</p> <h4><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="18ae0f4c-c314-4177-bd1d-9445e25cc7ac" height="473" src="/sites/default/files/inline-images/2023-05-08%2017_34_15-Phoenix%20Project%20Survey%20-%20Message%20%28HTML%29.png" width="939" /></h4> <p>This way of inspecting the errors requires a periodical check of the flow executions: a time consuming action that can be easily avoided with the following solution.</p> <h3>Handling errors occurring in one action</h3> <p>Let's suppose to have a flow responsible for updating the owning team of an account according to the country where the company is based in.</p> <p>We are going to trigger the flow when a new account is created or when its address is modified.</p> <p>If the company address contains a USA address, the flow assigns the company to the USA Team, otherwise it will be assign to the Non-USA Team.</p> <p>The flow structure is the following one:</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="7295cb59-06f2-4d15-9c06-d88929ca4026" height="477" src="/sites/default/files/inline-images/2023-05-08%2018_07_28-Phoenix%20Project%20Survey%20-%20Message%20%28HTML%29.png" width="922" /></p> <p>If the update of the account owning team is successfully performed we want to send an email to confirm the successful assignment of its owner.</p> <p>We also want to handle possible problems occurring in the update action called "<em>Update Account owning team</em>": in case an issue occurs while updating the account, we do not want the email to be sent, instead we want to catch the error, get its details and log the error for a later analysis.</p> <p>At the moment we suppose to log the error in the Dataverse: I created a custom table called "Error Log" with the needed fields to store the error details. I will propose a slightly different solution later in the article.</p> <p>The first thing we need to do to handle the update errors is to create a parallel branch after the update action as shown below.</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="21c167ae-ccfd-4683-85cf-d6bbbd9921e7" height="437" src="/sites/default/files/inline-images/2023-05-08%2017_52_29-Power%20Apps%20_%20Flows.png" width="925" /></p> <p>After adding the branch we will have two actions running in parallel after the update action.</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="79527638-9eef-4d90-8390-d9a662450cda" height="514" src="/sites/default/files/inline-images/2023-05-08%2018_11_13-Power%20Apps%20_%20Flows.png" width="913" /></p> <p>Our objective is to tell the flow to execute the branch on the right (Log error branch) <strong>only in case</strong> an issue with the previous action, "Update Account owning team", occurs. To achieve this we use the feature "<strong>Configure run after</strong>" of the "Log error" action.</p> <p>Using Configure run after you can tell the flow to run the specific action if and only if an error has occurred in the previous action. You can configure “Run After” to almost all Power Automate actions by simply clicking on the three dots on the right corner of the action which you wish to configure and select “Configure run after” from the drop-down menu.</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="e9e187ab-10e6-4892-940d-2d9d394e774e" height="614" src="/sites/default/files/inline-images/2023-05-08%2018_18_59-Power%20Apps%20_%20Flows.png" width="913" /></p> <p>From there, you can select either one of the options or multiple options.</p> <ul> <li><strong>Is successful</strong> – If the action runs successfully.</li> <li><strong>Has failed</strong> – An action has any type of failure (except timeout).</li> <li><strong>Is skipped</strong> – An action was skipped. Actions are skipped either when a condition is not met, or when a previous action before that fails.</li> <li><strong>Has timed out</strong> – An action times out. This can happen if the call to the backend times out (120 seconds), or for long-running actions such as approvals, after 30 days.</li> </ul> <p>We want to determine what the flow has to do when our update fails: we then select the "<strong>Has failed</strong>" option.</p> <p><img alt="Select option in Configure run after" data-entity-type="file" data-entity-uuid="831b70cb-759a-44ba-ace4-67dba815ce87" src="/sites/default/files/inline-images/2023-05-08%2018_21_54-Power%20Apps%20_%20Flows.png" /></p> <p>The error handling branch is displayed in the flow designer with a dotted line:</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="b24ffa4d-6d81-4a18-9cce-74e4909e3eaf" src="/sites/default/files/inline-images/2023-05-08%2018_27_30-Power%20Apps%20_%20Flows.png" /></p> <p>At this point our flow will send the email when the assignment is successfully performed and it will execute the "Log error" action if the update fails.</p> <p>Having handled the possible update errors in the Log error branch, this flow will result to have successfully run even if an error while updating the account occurred.</p> <p>To avoid this and ensure that the failed flow is marked as "failed" in the run history, add a <strong>Terminate </strong>action at the end of the error handling branch as shown in the picture below.</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="58496447-99a1-4363-99e4-782b064a0b61" src="/sites/default/files/inline-images/2023-05-08%2019_07_39-Power%20Apps%20_%20Flows.png" /></p> <p>What we are still missing now is how to get the error details to be logged into the Dataverse.</p> <p>To get this information we can rely on built in functions. The function we need in this case is called <strong>actions</strong>: This function takes the action name as input parameter and it returns an action's output at runtime in JSON format. The JSON format has approximately the following structure (further fields could eventually be present):</p> <pre> <code class="language-json">{   "name": "Update_Account_owning_team",   "inputs": {     "parameters": {       "entityName": "accounts"     }   },   "outputs": {     "statusCode": 400,     "body": {       "error": {         "code": "0x80040203",         "message": "Attribute: ownerid cannot be set to NULL"       }     }   },   "startTime": "2023-05-10T12:08:27.6333954Z",   "endTime": "2023-05-10T12:08:49.3524607Z",   "code": "BadRequest",   "status": "Failed" }</code></pre> <p>From the JSON structure of the returned value I will extract the error message and I will put it into the "Error message" field of my custom entity "Error log" as shown in the picture below.</p> <p><img alt="Actions function" data-entity-type="file" data-entity-uuid="fd0bcda1-c40a-4651-8405-0351aefb0aee" src="/sites/default/files/inline-images/2023-05-08%2021_42_19-Power%20Apps%20_%20Solutions%20-%20ErrorHandling.png" /></p> <p>As the error message is nested in the JSON message, we need to use the following syntax to extract it :</p> <p>actions('Update_Account_owning_team')?['outputs']?['body']?['error']?['message']</p> <p>In our custom entity "Error log" we will now find all the errors occurred while updating the owning team of the accounts and the specific error message.</p> <p><img alt="Error handling in Power Automate flows" data-entity-type="file" data-entity-uuid="d365a7f0-c4d5-4f33-90e4-9dbabb58037d" src="/sites/default/files/inline-images/2023-05-10%2015_15_56-Error%20Logs%20Active%20Error%20Logs%20-%20Dynamics%20365.png" /></p> <h3>Handling errors in multiple actions</h3> <p>So far we handled the errors that could happen in a single action. A flow usually consists of a lot of actions and handling the errors using "Configure run after" for each action in the flow is not an efficient approach. In order to be able to handle the errors occurring in multiple actions the best solution is to group the actions using the so called <strong>Scope </strong>blocks.</p> <p>In the scope action I can nest all my flow actions (the initialisation of the variables cannot be nested into a Scope action and must be kept outside, before entering the scope) as shown below. I will call this scope block "<strong>Try</strong>" (according to the error handling patterns in other programming languages). </p> <p>After the Try block I will then add another Scope action that I will call "<strong>Catch</strong>": on the Catch action I will then set the "Configure run after" exactly as I did for the single action before. The Catch block will then be executed <strong>only if one or more actions included in the Try block</strong> fail.</p> <p><img alt="Try-Catch blocks" data-entity-type="file" data-entity-uuid="8e7828ab-4d80-4d38-a8cc-6009830ad0eb" src="/sites/default/files/inline-images/2023-05-10%2016_27_18-Power%20Apps%20_%20Solutions%20-%20ErrorHandling.png" /></p> <p>In the Catch block we now need to get the details of what happened in the Try block: as in the Try block several actions could have thrown an error, we cannot use anymore the <strong>actions </strong>function as it refers to a specific action. Instead we will use the expression function called <strong>result. </strong>This function returns an array of objects consisting of the Input / Output information of the top-level actions in the specified scoped action. I now want to capture the Output of the actions in the Try block that have failed.</p> <p>To do it I need to filter the array of objects returned by the "result" function to get the objects of the failed actions only. This can be achieved using the <strong>Filter array</strong> action. Finally we can use the action "Create HTML Table" to store the returned results in a structured way. We will rename this action "Select result".</p> <p><img alt="Catch block" data-entity-type="file" data-entity-uuid="1d42cf83-b8a2-4989-8e62-f9c974aa530c" src="/sites/default/files/inline-images/2023-05-10%2017_27_12-Remote%20Desktop%20Web%20Client.png" /></p> <p>The <strong>result </strong>expression is <strong>result('Try')</strong>, the <strong>status</strong> expression: <strong>item()?[status] </strong>while the <strong>Body </strong>is <strong>body('Filter_array_-_Status_=_Failed').</strong></p> <p>Once you have all your information stored in the "Select result" action you are ready to use it and put it into the proper fields of the Error Log record.</p> <p>To include information about the flow in your error log, such as the name of the flow, you also need to use the power automate function called <strong>workflow</strong>. This function returns the Id, the name, the type and some other information about the running flow. We will use it for getting the flow name and for retrieving the flow information needed for building the Url of the specific execution or run where the log was written (you can find the syntax of it below).</p> <p>This is how our catch block looks like:</p> <p><img alt="Final catch block" data-entity-type="file" data-entity-uuid="5b81723f-daa6-45fa-b2e0-6c2a4209067a" src="/sites/default/files/inline-images/2023-05-11%2011_39_08-Window.png" /></p> <p>Here the expressions of the fields above:</p> <p><strong>Action </strong>: outputs('Select_Result')?['body']?[0]?['Action'] </p> <p><strong>Error message</strong>: outputs('Select_Result')?['body']?[0]?['Message']</p> <p><strong>Execution Url</strong>: concat('https://flow.microsoft.com/manage/environments/', workflow()?['tags']['environmentName'], '/flows/', workflow()?['name'], '/runs/', workflow()?['run']['name'])</p> <h3>Using Flow templates </h3> <p>When you create a new flow you get an empty page without any of the logic we just described. In order not to write the same error handling code every time you create a new flow you can prepare a flow including the <strong>Try-Catch</strong> pattern we just explained and use this flow as a template when you create a new one.</p> <p>This is how the template flow would look like:</p> <p><img alt="Flow template" data-entity-type="file" data-entity-uuid="d224305f-f048-4421-9feb-e16060ee594a" src="/sites/default/files/inline-images/2023-05-10%2017_23_58-Remote%20Desktop%20Web%20Client.png" /></p> <p> </p> <p>The <strong>Try</strong> block will contain the whole flow logic with its different actions.</p> <p>The <strong>Catch error</strong> block can be the same for every flow and does not need to be changed when you start to develop a flow: this block will be like the one presented in the previous picture..</p> <p>I also added a <strong>Catch success</strong> block where you can put the actions you want to take when the flow has successfully carried out its job, as sending an email or setting some flag or status to completed on other tables. You might want to track the executions of the flows in both cases, either it fails or it successfully runs: in this case you can log it in the same table with different status in the two catch blocks.</p> <p>I mentioned before that using a custom entity to keep track of the flow failures is not an ideal solution because the Dataverse can quickly increase its size with a lot of error messages. An alternative solution would be using a Power BI Data Set or an external database for storing the error records, depending on your storage availability.</p> <p>Well, we've come to the end of this article: I hope you enjoyed reading it and that it can be useful for your projects.</p> <p>Meet you in the next Chronicle!</p> <h2 class="title">Error handling in Power Automate flows</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2023-05/Error%20handling%20in%20Power%20Automate%20flows.jpeg</div> </div> </div> </div> </div> Tue, 30 May 2023 08:22:56 +0000 Sergio Ferraresi 644 at https://dynamics-chronicles.com Power Platform Managed Environments and Pipelines https://dynamics-chronicles.com/article/power-platform-managed-environments-and-pipelines <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Power Platform Managed Environments and Pipelines</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/marioortegaaguayo" lang="" about="/user/marioortegaaguayo" typeof="schema:Person" property="schema:name" datatype="" class="username">mario.ortegaaguayo</a></span> <span property="schema:dateCreated" content="2023-02-09T12:39:41+00:00" class="field field--name-created field--type-created field--label-hidden">Thu, 02/09/2023 - 13:39</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Power Platform Managed Environments and Pipelines:</em></p> <p><span><span><span><strong><em>What is Managed Environments?</em></strong></span></span></span></p> <p><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Managed Environments is a suite of capabilities that allows system administrators to manage Power Platform with more control, less effort, and more insights. Administrators can use Managed Environments with any type of environment except the Developer environments.</span></span></span></span></span></p> <p><span><span><span>Once enabled, users will need a Power Apps, Power Automate or 365 license Premium to use respective resources in this environment.</span></span></span></p> <p><span><span><span>Managed Environments from an IT perspective allow administrators to get better insights and feedback into how the environment is used.</span></span></span></p> <p><span><span><span>The principal features that Managed environments offer to administrators are:</span></span></span></p> <p> </p> <ol> <li><span><span><span><strong>Weekly digest</strong>: system administrators will receive by email <span><span>analytics about top apps, most impactful makers, and inactive resources you can safely clean up. Weekly digest will be delivered to administrator mailboxes once a week.</span></span></span></span></span></li> </ol> <p> </p> <ol start="2"> <li><span><span><span><strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Sharing Limits</span></span></strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>: Administrators can limit the number of users who can share canvas apps. </span></span></span></span></span></li> </ol> <p> </p> <ol start="3"> <li><span><span><span><strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Data Policies</span></span></strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>: Administrators can easily identify all the data policies that are applied to an environment. Data policies define the consumer connectors that data can be shared with. They make sure that data is managed in a uniform manner across your organization. </span></span></span></span></span></li> </ol> <p> </p> <ol start="4"> <li><span><span><span><strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Solution checker</span></span></strong><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>: With the solution checker feature, you can perform a rich static analysis check on your solutions against a set of best practice rules and quickly identify these problematic patterns. After the check completes, administrator receives a detailed report that lists the issues identified, the components and code affected, and links to documentation that describes how to resolve each issue. </span></span></span></span></span></li> </ol> <p> </p> <p><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Solution checker analyzes three solution components:</span></span></span></span></span></p> <ul> <li><span><span><span><span><span>Dataverse custom workflow activities.</span></span></span></span></span></li> <li><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Dataverse web resources (HTML and JavaScript).</span></span></span></span></span></li> <li><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Dataverse configurations, for instance SDK message steps.</span></span></span></span></span></li> </ul> <p> </p> <p><span><span><span><strong><em>How to enable Managed Environments</em></strong></span></span></span></p> <ol> <li><span><span><span>In the Power platform admin center, in the left panel, select Environments.</span></span></span></li> <li><span><span><span>Select the check mark to the left of an environment.</span></span></span></li> <li><span><span><span>On the command bar, select Enable Managed Environments. If the environment is already managed, select Edit Managed Environments.</span></span></span></li> <li><span><span><span>Configure the settings, and then select Enable or Save.</span></span></span></li> </ol> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="68bf0e0f-2510-4af1-a7f9-1d5a085b4e4e" src="/sites/default/files/inline-images/Picture1_4.png" class="align-center" /> <p> </p> <p><span><span><span>It needs to be highlighted three points regarding user permissions.</span></span></span></p> <ol> <li><span><span><span>You need to be Administrator (role of Global administrator, Power Platform service administrator or Dynamics 365 administrator in Azure Active Directory.</span></span></span></li> <li><span><span><span><span><span>Any user with permissions to see the environment details can view the Managed Environments properties for an environment.</span></span></span></span></span></li> <li><span><span><span><span><span>Users with the Delegated Admin role or the Environment Admin security role are not allowed to change the Managed Environments property in an environment.</span></span></span></span></span></li> </ol> <p> </p> <p><span><span><span><strong><em>What are pipelines in Power Platform?</em></strong></span></span></span></p> <p><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Pipelines in Power Platform aim to democratize application lifecycle management (ALM) for Power Platform and Dynamics 365 customers by bringing ALM automation, continuous integration and continuous delivery (CI/CD) capabilities into the service in a manner that is more approachable for all makers, admins, and developers.</span></span></span></span></span></p> <p><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Pipelines significantly reduce the effort and domain knowledge previously required to realize the ROI from adopting healthy, automated ALM processes within your team or organization.</span></span></span></span></span></p> <p><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US"><span>Pipelines offer the next advantages:</span></span></span></span></span></p> <ul> <li><span><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Admins easily configure automated deployment pipelines in minutes rather than days or weeks.</span></span></span></span></span></span></li> <li><span><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Makers have an intuitive user experience for easily deploying their solutions.</span></span></span></span></span></span></li> <li><span><span><span><span><span><span lang="EN-US" xml:lang="EN-US" xml:lang="EN-US">Professional developers can (optionally) run pipelines using their preferred tools such as the Power Platform command line interface (CLI).</span></span></span></span></span></span></li> </ul> <p> </p> <p><span><span><span><strong><em><span><span>How to configure pipelines</span></span></em></strong></span></span></span></p> <p><span><span><span><span><span>Before starting to configure pipelines, we need to clarify a few points:</span></span></span></span></span></p> <ul> <li><span><span><span>It is necessary to create a host environment, known as Pipeline Orchestrator, which is a special purpose environment which acts as storage and management layer for all pipeline configuration security and run history. </span></span></span><span><span><span>The recommendation is to create this environment as a dedicated production environment separate from the other environments and tenants.</span></span></span></li> <li><span><span><span>Environments that would be configured to be part of pipeline experience must have the same Region as the “Pipelines host”</span></span></span></li> <li><span><span><span>Pipeline Orchestrator "CAN BE" Managed Environment but the rest of the environments "MUST BE" Managed Environments.</span></span></span></li> <li><span><span><span>In Pipeline Orchestrator environment, you need to install "Power Platform Pipelines" application as resource. You can install it in the next path: </span></span></span>                                       <span><span><span>Power Platform </span></span></span><span><span><span>Admin Center-&gt; Environments -&gt; Pipeline Orchestrator -&gt; Resources -&gt; Dynamics 365 apps -&gt; Install App -&gt; Power Platform Pipelines.</span></span></span></li> </ul> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="84adfd25-d3f5-437d-bb65-56484911526b" height="519" src="/sites/default/files/inline-images/Picture2_3.png" width="653" class="align-center" /> <p> </p> <p>Once installed, open "Pipeline Orchestrator" environment and in Pipeline Setup -&gt; Environment you will create a Dev Environment and Prod Environment linked to the original environment through the ID.</p> <p> </p> <img alt="Pipeline Setup Environments" data-entity-type="file" data-entity-uuid="179981f1-c87a-448d-ab35-d54f8a2e4f58" height="303" src="/sites/default/files/inline-images/Picture3.png" width="974" class="align-center" /> <p> </p> <p>Below you have the configuration for each environment. Highlight that you can get "Environment ID" from the admin center, just by clicking on the required environment.</p> <p>It is also worth mentioning that, in the field "Environment Type", is required to specify which is the purpose of the environment. In this case, "Dev Environment" is the data source, therefore is a "Development Environment", and "Prod environment" will be the "Target Environment" or the environment where the data will be deployed.</p> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="f015a153-9846-4ab8-9249-14f40ae04d16" height="311" src="/sites/default/files/inline-images/Picture4_1.png" width="975" class="align-center" /><img alt="Prod environment Setup" data-entity-type="file" data-entity-uuid="b48ec0ca-500d-4acc-bcce-555e28a92137" height="301" src="/sites/default/files/inline-images/Picture5_1.png" width="973" class="align-center" /> <p> </p> <p>The next step is to create the Pipeline. As you see in the picture below, you click on "New" for navigating to the Pipeline configuration.</p> <p> </p> <img alt="Pipeline Configuration" data-entity-type="file" data-entity-uuid="97b3eab0-4c8c-4174-9f5c-2ad4708f8a11" height="290" src="/sites/default/files/inline-images/Picture6_1.png" width="977" class="align-center" /> <p> </p> <p>After that, provide a name and in "Linked Development Environments", you can add an existing development environment, in this case, the one you created earlier.</p> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="3a720381-2fae-4a30-aaa6-4da260cf09d3" height="471" src="/sites/default/files/inline-images/Picture7.png" width="986" class="align-center" /> <p> </p> <p>To conclude the Pipeline setup, you need to create a "New Deployment Stage". Clicking on this button, a pop-up will be opened for the Deployment Stage creation. Add Prod Environment in "Target Deployment Environment ID", then click on "Save and Close". The configuration is now complete.</p> <p> </p> <img alt="Pipeline setup 2" data-entity-type="file" data-entity-uuid="19f86589-e870-4737-80c2-a8bd8d733165" height="499" src="/sites/default/files/inline-images/Picture9_1.png" width="981" class="align-center" /> <p> </p> <img alt="Pipeline setup 3" data-entity-type="file" data-entity-uuid="7de0757e-510a-4d9f-a513-921e075cd99d" height="568" src="/sites/default/files/inline-images/Picture8.png" width="656" class="align-center" /> <p> </p> <p>The final step is to deploy a solution from Dev environment to Prod environment.</p> <p>For this deployment, you have to navigate to your solution created in Dev Environment. As seen below, a new section is created and you can now select the previously created Pipeline "Testing Pipelines". By clicking on "Deploy here", the solution will be deployed from the Dev environment to the Prod environment.</p> <p> </p> <img alt="Deploying Dev-&gt;Prod1" data-entity-type="file" data-entity-uuid="bef5ee1c-ead8-4f00-9c8e-339291a822d2" height="394" src="/sites/default/files/inline-images/Picture10.png" width="955" class="align-center" /> <p> </p> <p>Select your Pipeline and Stage (if you have only one Stage and Pipelines, it is selected by default) and click "Next".</p> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="98f26496-b261-42b4-8043-2def5c48f636" height="499" src="/sites/default/files/inline-images/Picture11.png" width="960" class="align-center" /> <p> </p> <p>After the validation, a Summary will be showed. Here you can specify the Version and review some configuration fields.</p> <p>Click on "Deploy" for finishing the deployment process.</p> <p> </p> <img alt="Power Platform Managed Environments and Pipelines" data-entity-type="file" data-entity-uuid="2f4040ed-65b0-4e9e-b5cc-ceb99778a739" height="490" src="/sites/default/files/inline-images/Picture12.png" width="953" class="align-center" /> <p> </p> <p>In conclusion, Microsoft has released a very useful tool for Power Platform developers and administrators. We will soon be able to see the final release and what functionalities they add.</p> <h2 class="title">Power Platform Managed Environments and Pipelines</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2023-02/Standard-DevOps-CICD-1024x483.png</div> </div> </div> </div> </div> Thu, 09 Feb 2023 12:39:41 +0000 mario.ortegaaguayo 616 at https://dynamics-chronicles.com CI/CD - Testing Power Apps Tools Tutorial https://dynamics-chronicles.com/article/power-platform-managed-environments-and-pipelines#comments Handle secrets in Azure DevOps https://dynamics-chronicles.com/article/handle-secrets-azure-devops <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Handle secrets in Azure DevOps</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/mattias-liloia" lang="" about="/user/mattias-liloia" typeof="schema:Person" property="schema:name" datatype="" class="username">Mattias Liloia</a></span> <span property="schema:dateCreated" content="2022-05-31T12:18:54+00:00" class="field field--name-created field--type-created field--label-hidden">Tue, 05/31/2022 - 14:18</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p>When creating a ci/cd pipeline for your project, at some point you have to define a connection to your environment. In case of Dataverse, the connection string will contain clientid and client secret values. It's always a good idea to store secret values in a secure place, instead of putting them in clear text into your pipeline definition file (yaml) and potentially pushing them into your code repository.</p> <p>Azure DevOps provides you a number of possible solutions to address just that:</p> <ul> <li>Azure DevOps Service Connection: <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints">https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints</a></li> <li>Azure Key Vault: <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/release/azure-key-vault">https://docs.microsoft.com/en-us/azure/devops/pipelines/release/azure-key-vault</a></li> <li>Azure DevOps Secret Variables: <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#secret-variables">https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#secret-variables</a></li> </ul> <p> </p> <p>Personally, I prefer to use Azure Key Vault because it allows me to use these secrets in other applications too (like for example an Azure Functions).</p> <p> </p></div> </div> Tue, 31 May 2022 12:18:54 +0000 Mattias Liloia 567 at https://dynamics-chronicles.com Azure CI/CD - Testing https://dynamics-chronicles.com/article/handle-secrets-azure-devops#comments Power Apps Portal source code with Visual Studio Code and Power Platform CLI https://dynamics-chronicles.com/article/power-apps-portal-source-code-visual-studio-code-and-power-platform-cli <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Power Apps Portal source code with Visual Studio Code and Power Platform CLI</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/fabian-kalchofner" lang="" about="/user/fabian-kalchofner" typeof="schema:Person" property="schema:name" datatype="" class="username">Fabian Kalchofner</a></span> <span property="schema:dateCreated" content="2022-01-18T09:45:49+00:00" class="field field--name-created field--type-created field--label-hidden">Tue, 01/18/2022 - 10:45</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Power Apps Portal source code with Visual Studio Code and Power Platform CLI</em></p> <p>When developing a Portal with Power Apps Portal, you'll reach a point, where you want to have your developments in a source control or where you want to deploy your portal to a production environment.</p> <p>With the help of the Power Platform CLI, you can do all this tasks directly from within Visual Studio Code. You even have the possibility to adjust content (e.g. content snippets or web templates) directly in Visual Studio Code and to update them on your development environment.</p> <p>You'll need the following tools to start:</p> <ul> <li><a href="https://code.visualstudio.com/" rel="nofollow">Visual Studio Code</a></li> <li><a href="https://marketplace.visualstudio.com/items?itemName=microsoft-IsvExpTools.powerplatform-vscode" rel="nofollow">Power Platform Tools</a> <ul> <li>This is an extension of Visual Studio Code, which also installs the Power Platform CLI</li> </ul> </li> </ul> <p> </p> <h3>Connect to Dataverse</h3> <p>Once you installed the tools, you must connect to a Dataverse Environment with the Power Platform CLI. You can either make a connection with app secrets or client credentials:</p> <ul> <li> <pre> <code class="language-vbscript">pac auth create --name "$ConnectionName" --url "$url" --applicationId "$appId" --clientSecret "$clientSecret" --tenant "$tenantId"</code></pre> </li> <li> <pre> <code class="language-vbscript">pac auth create --name "$ConnectionName" --url "$url" --username "$username" --password "$password"</code></pre> </li> </ul> <p>Open a terminal session in Visual Studio Code and execute the command. Remember the name of your connection, as you will need it later on.</p> <p>To switch between different environments, you can execute the following command:</p> <pre> <code class="language-vbscript">pac auth select --name "$ConnectionName"</code></pre> <p> </p> <h3>Download Portal Content</h3> <p>To download existing content from a portal, execute the following command in the terminal session:</p> <pre> <code class="language-vbscript">pac paportal download --webSiteId $WebsiteId --path "$DestinationFolder" --overwrite true</code></pre> <p>The $WebsiteId is the GUID of your portal website record. Within the $DestinationFolder a folder with the name of the website will be created.</p> <p>You can limit the the entities to download by adding the following parameter:</p> <pre> <code class="language-vbscript">--includeEntities "adx_entityform,adx_entityformmetadata" --excludeEntities "adx_weblink,adx_weblinkset"</code></pre> <p>After executing the command, your destination folder will look like this:</p> <p><img alt="Power Apps Portal source code with Visual Studio Code and Power Platform CLI" data-entity-type="file" data-entity-uuid="8025cf9a-eb6d-4d10-afc5-605e9ec44035" src="/sites/default/files/inline-images/VSC.png" /></p> <p> </p> <h3>Upload Portal Content</h3> <p>You can create different deployment profiles to have different values for each environment. Do to so, create a folder (if it does not exist) "deployment-profiles". In this folder, you can create a yml file for each environment, e.g. "production.deployment.yml". Within the yml files, you can define the values:</p> <p><img alt="Power Apps Portal source code with Visual Studio Code and Power Platform CLI" data-entity-type="file" data-entity-uuid="f5be6135-5c7d-41fc-83f4-b4e9bc9cb62d" src="/sites/default/files/inline-images/DeploymentProfile.png" /></p> <p>Each record can be updated like this. Just provide the entity name, the record id and the attributes to update.</p> <p> </p> <p>To upload the content, execute the following command:</p> <pre> <code class="language-vbscript">pac paportal upload --path "$SourcePath" --deploymentProfile $DeploymentProfile</code></pre> <p>$SourcePath contains the relative path to the website folder from your export. The $DeploymentProfile contains the first part of your yml file (e.g. "production").</p> <p>You can modify content and upload it to the developer environment if needed.</p> <p> </p> <h3>Source Control</h3> <p>As all exported files are either yml, js, or html files, you can simply add the exported portal content to any source control system.</p> <h2 class="title">Power Apps Portal source code with Visual Studio Code and Power Platform CLI</h2> </div> </div> Tue, 18 Jan 2022 09:45:49 +0000 Fabian Kalchofner 229 at https://dynamics-chronicles.com Azure CI/CD - Testing Programming Tutorial https://dynamics-chronicles.com/article/power-apps-portal-source-code-visual-studio-code-and-power-platform-cli#comments Dataverse Plugin telemetry with Azure Application Insights https://dynamics-chronicles.com/article/dataverse-plugin-telemetry-azure-application-insights <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Dataverse Plugin telemetry with Azure Application Insights</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/danny-rodrigues-alves" lang="" about="/user/danny-rodrigues-alves" typeof="schema:Person" property="schema:name" datatype="" content="Danny Rodrigues Alves" class="username">Danny Rodrigue…</a></span> <span property="schema:dateCreated" content="2021-10-28T14:44:48+00:00" class="field field--name-created field--type-created field--label-hidden">Thu, 10/28/2021 - 16:44</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Dataverse Plugin telemetry with Azure Application Insights:</em></p> <h4>Introduction</h4> <p>Troubleshooting a piece of code is probably one of the main task in software development. With good logs, you can understand what happened and the code behavior. This is even more accurate for a CRMs and Microsoft Dataverse, where <em>non-IT </em>users are working with the CRM all day long.</p> <p>In Dataverse and Dynamics 365, tracing has been the way to record run-time information and assist us to diagnose behaviors. Trace logs are written directly to a Dataverse table - PluginTraceLog - and triggered by a trace system settings (off, on or only for exceptions). These logs must be written specifically by the developer in the C# code. An example of such code is given below in the <em><a href="#plugintrace">Plug-in Tracing via Trace</a></em> section.</p> <p>In July 2021, Microsoft has announced a <a href="https://docs.microsoft.com/en-us/power-platform-release-plan/2021wave1/data-platform/plug-in-telemetry-application-insights-integration">public preview</a> version to have plug-in trace logs in <strong><em>Application Insights</em></strong>. Application Insights is a feature from the Azure world used to monitor and capture all enterprise activities. The data is collected into Azure Monitor and is used for performance diagnostics, alerts, visualizations, failures reviews and many more. You can created dashboard, enabled <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/app/proactive-diagnostics">Smart Detection</a> or even create you custom queries to asses the system's health. Microsoft <a href="https://docs.microsoft.com/en-us/power-platform/admin/overview-integration-application-insights">describes in more detail</a> the benefits of such tool. Combining this with other tools like the <a href="https://dynamics-chronicles.com/article/monitor-model-driven-apps">model-driven app monitoring</a> give a full picture of the plateform's health.</p> <img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="d2cf16ef-3dfd-4ac8-a85c-7a1904fa0f82" src="/sites/default/files/inline-images/application-insights-performance.png" class="align-center" /> <p>With this integration, there are no SDK or other work needed from the developers, everything is already set up and ready to use with the <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger?view=dotnet-plat-ext-5.0"><strong>ILogger</strong> interface</a>.</p> <h4>Set up insights</h4> <p>To set up the integration, the first thing to do is to create an Application Insights resource in Azure. This is very simple to do:</p> <ol> <li>Log in the <a href="portal.azure.com">Azure portal</a></li> <li>Create a new resource<img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="be95c117-335c-4d94-82de-6eab41f183fc" src="/sites/default/files/inline-images/createNewResource.png" class="align-center" /></li> <li>Search for <em>Application Insights </em>and click <em>Create</em><img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="45bc1540-6c38-41a3-9882-b719e67875f3" src="/sites/default/files/inline-images/appplicationInsightsCreate.png" class="align-center" /></li> <li>Fill the fields and create the new resource<img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="000f3788-e5df-470b-acde-376d934e0a89" src="/sites/default/files/inline-images/appplicationInsightsReviewCreate.png" class="align-center" /></li> <li>Note that you must have at least one of the following rights on this resource: contributor, writer, or admin.</li> </ol> <p> </p> <p>Once the Azure resource has been created, you need to go to the <a href="https://admin.powerplatform.microsoft.com/">Power Platform admin center</a>:</p> <ol> <li>On the right panel, select <em>Analytics &gt; Data export</em><img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="9b0928ea-ed0b-4338-a838-b01b9a47211d" src="/sites/default/files/inline-images/Admin2.png" class="align-center" /></li> <li>Click on the button <em>New data export </em>and select the desired environment<img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="502c9a2a-31fe-401b-9f1c-9b22eefb60d0" src="/sites/default/files/inline-images/admin3b.png" class="align-center" /></li> <li>Click <em>Next</em></li> <li>Select the <em>Application Insights</em> resource newly created<img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="f66b5e81-b64e-4dd5-956c-94f6eb49b497" src="/sites/default/files/inline-images/admin4b.png" class="align-center" /></li> <li>Click <em>Create</em></li> </ol> <p> </p> <p>And that's it! Nothing more to do.</p> <p>If for whatever reason you decided to not use the Application Insights telemetry, simply deleting the <em>Data export</em> will do the trick.</p> <h4>Telemetry with Application Insights</h4> <p>With this new integration, all logs a developer writes within the ILogger interface from the Organization Service SDK are available in the Application Insights resources specified, without the need to code anything more! Under the hood, Dataverse will receive the logs and send it to the Application Insight resource, meaning that some delay might be experienced before the telemetry is visible in Azure. </p> <p>Let's build a plug-in that makes usage of the ILogger interface. Please check below on the section <em>Plug-in Tracing via Trace</em> on how to register and trigger this plug-in.</p> <pre> <code class="language-java">using System; using System.ServiceModel; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.PluginTelemetry; namespace DynamicsChroniclesPlugins { public class FollowUpMeetingPlugin : IPlugin { public void Execute(IServiceProvider serviceProvider) { // Obtain the ILogger service ILogger logger = (ILogger)serviceProvider.GetService(typeof(ILogger)); // Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // The InputParameters collection contains all the data passed in the message request. if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; // Obtain the organization service reference which you will need for web service calls. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); try { using (logger.BeginScope("Init phase")) { logger.LogInformation("FollowupPlugin: Begin the plugin."); if (entity.Id == null || entity.Id.Equals(Guid.Empty)) { logger.LogWarning("Plug-in registered for a wrong entity {0}", entity.LogicalName); } } // Create a task activity to follow up with the account customer in 7 days. using (logger.BeginScope("CreateTask")) { Entity followup = new Entity("task"); logger.LogInformation("FollowupPlugin: Building Task record..."); followup["subject"] = "Send e-mail to the new customer."; followup["description"] = "Follow up with the customer. Check if there are any new issues that need resolution."; followup["scheduledstart"] = DateTime.Now.AddDays(7); followup["scheduledend"] = DateTime.Now.AddDays(7); followup["category"] = context.PrimaryEntityName; followup["regardingobjectid"] = new EntityReference(entity.LogicalName, entity.Id); // Create the task in Microsoft Dynamics CRM. logger.LogInformation("FollowupPlugin: Creating the task activity."); Guid taskId = service.Create(followup); logger.LogInformation($"FollowupPlugin: Task created with GUID = {taskId}"); } } catch (FaultException&lt;OrganizationServiceFault&gt; ex) { throw new InvalidPluginExecutionException("An error occurred in FollowUpPlugin.", ex); } catch (Exception ex) { logger.LogError(ex, "FollowUpPlugin failed"); throw; } } } } } </code></pre> <p> </p> <h4>Application Insights Logs</h4> <p>Once the plug-in is registered and triggered, you can go to the Application Insights Logs console. On the <a href="https://portal.azure.com/">portal.azure.com</a>, you can open the <em>Application Insights</em> resource.</p> <img alt="application insights resource" data-entity-type="file" data-entity-uuid="067d87ee-1ae5-47ee-ae8e-82f0cbc4b056" src="/sites/default/files/inline-images/azure_resource.png" class="align-center" /> <p>Then to see the telemetry, open the button <strong><em>Logs</em> </strong>on the right panel, under the <strong><em>Monitoring</em> </strong>section.</p> <img alt="Azure Application Insights Logs" data-entity-type="file" data-entity-uuid="407c9029-7ff7-43a6-9068-40fe9c690440" src="/sites/default/files/inline-images/azure_logs.png" class="align-center" /> <p>In the <em>traces</em> table of the <em>Application Insights</em>, all logs can be found. In the above image, you can see the 4 logs entry.</p> <p>In the trace, all information is stored, from the message to the scope - or <i>customDimensions </i>and<i> OriginalFormat - </i>and the timestamp.</p> <img alt="Application Insights CustomDimension" data-entity-type="file" data-entity-uuid="928c4474-dd38-4d7c-a76b-4e266318bdf3" src="/sites/default/files/inline-images/azure_customdim.png" class="align-center" /> <p> </p> <h4>Application Insights Tables</h4> <p>The <i>traces</i> table is not the only one that can be queried. In total, there are 10 tables</p> <img alt="Application Insights Tables" data-entity-type="file" data-entity-uuid="c5d598b1-eccc-4b3f-9566-5eb6ffc9b803" src="/sites/default/files/inline-images/application-insights-tables.png" class="align-center" /> <ul> <li>availabilityResults <ul> <li>Summary data from availability tests</li> </ul> </li> <li>browserTimings <ul> <li>Data about client performance, such as the time taken to process the incoming data</li> </ul> </li> <li>customEvents <ul> <li>Custom events created by your application</li> </ul> </li> <li>customMetrics <ul> <li>Custom metrics created by your application</li> </ul> </li> <li>dependencies <ul> <li>Calls from the application to other components (including external components) recorded via TrackDependency() - for example, calls to REST API, database or a file system</li> </ul> </li> <li>exceptions <ul> <li>Exceptions thrown by the application runtime, captures both server side and client-side (browsers) exceptions</li> </ul> </li> <li>pageViews <ul> <li>Data about each website view with browser information</li> </ul> </li> <li>performanceCounters <ul> <li>Performance measurements from the compute resources supporting the application, for example, Windows performance counters</li> </ul> </li> <li>requests <ul> <li>Requests received by your application. For example, a separate request record is logged for each HTTP request that your web app receives</li> </ul> </li> <li>traces <ul> <li>Detailed logs (traces) emitted through application code/logging frameworks recorded via TrackTrace()</li> </ul> </li> </ul> <p>This page from the <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/app/data-model">Microsoft's documentation</a> also holds some information about the data model used by Azure Application Insights.</p> <h4 id="plugintrace">Plug-in Tracing via Trace</h4> <p>The <em>normal</em> way of having some logs from your plug-in developments is by using <strong><em>Trace Logs</em></strong>. When writing a C# class that implements the <em>IPlugin </em>interface, you can obtain a <em>ITracingService</em> object. This object allows you to write Trace Logs and then consult them directly from Dynamics 365!</p> <p>Let's build such plug-in. Based on <a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/tutorial-write-plug-in">Microsoft's documentation</a>, the following code has been created:</p> <pre> <code class="language-java">using System; using System.ServiceModel; using Microsoft.Xrm.Sdk; namespace DynamicsChroniclesPlugins { public class FollowUpMeetingPlugin : IPlugin { public void Execute(IServiceProvider serviceProvider) { // Obtain the tracing service ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); // Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // The InputParameters collection contains all the data passed in the message request. if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; // Obtain the organization service reference which you will need for web service calls. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); try { tracingService.Trace("FollowupPlugin: Begin the plugin."); // Create a task activity to follow up with the account customer in 7 days. Entity followup = new Entity("task"); tracingService.Trace("FollowupPlugin: Building Task record..."); followup["subject"] = "Send e-mail to the new customer."; followup["description"] = "Follow up with the customer. Check if there are any new issues that need resolution."; followup["scheduledstart"] = DateTime.Now.AddDays(7); followup["scheduledend"] = DateTime.Now.AddDays(7); followup["category"] = context.PrimaryEntityName; followup["regardingobjectid"] = new EntityReference(entity.LogicalName, entity.Id); // Create the task in Microsoft Dynamics CRM. tracingService.Trace("FollowupPlugin: Creating the task activity."); Guid taskId = service.Create(followup); tracingService.Trace($"FollowupPlugin: Task created with GUID = {taskId}"); } catch (FaultException&lt;OrganizationServiceFault&gt; ex) { throw new InvalidPluginExecutionException("An error occurred in FollowUpPlugin.", ex); } catch (Exception ex) { tracingService.Trace("FollowUpPlugin: {0}", ex.ToString()); throw; } } } } } </code></pre> <p>The plug-in is very simple an only creates a Task for a contact, seven days from now. Then, it has been registered with a step on the <em>Contact</em> entity, with the <em>Update</em> event, and with a filtering attribute.</p> <img alt="plug-in step.png" data-entity-type="file" data-entity-uuid="b5a70cb5-10b4-43a4-bd0e-b9cbdc3dc608" src="/sites/default/files/inline-images/plug-in%20step.png" class="align-center" /> <p>The last configuration is to enable the plug-in trace logs enabled for all events.</p> <img alt="trace log settings" data-entity-type="file" data-entity-uuid="bcdcc792-11a8-44f1-90da-538cbf05dbe7" src="/sites/default/files/inline-images/system_settings.png" class="align-center" /> <p>And voilà! Now when a <em>Contact</em> record is updated, the complete Trace Log can be find in Dynamics:</p> <ol> <li>Under Settings &gt; Customization &gt; Plug-In Trace Log</li> <li>Select a record with the name as in your plug-in assembly</li> <li>Search for the <em>Message Block </em>field<img alt="TraceLog Record" data-entity-type="file" data-entity-uuid="2e8d0ea6-2e36-495e-a153-5a33cb012ec6" src="/sites/default/files/inline-images/TraceLogRecord.png" class="align-center" /> <p> </p> </li> </ol> <h4>Differences between ILogger and ITracing Service</h4> <p>The following tables comes directly from <a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/application-insights-ilogger#logging-exceptions">Microsoft's documentation</a>. It is quite interesting because it states the core differences between those different approached of <em>logs</em>.</p> <table> <thead> <tr> <th>Criteria</th> <th>ILogger for Application Insights</th> <th>ITracingService Trace for Plug-in Trace Logs</th> </tr> </thead> <tbody> <tr> <td>Intended use</td> <td>Capture telemetry over time for analysis and debugging.</td> <td>While developing and debugging plug-ins</td> </tr> <tr> <td>How long data is stored</td> <td>According to your Application Insights data retention period, which is 90 days by default</td> <td>24 hours</td> </tr> <tr> <td>Available</td> <td>Only for organizations that have subscribed to Application Insights integration.</td> <td>For any organization when Plug-in tracing is enabled.</td> </tr> <tr> <td>Amount of data</td> <td>Each log message can pass a String value.</td> <td>Only 10kb of text can be written for each plug-in execution. Any more will be truncated.</td> </tr> <tr> <td>Available in runtime errors</td> <td>No</td> <td>Available in model-driven app client errors and as annotations in Web API.</td> </tr> </tbody> </table> <p>One key difference is the retention period. Traditional plug-in trace logs are only available for 24 hours. That can be painful when an user experiences a bug, but only brings it up too late or cannot reproduce it. That one of the huge advantage of using telemetry via Application Insights.</p> <p>The key advantage of the ILogger is to integrate the traditional plug-ins logs within a much bigger scope of telemetry information. In addition to the logs written by the developer, Application Insights also stores when was the code triggered, how long did it run and give some information about external HTTP requests.</p> <p>Please note that you don't need to choose one or other: plug-in tracing logs and telemetry can work together! For example, if you're building an ISV product, some clients my have Application Insights enabled, some other may not. By having both options, everyone with happy :)</p> <h4>Application Insights Tools</h4> <p>The Application Insights Azure resource tracks both client and server side actions. For example, if you go on to the <strong><em>Performance</em> </strong>section of the <em>Investigate</em> pane, you can see both server et browser related operations.</p> <img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="251bd0e3-6cd6-4554-88a5-04641cf53e51" src="/sites/default/files/inline-images/perf_0.png" class="align-center" /> <p>There are a lot of information possible, from the performance to the number of request.</p> <p>Among all other tools offered by Azure Monitor, there is also the <strong><em>Failures</em> </strong>section.</p> <img alt="Dataverse Plugin telemetry with Azure Application Insights" data-entity-type="file" data-entity-uuid="0e875549-6ab3-4419-a60a-bf035f821d12" src="/sites/default/files/inline-images/failures.png" class="align-center" /> <h4>Reference</h4> <ul> <li><a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/logging-tracing">Microsoft's Tracing and logging documentation</a></li> <li><a href="https://docs.microsoft.com/en-us/power-platform-release-plan/2021wave1/data-platform/plug-in-telemetry-application-insights-integration">Microsoft's Dataverse Release 2021 Wave 1</a></li> <li><a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/application-insights-ilogger#logging-exceptions">Microsoft's Dataverse Plug-in</a></li> <li><a href="https://docs.microsoft.com/en-us/power-platform/admin/analyze-telemetry">Application Insights and Telemetry</a></li> </ul> <h2 class="title">Dataverse Plugin telemetry with Azure Application Insights</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2021-08/title_0.png</div> </div> </div> </div> </div> Thu, 28 Oct 2021 14:44:48 +0000 Danny Rodrigues Alves 375 at https://dynamics-chronicles.com Azure CI/CD - Testing Integration Programming Tutorial https://dynamics-chronicles.com/article/dataverse-plugin-telemetry-azure-application-insights#comments Azure DevOps for Power Platform : Automation for Build, Deployment, Publish, Export, GIT, Variables https://dynamics-chronicles.com/article/azure-devops-power-platform-automation-build-deployment-publish-export-git-variables <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Azure DevOps for Power Platform : Automation for Build, Deployment, Publish, Export, GIT, Variables</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/nguyen-van-hao" lang="" about="/user/nguyen-van-hao" typeof="schema:Person" property="schema:name" datatype="" class="username">Nguyen Van Hao</a></span> <span property="schema:dateCreated" content="2021-06-01T04:57:54+00:00" class="field field--name-created field--type-created field--label-hidden">Tue, 06/01/2021 - 06:57</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Azure DevOps for Power Platform:</em></p> <p>Azure DevOps is a Microsoft product that provides version control, reporting, requirements management, project management, automated builds, testing, and release management capabilities. It covers the entire application lifecycle and enables DevOps capabilities</p> <p>The article<a href="https://dynamics-chronicles.com/article/azure-devops-dataverse-using-power-platform-build-tools"> Azure DevOps for Dataverse using Power Platform Build Tools</a> shows you a basic usage of Azure Pipeline to export and import solution</p> <p>In this article, we'll implement some advanced setup for Azure Pipeline in the build steps</p> <p>We'll complete the following steps:</p> <ol> <li> <h4><a href="#step1">Implement basic setup for Azure Pipeline</a></h4> </li> <li> <h4><a href="#step2">Publish CRM customizations</a></h4> </li> <li> <h4><a href="#step3">Export unmanaged solution (.zip file)</a></h4> </li> <li> <h4><a href="#step4">Unpack the unmanaged solution to a folder</a></h4> </li> <li> <h4><a href="#step5">Commit changes of the unmanaged solution (a folder after unpacking) to git</a></h4> <ul> <li> <h5><a href="#step51">5.1 Update permission configuration</a></h5> </li> <li> <h5><a href="#step52">5.2 Create Window command task to commit solution</a></h5> </li> </ul> </li> <li> <h4><a href="#step6">Using variables and variable group</a></h4> <ul> <li> <h5><a href="#step61">6.1 Using variables</a></h5> </li> <li> <h5><a href="#step62">6.2 Using variable group</a></h5> </li> <li> <h5><a href="#step63">6.3 Link Azure Key-Val to the variable group</a></h5> </li> </ul> </li> <li> <h4><a href="#conclusion">Conclusion</a></h4> </li> </ol> <p> </p> <h4 id="step1">1. Implement basic setup for Azure Pipeline</h4> <p>To follow the rest of this article, you need to follow <a href="https://dynamics-chronicles.com/article/azure-devops-dataverse-using-power-platform-build-tools">Azure DevOps for Dataverse using Power Platform Build Tools</a> to implement the basic setup.</p> <p> </p> <h4 id="step2">2. Publish CRM customizations </h4> <p>The power platform extension support publishes customization before exporting.</p> <p>To do this, add a "Power Platform Publish Customizations" to the build pipeline. You need to specify a connection to the CRM DEV environment</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="9693c4f6-96c3-4b02-b53c-a17a607b2c4f" height="534" src="/sites/default/files/inline-images/publish_customization.png" width="923" /></p> <p> </p> <h4 id="step3">3. Export unmanaged solution</h4> <p>You can also export solution as unmanaged in Power Platform Build Tools</p> <p>Note: <a href="#step4">Step 4</a> and <a href="#step5">Step 5</a> will use data from this step.</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="bf8a8510-9cce-404f-9319-917c69810e82" height="628" src="/sites/default/files/inline-images/export_unmanaged_solution.png" width="926" /></p> <p> </p> <h4 id="step4">4. Unpack a managed solution</h4> <p>In <a href="#step3">Step 3</a>, we already export the unmanaged solution, it's a .zip file</p> <p>We can use Power Platform Build Tools to unpack (unzip) solution into a folder</p> <p><img alt="Unpack solution" data-entity-type="file" data-entity-uuid="1b4dec06-91cf-4848-9f39-1a047447738f" src="/sites/default/files/inline-images/unpack%20solution.png" /></p> <p>Parameters:</p> <ol> <li>Select the unmanaged solution from the build at <a href="#step3">Step 3</a> <ul> <li>$(Build.ArtifactStagingDirectory): this is a <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&amp;tabs=yaml">predefined variable</a> of Azure DevOps</li> </ul> </li> <li>Select the folder name to contain the unpack solution <ul> <li>$(Build.SourcesDirectory): this is a<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&amp;tabs=yaml"> predefined variable</a> of Azure DevOps which points to the git repository root folder</li> <li>Make sure the folder "solutions" exits in your repo</li> <li><img alt="Unpack solution" data-entity-type="file" data-entity-uuid="dbcc91bc-ef85-4818-8807-2c6c15454859" height="305" src="/sites/default/files/inline-images/unpack%20solution2.png" width="805" /></li> </ul> </li> <li>The type of solution is Unmanaged </li> </ol> <h4 id="step5">5. Commit changes of the unmanaged solution (a folder after unpacking) to git</h4> <p>It's helpful to commit the changes to Git to track all changes that go to the PROD environment.</p> <p>To do this, we can create a Window command to commit changes in folder "solutions".</p> <p> </p> <h5 id="step51">5.1 Update permission configuration</h5> <p>Open Project Settings at the left-bottom of Azure DevOps</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="6b127ca9-83c6-470a-822b-c3ca33c1d43a" src="/sites/default/files/inline-images/project_settings.png" /></p> <p>Set "Allow" for permission "Contribute" for the current user or group</p> <p><img alt="project_settings2.png" data-entity-type="file" data-entity-uuid="56da3d15-aadd-4436-bd3f-764d244ebe69" src="/sites/default/files/inline-images/project_settings2.png" /></p> <h5> </h5> <p>Allow scripts to access the OAuth token</p> <p><img alt="Allow access token" data-entity-type="file" data-entity-uuid="2f4d2522-b13b-4cd6-84ec-a2a740e37158" src="/sites/default/files/inline-images/allow_access_token.png" /></p> <p>If you do not update the configuration correctly, we'll get these error when commit code using Azure Pipeline</p> <ul> <li>Fatal: Cannot prompt because user interactivity has been disabled.</li> <li>You need the Git 'GenericContribute' permission to perform this action</li> </ul> <h5 id="step52">5.2 Create Window command task to commit solution</h5> <p>After updating the configuration in 4.1, you need to create a command-line task to commit code (the unmanaged solution) into GIT to track change</p> <p>To do this, create a new "Command line" task</p> <h4><img alt="Git commit" data-entity-type="file" data-entity-uuid="60001fd5-a951-4087-b673-ee3f0d5b82c1" src="/sites/default/files/inline-images/commit.png" /></h4> <ol> <li>"master": the name of the branch that you want to commit to</li> <li>"solution": the folder that contains data to commit. See detail in <a href="#step4">Step 4</a></li> </ol> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="2bdd2c92-6f0f-47e8-8099-d403dc23ab6d" src="/sites/default/files/inline-images/git_commit.png" /></p> <h4 id="step6">6. Using variables and variable group</h4> <p>When you configure for the Azure DevOps task, you can use variables for each config parameter instead of hard code.</p> <p>There are 3 kinds of variables in Azure DevOps</p> <ol> <li>Pipeline variables: custom variable for this pipeline. You can create as many as you want.<br /> <img alt="Variables" data-entity-type="file" data-entity-uuid="44975f33-3ac6-438c-a3b4-aa326f2bc273" src="/sites/default/files/inline-images/variables1.png" /><br />  </li> <li><a href="https://go.microsoft.com/fwlink/?linkid=849035">Predefined variables</a>: predefined variables of Azure Pipeline. For example "$(Build.SourcesDirectory)"<br /> <img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="629c0915-7f31-4015-9ff3-2e9de562ad5f" src="/sites/default/files/inline-images/variables2.png" /><br />  </li> <li><a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups?view=azure-devops&amp;tabs=yaml">Variable groups</a>: Use a variable group to store values that you want to control and make available across multiple pipelines. See detail in "6. Using variable groups from Azure Key-Val"</li> </ol> <h5 id="step61">6.1 Using variables</h5> <p>To access variable, open tab "variables"</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="08b86546-c5ad-4eb2-81a6-044eebe088e1" src="/sites/default/files/inline-images/variables.png" /></p> <p> </p> <p>Now, let's try to create a new variable "dev.solution_name" and replace the hard code solution name in task "Power Platform Export Unmanaged Solution"</p> <p><img alt="Variable 3" data-entity-type="file" data-entity-uuid="9db3202a-7176-427c-8968-8d9ea6383d40" src="/sites/default/files/inline-images/variables3.png" /></p> <h5 id="step62">6.2 Using variable groups</h5> <p>Open variable group library</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="8e84a8d8-0b1e-44a3-8976-dddc6df316c8" src="/sites/default/files/inline-images/variables4.png" /></p> <p>Create 2 sample variables</p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="a7596d2b-960a-4372-b210-2c7cc2a4b394" src="/sites/default/files/inline-images/variables5.png" /></p> <p> </p> <p>Link variable group to pipeline</p> <p><img alt="Variables" data-entity-type="file" data-entity-uuid="7db00931-baf2-4050-89f5-0a48fa17b943" src="/sites/default/files/inline-images/variables6.png" /></p> <p>Select your variable group</p> <p><img alt="Variables" data-entity-type="file" data-entity-uuid="b1a8bf27-d975-4eca-9a0f-91e3ae50dbc6" src="/sites/default/files/inline-images/variables7.png" /></p> <p> </p> <p><img alt="Azure DevOps for Power Platform" data-entity-type="file" data-entity-uuid="07d455c2-a5ab-4967-8114-4944d7270f86" src="/sites/default/files/inline-images/variables8.png" /></p> <p>Now, you can use $(key1), $(key2) in your pipeline configuration. </p> <h4> </h4> <h5 id="step63">6.3 Link Azure Key-Val to the variable group</h5> <p>You can also create variable group from  <a href="https://azure.microsoft.com/en-us/services/key-vault/">Azure Key-Val</a></p> <p>To do this you need to register a Azure subscription and setup your Azure Key-Val, then link it to Azure DevOps</p> <p><img alt="Azure Key-Val" data-entity-type="file" data-entity-uuid="794300c5-c89e-4d09-81ee-14d4aaf63bb1" src="/sites/default/files/inline-images/image_2021_06_01T06_54_59_819Z_0.png" /></p> <p> </p> <h4 id="conclusion">7. Conclusion</h4> <ol> <li>This article is the advanced setup for Azure DevOps, you can see the basic setup here <a href="https://dynamics-chronicles.com/article/azure-devops-dataverse-using-power-platform-build-tools">Azure DevOps for Dataverse using Power Platform Build Tools</a></li> <li>Azure DevOps Pipeline is powerful, you can do most CI/CD tasks using it</li> <li>Using variable is a best practice, you can define a value that you can then use in your pipeline</li> <li><a href="https://azure.microsoft.com/en-us/services/key-vault/">Azure Key-Val</a> increase security and control over keys and passwords, you should use it when possible </li> </ol> <h2 class="title">Azure DevOps for Power Platform</h2> </div> </div> <div class="field field--name-field-image field--type-image field--label-above"> <div class="field__label">Image</div> <div class="images-container clearfix"> <div class="image-preview clearfix"> <div class="image-wrapper clearfix"> <div class="field field--name-field-image field--type-image field--label-above field__item">/sites/default/files/2021-06/index-hero.jpg</div> </div> </div> </div> </div> Tue, 01 Jun 2021 04:57:54 +0000 Nguyen Van Hao 347 at https://dynamics-chronicles.com Azure CI/CD - Testing Deep Dive Integration Programming Tutorial https://dynamics-chronicles.com/article/azure-devops-power-platform-automation-build-deployment-publish-export-git-variables#comments Dataverse PowerDataOps Introduction https://dynamics-chronicles.com/article/dataverse-powerdataops-introduction <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Dataverse PowerDataOps Introduction</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/amaury-veron" lang="" about="/user/amaury-veron" typeof="schema:Person" property="schema:name" datatype="" class="username">Amaury Veron</a></span> <span property="schema:dateCreated" content="2021-05-26T14:40:18+00:00" class="field field--name-created field--type-created field--label-hidden">Wed, 05/26/2021 - 16:40</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Dataverse PowerDataOps</em></p> <p>Let me introduce you a PowerShell module for Dataverse: PowerDataOps. PowerShell has many benefits: you can edit and run script on Windows servers, execute .Net code, use it easily in many tools, ... </p> <p>You can find the GitHub for the project here: <a href="https://github.com/AymericM78/PowerDataOps">https://github.com/AymericM78/PowerDataOps</a>. As you will quickly see, the module is very well documented.</p> <p>This module provides various features to:</p> <ul> <li>Execute CRUD operations on Dataverse data</li> <li>Work with solutions</li> <li>Administrate/manage the environment</li> <li>Perform DevOps operations</li> </ul> <p>You can find the exhaustive list of commands in <a href="https://github.com/AymericM78/PowerDataOps/blob/b99ae87b6e6265f5a134b60b09118dfaa385379d/documentation/index.md">this file</a> of the GitHub.</p> <p>The module is built on top of Microsoft PowerShell modules: </p> <ul> <li><a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.xrm.tooling.crmconnector.powershell/?view=pa-ps-latest">Microsoft.Xrm.Tooling.CrmConnector.PowerShell</a></li> <li><a href="https://docs.microsoft.com/en-us/power-platform/admin/powerapps-powershell#power-apps-cmdlets-for-administrators">Microsoft.PowerApps.Administration.PowerShell</a></li> </ul> <p>It also uses some C# libraries such as Microsoft.Xrm.Sdk.Entity.</p> <p> </p> <p>This module allows to use very easily the features described above.</p> <p>To explore and discover the module, I would advise you to start by having a look at these two great samples:</p> <ul> <li><a href="https://github.com/AymericM78/PowerDataOps/blob/main/documentation/samples/Working%20with%20data.md">Working with data.md</a> <ul> <li>In just a few lines, performs the following operations: <ul> <li>Connect to Microsoft Dataverse</li> <li>Create a record</li> <li>Retrieve all records and output in a gridview</li> <li>Update a record</li> <li>Retrieve a specific record</li> <li>Delete record</li> </ul> </li> </ul> </li> <li><a href="https://github.com/AymericM78/PowerDataOps/blob/main/documentation/samples/Working%20with%20solutions.md">Working with solutions.md</a> <ul> <li>In just a few lines, performs the following operations: <ul> <li>Connect to Microsoft Dataverse</li> <li>Retrieve a solution record (row) with its uniquename</li> <li>Increase version number</li> <li>Export in managed</li> </ul> </li> </ul> </li> </ul> <p> </p> <p>I hope you will enjoy this module. Don't hesitate to go in the GitHub and explore it more!</p> <h2 class="title">Dataverse PowerDataOps</h2> </div> </div> Wed, 26 May 2021 14:40:18 +0000 Amaury Veron 373 at https://dynamics-chronicles.com API CI/CD - Testing Tools https://dynamics-chronicles.com/article/dataverse-powerdataops-introduction#comments Dynamics 365 Impersonate user using browser extension https://dynamics-chronicles.com/article/dynamics-365-impersonate-user-using-browser-extension <span property="schema:name" class="field field--name-title field--type-string field--label-hidden">Dynamics 365 Impersonate user using browser extension</span> <span rel="schema:author" class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/vo-sy-lien-thanh" lang="" about="/user/vo-sy-lien-thanh" typeof="schema:Person" property="schema:name" datatype="" class="username">Vo Sy Lien Thanh</a></span> <span property="schema:dateCreated" content="2021-05-17T04:08:04+00:00" class="field field--name-created field--type-created field--label-hidden">Mon, 05/17/2021 - 06:08</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-above"> <div class="field__label">Body</div> <div property="schema:text" class="field__item"><p><em>Dynamics 365 Impersonate user using browser</em></p> <p>In Dynamics 365 online, when we need to peform the tests for the security model, It could be a nightmare since we need to login and logout many times and use many browser with private mode and normal mode. Then I found to ease a lot these test sessions thanks to a chrome Extension named "ModHeader". This article will share how to deal with impersonation using webapi and using Chrome extension.</p> <h2>1/ Impersonate using Web API</h2> <p>First of all, I started to figure out how to impersonate another person, I found a document from Microsoft with impersonate detail for WebAPI. You can find it <a href="https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/impersonate-another-user-web-api">here</a>.</p> <p>The main point of above documentation is that your running account must have "<code>prvActOnBehalfOfAnotherUser</code>" privilege. And in the header of request need to impersonate must have one of these two params:</p> <ul> <li><strong>CallerObjectId</strong>: Azure Active Directory (AAD) object id</li> <li><strong>MSCRMCallerID</strong>: system user id</li> </ul> <p>However, Microsoft prefers to use <strong>CallerObjectId</strong> instead of <strong>MSCRMCallerID</strong>. Therefore, in this article, I will show you only the method for <strong>CallerObjectId</strong> (Actually, you can do the same for <strong>MSCRMCallerID</strong>. You can try it by yourself! ;))</p> <h2>2/ Add the security privilege to enable Impersonate</h2> <p>As I mention in the previous section, you need to ensure that your account has "<code>prvActOnBehalfOfAnotherUser</code>" privilege.<br /> To enable this privilege, you can open your security role and navigate to tab "Business Management", find "Act on Behalf of Another User" in the last section check enable it</p> <img alt="Dynamics 365 Impersonate user using browser" data-entity-type="file" data-entity-uuid="56717dca-fca4-4bf6-ae6a-cd5e380745f8" src="/sites/default/files/inline-images/Untitled_27.png" class="align-center" /> <h2>3/ Get Azure AD Object ID of the user:</h2> <p>In Dynamics 365 online, each system user has an "Azure AD Object ID" (azureactivedirectoryobjectid). We need to get user's "Azure AD Object ID" and add it to the header of the request to act on behalf of that user.</p> <p>The simplest way to get "Azure AD Object ID" is used advanced find and add "Azure AD Object ID" column to the result grid.</p> <img alt="Dynamics 365 Impersonate user using browser" data-entity-type="file" data-entity-uuid="a65ee14f-fdc8-45c2-abd8-60bd1efdd44e" src="/sites/default/files/inline-images/Untitled_28.png" class="align-center" /> <p>You can copy ID and use it in some step behind.</p> <h2>4/ Install ModHeader:</h2> <p>You can find ModHeader extension <a href="https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj?hl=en-US">here</a> or you can open Chrome/Firefox web store and search for ModHeader.</p> <img alt="Dynamics 365 Impersonate user using browser" data-entity-type="file" data-entity-uuid="a67b8509-a1da-45c1-abd3-d9c2ee2a19db" src="/sites/default/files/inline-images/Untitled_29.png" class="align-center" /> <p>The purpose of this extension is to add some custom params to the header for each request to impersonate.</p> <h2>5/ Use ModHeader:</h2> <img alt="Dynamics 365 Impersonate user using browser" data-entity-type="file" data-entity-uuid="f8a8b59e-3254-44fa-a478-69ecb9aa72d0" src="/sites/default/files/inline-images/Untitled_30.png" class="align-center" /> <ol> <li>You can change the name of profile. I usually use email of the account to identify which user I'm using.</li> <li>Name of header param: CallerObjectId</li> <li>Value of header param: Azure AD Object ID value</li> </ol> <p>After you finish the setting, you need to refresh the page to see Dynamics 365 in the context of the user you are impersonating.</p> <h2>6/ Stop impersonating:</h2> <p>When you finish troubleshooting the security model, you need to stop impersonating. You have many ways to do it:</p> <ul> <li>Disable ModHeader extension</li> <li>Remove CallerObjectId</li> <li>Pause ModHeader extension:</li> </ul> <img alt="stop impersonate" data-entity-type="file" data-entity-uuid="c9d7cf2c-2576-49b5-b580-90c32364f3c9" src="/sites/default/files/inline-images/Untitled_31.png" class="align-center" /> <p>Hope this article will help you save your time when you need to troubleshoot or test security model on Dynamics 365 online!</p> <h2 class="title">Dynamics 365 Impersonate user using browser</h2> </div> </div> Mon, 17 May 2021 04:08:04 +0000 Vo Sy Lien Thanh 358 at https://dynamics-chronicles.com Customization CI/CD - Testing https://dynamics-chronicles.com/article/dynamics-365-impersonate-user-using-browser-extension#comments