{"id":15636,"date":"2024-11-29T09:58:46","date_gmt":"2024-11-29T00:58:46","guid":{"rendered":"https:\/\/www.btc-embedded.jp\/?p=15636"},"modified":"2025-01-27T21:20:24","modified_gmt":"2025-01-27T12:20:24","slug":"how-to-automate-dependency-management-part-2","status":"publish","type":"post","link":"https:\/\/www.btc-embedded.jp\/ja\/how-to-automate-dependency-management-part-2\/","title":{"rendered":"How to Automate Dependency Management: Part 2"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"15636\" class=\"elementor elementor-15636\" data-elementor-post-type=\"post\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3b5f0493 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3b5f0493\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-559a247a\" data-id=\"559a247a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d83c847 elementor-widget elementor-widget-text-editor\" data-id=\"d83c847\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.20.0 - 26-03-2024 *\/\n.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:#69727d;color:#fff}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap{color:#69727d;border:3px solid;background-color:transparent}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap{margin-top:8px}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap-letter{width:1em;height:1em}.elementor-widget-text-editor .elementor-drop-cap{float:left;text-align:center;line-height:1;font-size:50px}.elementor-widget-text-editor .elementor-drop-cap-letter{display:inline-block}<\/style>\t\t\t\tIf you\u2019ve ever had to deal with manually migrating dependencies to the latest version, you know how difficult and time-consuming it can be to upgrade and validate your model. Thankfully, by leveraging powerful modern dev-ops practices, don\u2019t have to! By utilizing the power of automation and other powerful dev-ops best practices, you can let your process work for you, and focus on delivering the code that matters.\n\nIf you haven\u2019t read part 1 of this article, start there! This establishes the context for how we\u2019ve separated out our sample model to utilize a server-consumer paradigm for versioning and serving our model.\n\nIn <a href=\"https:\/\/www.btc-embedded.com\/how-to-automate-dependency-management-part-1\/\" target=\"_blank\" rel=\"noopener\">part 1<\/a> of <strong>this article<\/strong>, I focused on the development part of the toolchain, where we restructured an original monolithic model to version its dependencies and build them on-the-fly. In part 2 of <strong>this article<\/strong> (you are here!), I\u2019ll add in a CI pipeline to automatically migrate and test our dependencies to the latest version. Here\u2019s an outline of the steps involved:\n<ol>\n \t<li>Creating our original, unified model<\/li>\n \t<li>Separating out our model into main module and dependency module<\/li>\n \t<li>Serving our dependency module through a package-manager<\/li>\n \t<li><strong>Migrating our main module to use the latest version of its dependency<\/strong><\/li>\n \t<li><strong>Testing the main module to validate the migration didn\u2019t break anything<\/strong><\/li>\n<\/ol>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1144c66 elementor-widget elementor-widget-heading\" data-id=\"1144c66\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.20.0 - 26-03-2024 *\/\n.elementor-heading-title{padding:0;margin:0;line-height:1}.elementor-widget-heading .elementor-heading-title[class*=elementor-size-]>a{color:inherit;font-size:inherit;line-height:inherit}.elementor-widget-heading .elementor-heading-title.elementor-size-small{font-size:15px}.elementor-widget-heading .elementor-heading-title.elementor-size-medium{font-size:19px}.elementor-widget-heading .elementor-heading-title.elementor-size-large{font-size:29px}.elementor-widget-heading .elementor-heading-title.elementor-size-xl{font-size:39px}.elementor-widget-heading .elementor-heading-title.elementor-size-xxl{font-size:59px}<\/style><h2 class=\"elementor-heading-title elementor-size-default\">Step 4: Migrating our Main Model to use the Latest Dependency<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9a4031e elementor-widget elementor-widget-text-editor\" data-id=\"9a4031e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>We\u2019ve already broken up our monolithic model into a main module (our concern) and a dependency (not our concern). We\u2019ve also established a link between the two to bring them together at run-time. But there\u2019s one situation that we still haven\u2019t addressed: what happens when the dep team pushes out a new feature or bugfix, that I want to make available to my own SWC? How can I upgrade my dependency version?<\/p><p>Let\u2019s try this out and see what happens! If I look into shared_module_a.slx, I\u2019ll see the following simple model:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-aed285d elementor-widget elementor-widget-image\" data-id=\"aed285d\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.20.0 - 26-03-2024 *\/\n.elementor-widget-image{text-align:center}.elementor-widget-image a{display:inline-block}.elementor-widget-image a img[src$=\".svg\"]{width:48px}.elementor-widget-image img{vertical-align:middle;display:inline-block}<\/style>\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_16.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-abffcbf elementor-widget elementor-widget-text-editor\" data-id=\"abffcbf\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Double click on the \u2019rem\u2019 function and change it to \u2019mod\u2019. This will have the same functionality for our inputs, but will trigger a hash change on our model that Conan can pick up on.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e7f53dd elementor-widget elementor-widget-image\" data-id=\"e7f53dd\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_17.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5a27341 elementor-widget elementor-widget-text-editor\" data-id=\"5a27341\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Save the model, change the version number to 1.0.1 in the conanfile, and then build and push:<\/p><p class=\"MsoNormal\" style=\"line-height: 18.56px; font-size: 12pt; margin: 0cm 0cm 8pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoIntenseReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #0f4761; letter-spacing: 0.25pt; font-weight: bold;\">conan create .<\/span><\/p><p class=\"MsoNormal\" style=\"line-height: 18.56px; font-size: 12pt; margin: 0cm 0cm 8pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoIntenseReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #0f4761; letter-spacing: 0.25pt; font-weight: bold;\">conan upload shared_module_a -r=artifactory<\/span><\/p><p>And you\u2019ll see that the update has been successfully pushed to our Artifactory. Great!<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c78b542 elementor-widget elementor-widget-image\" data-id=\"c78b542\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_18.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f7537a4 elementor-widget elementor-widget-text-editor\" data-id=\"f7537a4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Of course, we\u2019re assuming here that we\u2019ve done our rigorous unit testing and development best practices that we normally would\u2014so, at this point, our \u2018public release\u2019 of shared_modula_a version 1.0.1 represents an official release that\u2019s intended for other people to rely on and use. So lets switch back to our SWC1, and address our question from earlier:<\/p><p><strong>How can I upgrade my dependency version?<\/strong><\/p><p>Well, you have a mouse and a keyboard, don\u2019t you? Why not just stop being lazy, and go change your required dependency from 1.0.0 to 1.0.1?<\/p><p>You could, but there are good reasons to be lazy in this case. Firstly, I don\u2019t necessarily have a way to know when the latest release of 1.0.1 came out, other than asking the developers of my dep to notify me when it comes out (and <em>they<\/em> could forget, just pushing the problem back one level). Secondly, even if I do remember (or schedule) to, say, do a once-a-week dependency check, I might not have only a single dependency\u2014I might have several hundred, at which point I\u2019d probably just throw my hands up in frustration and do what most developers do: leave my dependencies stuck on an old version because \u201cit just works\u201d and I don\u2019t have the time to upgrade them.<\/p><p>No, the best way to upgrade dependencies is going to have to be automated, to get over these hurdles\u2014and thats where GitHub and CI come in! By using GitHub actions, we can create a timed trigger, that, when run, will check the version in the conanfile, and try to increment it to the latest-and-greatest feature upgrades, and then create a new branch with a pull request for us to manually review and merge the changes.<\/p><p>Let\u2019s get our files set up to automate in all the missing parts of the workflow. The first thing we\u2019ll do is create a separate \u2018scripts\u2019 folder inside our swc1 repository, and download the update_dependencies.py and requirements.txt files from the <a href=\"https:\/\/github.com\/thabok\/deps-swc-1\" target=\"_blank\" rel=\"noopener\">demo repository<\/a>. These will do the actual task of updating our declared dependency in our Conan file.<\/p><p>Of course, this script won\u2019t do anything unless it\u2019s invoked, and for that we need to write a yaml file to tell Github Actions what steps we want to take, and in what order. Open up your favorite editor, and create the file version_update.yml, with the following contents:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-776cc98 elementor-widget elementor-widget-text-editor\" data-id=\"776cc98\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">name: Version Update Check<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\"># run regularly or on demand<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">on:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 # schedule:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 #\u00a0 &#8211; cron: &#8216;0 0 * * *&#8217; # at midnight<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 workflow_dispatch: # allow workflow to be triggered manually<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">jobs:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 # workflow<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 version_update:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 runs-on: self-hosted<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 steps:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0 &#8211; name: Checkout repo content<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 uses: actions\/checkout@v3<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0 &#8211; name: Ensure required python packages<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 run: pip install -r scripts\/requirements.txt<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 shell: cmd<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0 &#8211; name: Update dependencies<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 env:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GH_REPO: ${{ github.repository }}<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GH_TOKEN: ${{ secrets.REPO_TOKEN }}<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 run:\u00a0 python scripts\/update_dependencies.py<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-55abca3 elementor-widget elementor-widget-text-editor\" data-id=\"55abca3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>The language is documented <a href=\"https:\/\/docs.github.com\/en\/actions\/using-workflows\/workflow-syntax-for-github-actions\" target=\"_blank\" rel=\"noopener\">extensively<\/a> on GitHub\u2019s own pages, but the gist of what\u2019s happening here is that we\u2019re creating a trigger-point (in our case, a manual trigger) that, when activated, checks out the repository, installs any missing dependencies, and then executes our update_dependecies.py script to perform the version upgrade and create the pull request.<\/p><p>Of course, we should test it to make sure it works, but there\u2019s just a few more steps to configure GitHub so that it know what this file is and how to process it. First, we need to create a special folder, .github\/workflows, and put our yml file in there. Your directory will look like this: go ahead and push it to GitHub.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a942fa0 elementor-widget elementor-widget-image\" data-id=\"a942fa0\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_19.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ccf9d89 elementor-widget elementor-widget-text-editor\" data-id=\"ccf9d89\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Github also needs to know where to execute this script, be that a machine you provide or on the cloud: this is called, fittingly enough, the \u2018runner,\u2019 because it runs the code you give it. GitHub hosts their own runner computers, but to have more control over the process, the workflow yaml we wrote uses a self-hosted runner. For this example, we can just use our local dev machine for a proof-of-concept: navigate to your repo, then click through to Settings &gt; Actions &gt; Runners. Create a new self-hosted runner, and follow the instructions to register and connect it from your PC to GitHub. Remember, unless your Artifactory server is publicly accessible, the runner is going to have to be on the same network in order to see the dependency files.<\/p><p>Part of our update workflow involves creating a new branch as a pull request, so that we can test our dependency migration without necessarily committing to it just yet (after all, the dependency upgrade may break out code, and we don\u2019t want to push that to production!). This means we\u2019ll need to give our workflow read and write permissions so that our scripts can modify the repository, specifically to enable it to create a new branch and pull request. You can find this under Settings &gt; Actions &gt; General:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-253a875 elementor-widget elementor-widget-image\" data-id=\"253a875\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_20.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fbaec03 elementor-widget elementor-widget-text-editor\" data-id=\"fbaec03\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Finally, we\u2019ll need to give our runner permission to access our git repo (remember, this could potentially be running on a cloud computer we don\u2019t own, so this is an important security measure). Github allows this through their \u201cpersonal access tokens,\u201d which will let our host machine push to the repo, create branches and pull requests, and in general commit changes and modifications to our software.<\/p><p>To do this, follow <a href=\"https:\/\/docs.github.com\/en\/authentication\/keeping-your-account-and-data-secure\/managing-your-personal-access-tokens\" target=\"_blank\" rel=\"noopener\">GitHub&#8217;s instructions<\/a> on how to create the token; make sure to save the token! We\u2019ll need it in a few minutes.<\/p><p>Then, we\u2019ll want to store our token to a variable that our script accesses and uses to authenticate itself. Go to your settings in the repository, and under \u2018Secrets and variables\u2019 &gt; \u2018actions\u2019, create a new repository secret. Set the value to be the token you just made in the last step, and name it REPO_TOKEN. Don\u2019t forget to save!<\/p><p>Let\u2019s test out and make sure that everything worked. Go to your repository, and under \u2018Actions\u2019, select \u2018Version Upgrade,\u2019 and run the workflow. If you see an error that running scripts is disabled on your host machine, you\u2019ll need to change your execution policy on Windows: open up a powershell as administrator, and run<\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #0f4761; letter-spacing: 0.25pt; font-weight: bold;\">Set-ExecutionPolicy RemoteSigned<\/span><\/p><p>Then restart the runner and try again.<\/p><ul><li>When everything\u2019s configured correctly you\u2019ll see a pretty green checkmark pop up after a minute or two:<\/li><\/ul><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #0f4761; letter-spacing: 0.25pt; font-weight: bold;\">\u00a0<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bdfcf1f elementor-widget elementor-widget-image\" data-id=\"bdfcf1f\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_21.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-43a37fc elementor-widget elementor-widget-text-editor\" data-id=\"43a37fc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>And in the top-left, you\u2019ll see an active pull request. Success!<\/p><p>At this point, you can go ahead and manually perform the review by testing with the updated version&#8230;. but we\u2019ve come so far with automation, so why not go all the way and automate away even the testing?<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-46f5d1e elementor-widget elementor-widget-heading\" data-id=\"46f5d1e\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Step 5: Testing our Model<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-223dfa0 elementor-widget elementor-widget-text-editor\" data-id=\"223dfa0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Even though the dependency itself has been tested before being officially released (or at least, it should be!), it\u2019s still a good idea to perform testing on our main, integrated module, for a few reasons. First, we may find a bug that was missed in testing the dependency. It may also be that our module is relying, whether consciously or not, on ambiguous or implementation-specific behavior of its dependency, in which case even a perfectly tested dependency may break when we integrate it into our main module. Finally, at the very least, we want to validate that no interfaces have changed, and the data flow is fully integrated between our main module and the dependency it\u2019s calling.<\/p><p>I\u2019m going to be using BTC EmbeddedPlatform to do this testing, specifically by running a series of requirements-based tests and then a back-to-back test between my model and code; there are, of course, different ways to quantify what is a \u2018passed\u2019 vs \u2018failed\u2019 test, and this is only one way of defining it. But regardless of what metrics matter to our specific project, if we do a good job defining our requirements and writing rigorous test cases, then when can just auto-merge our pull request without ever needing to do a manual review!<\/p><p>We\u2019re going to need to set up a few things. First, like with the dependency migration itself, we need to create our workflow yml that tells GitHub Actions what testing means to us. We\u2019ll also need to write a script to perform the actual testing, and for this example that\u2019s going to involve creating an .epp.<\/p><p>Let\u2019s start with the CI side of things. First, going back to the main module <a href=\"https:\/\/github.com\/thabok\/deps-swc-1\" target=\"_blank\" rel=\"noopener\">repository<\/a>, download the test.yml file under the .github\/workflows directory, and place it next to the version_update.yml. You can go ahead and check out the file if you\u2019re interested, but it\u2019s largely the same as one from the previous step.<\/p><p>Next up, let\u2019s write our testing scripts. Create a file, scripts\/run_tests.py, with the following contents:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-16a87a4 elementor-widget elementor-widget-text-editor\" data-id=\"16a87a4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">import sys<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">from glob import glob<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">from os import getcwd<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">from os.path import abspath, dirname<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">from btc_embedded import EPRestApi, util<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">def run_btc_test(epp_path, matlab_project_path, work_dir=getcwd()):<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 epp_path = abspath(epp_path)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 matlab_project_path = abspath(matlab_project_path)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 work_dir = dirname(epp_path)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # BTC EmbeddedPlatform API object<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 from btc_embedded import config<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 print(&#8220;##### GETTING MERGED CONFIG #####&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 print(config.get_merged_config())<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep = EPRestApi(config=config.get_merged_config())<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # Load a BTC EmbeddedPlatform profile (*.epp)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep.get(f&#8217;profiles\/{epp_path}?discardCurrentProfile=true&#8217;, message=&#8221;Loading profile&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # Load ML Project &amp; generate code generation<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep.put(&#8216;architectures&#8217;, message=&#8221;Analyzing Model &amp; Generating Code&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # Execute requirements-based tests<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 scopes = ep.get(&#8216;scopes&#8217;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 scope_uids = [scope[&#8216;uid&#8217;] for scope in scopes if scope[&#8216;architecture&#8217;] == &#8216;Simulink&#8217;]<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 toplevel_scope_uid = scope_uids[0]<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 rbt_exec_payload = {<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8216;UIDs&#8217;: scope_uids,<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8216;data&#8217; : {<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8216;execConfigNames&#8217; : [ &#8216;SL MIL&#8217;, &#8216;SIL&#8217; ]<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 }<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 response = ep.post(&#8216;scopes\/test-execution-rbt&#8217;, rbt_exec_payload, message=&#8221;Executing requirements-based tests&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 rbt_coverage = ep.get(f&#8221;scopes\/{toplevel_scope_uid}\/coverage-results-rbt?goal-types=MCDC&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 util.print_rbt_results(response, rbt_coverage)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # automatic test generation<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 vector_gen_config = { &#8216;pllString&#8217; : &#8216;MCDC;CA;DZ&#8217;, &#8216;scopeUid&#8217; : toplevel_scope_uid }<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep.post(&#8216;coverage-generation&#8217;, vector_gen_config, message=&#8221;Generating vectors&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 b2b_coverage = ep.get(f&#8221;scopes\/{toplevel_scope_uid}\/coverage-results-b2b?goal-types=MCDC&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # B2B SL MIL vs. SIL<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 response = ep.post(f&#8221;scopes\/{toplevel_scope_uid}\/b2b&#8221;, { &#8216;refMode&#8217;: &#8216;SL MIL&#8217;, &#8216;compMode&#8217;: &#8216;SIL&#8217; }, message=&#8221;Executing B2B test&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 util.print_b2b_results(response, b2b_coverage)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # Create project report<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 report = ep.post(f&#8221;scopes\/{toplevel_scope_uid}\/project-report?&#8221;, message=&#8221;Creating test report&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # export project report to a file called &#8216;report.html&#8217;<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep.post(f&#8221;reports\/{report[&#8216;uid&#8217;]}&#8221;, { &#8216;exportPath&#8217;: work_dir, &#8216;newName&#8217;: &#8216;test_report&#8217; })<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 # Save *.epp<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 ep.put(&#8216;profiles&#8217;, { &#8216;path&#8217;: epp_path }, message=&#8221;Saving profile&#8221;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 print(&#8216;Finished btc test workflow.&#8217;)<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\"># if the script is called directly: expect<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\"># &#8211; the first argument to be the epp path<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\"># &#8211; the sedocnd argument to be the ml project path<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">if __name__ == &#8216;__main__&#8217;:<\/span><\/p><p style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0\u00a0\u00a0 run_btc_test(sys.argv[1], sys.argv[2])<\/span><\/p><p><span style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a; font-size: medium;\"><span lang=\"EN-US\" style=\"font-size: 12pt; line-height: 18.56px; font-family: Aptos, sans-serif;\">\u00a0\u00a0\u00a0 # run_btc_test(&#8216;test\/swc_1.epp&#8217;, &#8216;swc_1.prj&#8217;)<\/span><\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a4c622d elementor-widget elementor-widget-text-editor\" data-id=\"a4c622d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This file has a lot of EP-specific code, which is well documented on our <a href=\"https:\/\/github.com\/btc-embedded\/btc_embedded\" target=\"_blank\" rel=\"noopener\">Github<\/a>, but the gist of what it\u2019s doing is invoking the EP REST API to open up our profile, run our tests, and create a project report. Going into the particular details is beyond the scope of this tutorial, but if you\u2019re interested you can always reach out for more info.<\/p><p>One final thing EP needs to run over CI is a config file, to tell it what version of EP to run, what version of Matlab is integrated, and where our license server exists. Create the file scripts\/btc_project_config.yml, with the following text:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a8eabef elementor-widget elementor-widget-text-editor\" data-id=\"a8eabef\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This file has a lot of EP-specific code, which is well documented on our <a href=\"https:\/\/github.com\/btc-embedded\/btc_embedded\" target=\"_blank\" rel=\"noopener\">Github<\/a>, but the gist of what it\u2019s doing is invoking the EP REST API to open up our profile, run our tests, and create a project report. Going into the particular details is beyond the scope of this tutorial, but if you\u2019re interested you can always reach out for more info.<\/p><p>One final thing EP needs to run over CI is a config file, to tell it what version of EP to run, what version of Matlab is integrated, and where our license server exists. Create the file scripts\/btc_project_config.yml, with the following text:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4369b0d elementor-widget elementor-widget-text-editor\" data-id=\"4369b0d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p class=\"MsoNormal\" style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoSubtleReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">epVersion: 23.3p0<\/span><\/p><p class=\"MsoNormal\" style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoSubtleReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">#licenseLocation: 27000@localhost<\/span><\/p><p class=\"MsoNormal\" style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoSubtleReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">preferences:<\/span><\/p><p class=\"MsoNormal\" style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoSubtleReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 GENERAL_MATLAB_CUSTOM_VERSION: MATLAB R2022b (64-bit)<\/span><\/p><p class=\"MsoNormal\" style=\"margin: 0cm 0cm 8pt; line-height: 18.56px; font-size: 12pt; font-family: Aptos, sans-serif; color: #000000;\"><span class=\"MsoSubtleReference\" style=\"font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-caps: small-caps; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; color: #5a5a5a;\">\u00a0 GENERAL_COMPILER_SETTING: MinGW64 (64bit)<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6a5d36b elementor-widget elementor-widget-text-editor\" data-id=\"6a5d36b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Adjusting the preferences depending on your particular environment values.<\/p><p><strong>Creating an EP Profile and Putting It All Together<\/strong><\/p><p>One more step to set up our testing! EP provides a persistent environment to store test cases and simulation results, and we need to create this profile so that we have a context for our tests to execute in, that our testing script can simply point to. To create this, open up Matlab and EP. Make sure to (temporarily) add in the dependency, shared_module_a.slx, to your path, so that we can generate code from our module. Go ahead and select a new \u2018EmbeddedCoder\u2019 type profile, and point it to swc1:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-027a727 elementor-widget elementor-widget-image\" data-id=\"027a727\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_22.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bc53c80 elementor-widget elementor-widget-text-editor\" data-id=\"bc53c80\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Click through the dialogue, adjusting any settings as needed. When everything looks good, press \u2019import\u2019. For the sake of completion, create an empty requirements-based test case, and then save the profile as swc_1.epp inside the test folder, and push it to git.<\/p><p>Once again: go ahead and trigger the workflow manually:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-66a46f3 elementor-widget elementor-widget-image\" data-id=\"66a46f3\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/www.btc-embedded.com\/wp-content\/uploads\/2024\/11\/blog_2_23.webp\" title=\"\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7487481 elementor-widget elementor-widget-text-editor\" data-id=\"7487481\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Success! We can even see our test results, bundled up in a nice little HTML under our \u2018artifacts.\u2019 This shows us that all of our test cases passed, and we can see a detailed breakdown of any discrepancies if we were to detect any failures.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3b7fb9e elementor-widget elementor-widget-heading\" data-id=\"3b7fb9e\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Summary<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-349560c elementor-widget elementor-widget-text-editor\" data-id=\"349560c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Phew! That was a lot! We went from an empty repository to a fully-fledged CI pipeline, in just a few hours. To summarize everything we did:<\/p><ol><li>We created a Simulink project and separated it out into its main constituent and its dependency. These are versioned, developed, and served separately!<\/li><li>We set up an Artifactory server where our dependency can push\/upload newer releases of itself, for consumption by the main constituent.<\/li><li>We configured a conanfile for both main and dependent components, to allow them to either release a public-facing version, or download said version as a dependency.<\/li><li>We created a CI script to automatically check for dependency version updates and create a new branch and pull-request with the updated dependency version, if we detect one.<\/li><li>We created a similar CI script to run unit-testing which validates the results of migrating our software, to confirm that the dependency migration hasn\u2019t broken our main module functionality.<\/li><\/ol><p>The only thing we haven\u2019t done is connect the last two steps, to merge our pull request automatically if it passes. Well, that, and push our pipeline to a production setting; I\u2019ll leave that as an exercise for the reader<\/p><p>Thank you for joining me! Until next time!<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>If you\u2019ve ever had to deal with manually migrating dependencies to the latest version, you know how difficult  [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":15637,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"elementor_theme","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[136,53,137,48,138,51,80,139],"product":[],"use_cases":[],"class_list":["post-15636","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-embedded-coder","tag-iso-26262","tag-matlab","tag-simulink","tag-standard-tools","tag-targetlink","tag-test-generation","tag-testing"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/posts\/15636","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/comments?post=15636"}],"version-history":[{"count":1,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/posts\/15636\/revisions"}],"predecessor-version":[{"id":15639,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/posts\/15636\/revisions\/15639"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/media\/15637"}],"wp:attachment":[{"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/media?parent=15636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/categories?post=15636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/tags?post=15636"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/product?post=15636"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.btc-embedded.jp\/ja\/wp-json\/wp\/v2\/use_cases?post=15636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}