{"id":2600,"date":"2021-03-17T13:11:36","date_gmt":"2021-03-17T17:11:36","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=2600"},"modified":"2021-03-25T21:56:58","modified_gmt":"2021-03-26T01:56:58","slug":"coming-around-full-circle","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2021\/03\/17\/coming-around-full-circle\/","title":{"rendered":"Coming around full Circle"},"content":{"rendered":"<div class=\"content\"><p>CI services in the cloud. They are beautiful. All you need to do is drop a little bit o' yaml in your repository and a whole world of automated build and test infrastructure starts creating some good clean fun with your commits. The kind of good clean fun that actually makes your code cleaner. You don't need to set up your machines, you don't need to worry about the power button on your CI server (or your agents for that matter). It's all just done for you and it's lovely.<\/p><p>A little while ago we showed how MATLAB, Simulink, and most toolboxes are now supported on a variety of cloud CI services for public projects. Today, I'd like to highlight one of these services, <a href=\"https:\/\/circleci.com\">CircleCI<\/a>, in a little more detail. CircleCI is a top CI platform that supports repositories on both GitHub and Bitbucket.<\/p><p>To show you how this can work with MATLAB and Simulink code, let me remind you about our deep learning repository highlighting face detection using a multi-task cascaded convolutional neural network (MTCNN). This is a nice project that we can use to show some of the benefits of a platform like CircleCI.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_mtcnn_repo.png\" alt=\"\"> <\/p><p>First, let's see how easy it is for us to run the tests this repo specifies to run. This repo uses a <a href=\"https:\/\/blogs.mathworks.com\/developer\/2020\/08\/19\/tests-in-projects\/\">MATLAB project<\/a> to label all the tests to be run. Assuming the repository is already <a href=\"https:\/\/circleci.com\/docs\/2.0\/getting-started\/#setting-up-circleci\">setup to build with CircleCI<\/a>, you can then immediately reap the benefits from an <a href=\"https:\/\/circleci.com\/developer\/orbs\/orb\/mathworks\/matlab\">orb that we have developed to streamline your MATLAB and Simulink builds<\/a>. What are orbs you say? They are sharable nuggets of CI config. In our case it helps you define how you can get MATLAB to CircleCI cloud agents, how you can run arbitrary MATLAB commands, and how you can easily run tests with some of the most common options.<\/p><p>For example, let's say we start by running our tests and producing a couple popular artifacts, a JUnit-style xml output and a PDF test report, the former for integrating with CircleCI test results views and the latter for archiving purposes and rich MATLAB and Simulink specific reporting information (e.g. like we see <a href=\"https:\/\/blogs.mathworks.com\/developer\/2018\/11\/13\/simulink-test-html-report\/\">here<\/a>, <a href=\"https:\/\/blogs.mathworks.com\/developer\/2018\/07\/30\/semi-automated-testing\/\">here<\/a>, and <a href=\"https:\/\/blogs.mathworks.com\/developer\/2016\/11\/17\/test-report\/\">here<\/a>). First we start by adding to a CircleCI YAML config file some version information, both for what version of the CircleCI configuration spec we are using and what version of our orb we will be using. We will use the most current versions of both the spec and the orb.<\/p><p>Then, you set up the executor type, which is the machine or image that you will be using to run your build. In this case we will use a recent version of Ubuntu. Note, that if you are using a Linux cloud agent machine image in a public project, you can setup MATLAB quickly and easily using the <tt>install<\/tt> element that you get with our orb.<\/p><p>Once MATLAB is squared away, you can then define a job that can be referenced in a workflow to produce our JUnit and PDF artifacts from the test run by using the <tt>run-tests<\/tt> element and simply telling the orb where to create the artifacts.<\/p><p>We then, as part of the same job, store these artifacts using the built-in <tt>store_test_results<\/tt> element (to process the JUnit-style XML output), and the <tt>store_artifacts<\/tt> element to save away both the PDF report and the XML for saving keeping. Here's is what that looks like:<\/p><p>Finally, we reference this job we've defined in a workflow and we are all good.<\/p><pre class=\"language-matlab\">version: 2.1\r\norbs:\r\n   matlab: mathworks\/matlab@0.4.0\r\njobs:\r\n  run-all-dem-magnificient-matlab-tests:\r\n    machine:\r\n      image: ubuntu-2004:202101-01\r\n    steps:\r\n      - checkout\r\n      - matlab\/install\r\n      - matlab\/run-tests:\r\n          test-results-junit: artifacts\/junit\/testResults.xml\r\n          test-results-pdf: artifacts\/pdf\/testResults.pdf\r\n      - store_test_results:\r\n          path: artifacts\/junit\r\n      - store_artifacts:\r\n          path: artifacts\r\nworkflows:\r\n  test:\r\n    jobs:\r\n      - run-all-dem-magnificient-matlab-tests\r\n<\/pre><p>Alright, now let's run a build with that and see what we are lookin like:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_first_build.gif\" alt=\"\"> <\/p><p>Note I sped up the video of this build for brevity. You can see however, that CircleCI spins up a build agent, MATLAB is setup on this agent, and the tests run and pass, all in a matter of minutes. What's more, it saved us some artifacts! Let's check out the PDF report:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_report_inspection.gif\" alt=\"\"> <\/p><p>Alright there's a couple cool things here:<\/p><div><ol><li>Can we say artifacts? It's pretty easy to get a streamlined way to store record keeping artifacts like pdf results<\/li><li>These reports can contain additional richness like images, plots and visualizations, screenshots, and if you are using Simulink Test, signal level comparisons and visualizations. Dope. In this case we are including images generated from the example doc code, which is tested to ensure the examples execute without error, and the resulting figures are logged using a FigureDiagnostic (similar to what we did in <a href=\"https:\/\/blogs.mathworks.com\/developer\/2018\/07\/30\/semi-automated-testing\/\">this post<\/a>).<\/li><li><i>Look at 'dem filtered tests<\/i>! Alright, while not super cool that we have some tests that are filtered out, it is at least nice that we are able to see this pretty cleanly from the report. Digging into the diagnostics we see that the reason these tests are filtered out is because they require a GPU to run.<\/li><\/ol><\/div><p>Ah well, on that last point, we can't get too picky right? After all we are leveraging a cloud service that is handling all of our machine configuration for us, so we shouldn't expect to be able to run tests that need GPUs in the cloud. I guess we will just have to remember to run those tests from time to time offline on our own machines with GPUs.<\/p><p><b>Wrong!<\/b><\/p><p>As it turns out, CircleCI has a plan that <a href=\"https:\/\/circleci.com\/build-environments\/gpu\/\">supports machines with GPU hardware<\/a>! Isn't that nice? Trying that out here on our build simply means changing our yaml snippet from this:<\/p><pre class=\"language-matlab\">machine:\r\n  image: ubuntu-2004:202101-01\r\n<\/pre><p>...to something like this:<\/p><pre class=\"language-matlab\">resource_class: gpu.nvidia.small\r\nmachine:\r\n  image: ubuntu-1604-cuda-11.1:202012-01\r\n<\/pre><p>Now if your CircleCI plan has GPUs enabled, with that small snippet you can see our build is now using a machine with a GPU:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_GPU_View.png\" alt=\"\"> <\/p><p>However, we have a problem!<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_failed_tests.gif\" alt=\"\"> <\/p><p>Looks like we have some test failures. That was unexpected (really, it was unexpected as I was writing this blog!) Turns out, when you don't test things in automation, test failures creep in. That's why having all your tests automated under CI is really a must have. In this case, this deep-learning repository began failing in R2020b with the introduction of gpuArray support for <tt>selectStrongestBbox<\/tt> from the Computer Vision Toolbox. Long story short, it was an easy fix, we simply needed to shift around a <tt>gather<\/tt> call around the gpuArray to account for these differences in earlier releases. However, just getting early detection of this bug required that we run on GPU hardware, so this is a great feature of the CircleCI platform to enable that. Also, take note of that clean test results failure display that we see because we uploaded our JUnit-style xml artifacts. Nice bonus.<\/p><p>I seem to remember that once or twice I have heard that GPUs can be otherwise useful in deep learning applications? Does that sound right? <i>grin<\/i> Just imagine what automated workflows you could do with the power of MATLAB &amp; CircleCI.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_81d5c9fd5ac94446bf1430eb59304bbe() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='81d5c9fd5ac94446bf1430eb59304bbe ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 81d5c9fd5ac94446bf1430eb59304bbe';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2021 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_81d5c9fd5ac94446bf1430eb59304bbe()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2021a<br><\/p><\/div><!--\r\n81d5c9fd5ac94446bf1430eb59304bbe ##### SOURCE BEGIN #####\r\n%%\r\n% CI services in the cloud. They are beautiful. All you need to do is drop\r\n% a little bit o' yaml in your repository and a whole world of automated\r\n% build and test infrastructure starts creating some good clean fun with\r\n% your commits. The kind of good clean fun that actually makes your code\r\n% cleaner. You don't need to set up your machines, you don't need to worry\r\n% about the power button on your CI server (or your agents for that\r\n% matter). It's all just done for you and it's lovely.\r\n%\r\n% A little while ago we showed how MATLAB, Simulink, and most toolboxes are\r\n% now supported on a variety of cloud CI services for public projects.\r\n% Today, I'd like to highlight one of these services, <https:\/\/circleci.com\r\n% CircleCI>, in a little more detail. CircleCI is a top CI platform that\r\n% supports repositories on both GitHub and Bitbucket.\r\n%\r\n% To show you how this can work with MATLAB and Simulink code, let\r\n% me remind you about our deep learning repository highlighting face\r\n% detection using a multi-task cascaded convolutional neural network\r\n% (MTCNN). This is a nice project that we can use to show some of the\r\n% benefits of a platform like CircleCI.\r\n%\r\n% <<y2021circle_mtcnn_repo.png>>\r\n%\r\n% First, let's see how easy it is for us to run the tests this repo\r\n% specifies to run. This repo uses a\r\n% <https:\/\/blogs.mathworks.com\/developer\/2020\/08\/19\/tests-in-projects\/\r\n% MATLAB project> to label all the tests to be run. Assuming the repository\r\n% is already\r\n% <https:\/\/circleci.com\/docs\/2.0\/getting-started\/#setting-up-circleci setup\r\n% to build with CircleCI>, you can then immediately reap the benefits from\r\n% an <https:\/\/circleci.com\/developer\/orbs\/orb\/mathworks\/matlab orb that we\r\n% have developed to streamline your MATLAB and Simulink builds>. What are\r\n% orbs you say? They are sharable nuggets of CI config. In our case it\r\n% helps you define how you can get MATLAB to CircleCI cloud agents, how you\r\n% can run arbitrary MATLAB commands, and how you can easily run tests with\r\n% some of the most common options.\r\n% \r\n% For example, let's say we start by running our tests and producing a\r\n% couple popular artifacts, a JUnit-style xml output and a PDF test report,\r\n% the former for integrating with CircleCI test results views and the\r\n% latter for archiving purposes and rich MATLAB and Simulink specific\r\n% reporting information (e.g. like we see\r\n% <https:\/\/blogs.mathworks.com\/developer\/2018\/11\/13\/simulink-test-html-report\/\r\n% here>,\r\n% <https:\/\/blogs.mathworks.com\/developer\/2018\/07\/30\/semi-automated-testing\/\r\n% here>, and <https:\/\/blogs.mathworks.com\/developer\/2016\/11\/17\/test-report\/\r\n% here>). First we start by adding to a CircleCI YAML config file some\r\n% version information, both for what version of the CircleCI configuration\r\n% spec we are using and what version of our orb we will be using. We will\r\n% use the most current versions of both the spec and the orb.\r\n%\r\n% Then, you set up the executor type, which is the machine or image that\r\n% you will be using to run your build. In this case we will use a recent\r\n% version of Ubuntu. Note, that if you are using a Linux cloud agent\r\n% machine image in a public project, you can setup MATLAB quickly and\r\n% easily using the |install| element that you get with our orb. \r\n%\r\n% Once MATLAB is squared away, you can then define a job that can be\r\n% referenced in a workflow to produce our JUnit and PDF artifacts from the\r\n% test run by using the |run-tests| element and simply telling the orb\r\n% where to create the artifacts.\r\n%\r\n% We then, as part of the same job, store these artifacts using the\r\n% built-in |store_test_results| element (to process the JUnit-style XML\r\n% output), and the |store_artifacts| element to save away both the PDF\r\n% report and the XML for saving keeping. Here's is what that looks like:\r\n% \r\n% Finally, we reference this job we've defined in a workflow and we are all\r\n% good.\r\n%\r\n%   version: 2.1\r\n%   orbs:\r\n%      matlab: mathworks\/matlab@0.4.0\r\n%   jobs:\r\n%     run-all-dem-magnificient-matlab-tests:\r\n%       machine:\r\n%         image: ubuntu-2004:202101-01\r\n%       steps:\r\n%         - checkout\r\n%         - matlab\/install\r\n%         - matlab\/run-tests:\r\n%             test-results-junit: artifacts\/junit\/testResults.xml\r\n%             test-results-pdf: artifacts\/pdf\/testResults.pdf\r\n%         - store_test_results:\r\n%             path: artifacts\/junit\r\n%         - store_artifacts: \r\n%             path: artifacts\r\n%   workflows:\r\n%     test:\r\n%       jobs:\r\n%         - run-all-dem-magnificient-matlab-tests\r\n%\r\n% Alright, now let's run a build with that and see what we are lookin like:\r\n%\r\n% <<y2021circle_first_build.gif>>\r\n%\r\n% Note I sped up the video of this build for brevity. You can see however,\r\n% that CircleCI spins up a build agent, MATLAB is setup on this agent, and\r\n% the tests run and pass, all in a matter of minutes. What's more, it saved\r\n% us some artifacts! Let's check out the PDF report:\r\n%\r\n% <<y2021circle_report_inspection.gif>>\r\n%\r\n% Alright there's a couple cool things here:\r\n%\r\n% # Can we say artifacts? It's pretty easy to get a streamlined way to\r\n% store record keeping artifacts like pdf results\r\n% # These reports can contain additional richness like images, plots and\r\n% visualizations, screenshots, and if you are using Simulink Test, signal\r\n% level comparisons and visualizations. Dope. In this case we are including\r\n% images generated from the example doc code, which is tested to ensure the\r\n% examples execute without error, and the resulting figures are logged\r\n% using a FigureDiagnostic (similar to what we did in\r\n% <https:\/\/blogs.mathworks.com\/developer\/2018\/07\/30\/semi-automated-testing\/\r\n% this post>).\r\n% # _Look at 'dem filtered tests_! Alright, while not super cool that we have\r\n% some tests that are filtered out, it is at least nice that we are able to\r\n% see this pretty cleanly from the report. Digging into the diagnostics we\r\n% see that the reason these tests are filtered out is because they require\r\n% a GPU to run.\r\n%\r\n% Ah well, on that last point, we can't get too picky right? After all we\r\n% are leveraging a cloud service that is handling all of our machine\r\n% configuration for us, so we shouldn't expect to be able to run tests that\r\n% need GPUs in the cloud. I guess we will just have to remember to run\r\n% those tests from time to time offline on our own machines with GPUs.\r\n%\r\n% *Wrong!*\r\n%\r\n% As it turns out, CircleCI has a plan that <https:\/\/circleci.com\/build-environments\/gpu\/\r\n% supports machines with GPU hardware>! Isn't that nice? Trying that out\r\n% here on our build simply means changing our yaml snippet from this:\r\n%\r\n%   machine:\r\n%     image: ubuntu-2004:202101-01\r\n%\r\n% ...to something like this:\r\n%\r\n%   resource_class: gpu.nvidia.small\r\n%   machine:\r\n%     image: ubuntu-1604-cuda-11.1:202012-01\r\n%\r\n% Now if your CircleCI plan has GPUs enabled, with that small snippet you\r\n% can see our build is now using a machine with a GPU:\r\n%\r\n% <<y2021circle_GPU_View.png>>\r\n%\r\n% However, we have a problem!\r\n%\r\n% <<y2021circle_failed_tests.gif>>\r\n%\r\n% Looks like we have some test failures. That was unexpected (really,\r\n% it was unexpected as I was writing this blog!) Turns out, when you\r\n% don't test things in automation, test failures creep in. That's why\r\n% having all your tests automated under CI is really a must have. In this\r\n% case, this deep-learning repository began failing in R2020b with the\r\n% introduction of gpuArray support for |selectStrongestBbox| from the\r\n% Computer Vision Toolbox. Long story short, it was an easy fix, we simply\r\n% needed to shift around a |gather| call around the gpuArray to account for\r\n% these differences in earlier releases. However, just getting early\r\n% detection of this bug required that we run on GPU hardware, so this is a\r\n% great feature of the CircleCI platform to enable that. Also, take note of\r\n% that clean test results failure display that we see because we uploaded\r\n% our JUnit-style xml artifacts. Nice bonus. \r\n%\r\n% I seem to remember that once or twice I have heard that GPUs can be\r\n% otherwise useful in deep learning applications? Does that sound right?\r\n% _grin_ Just imagine what automated workflows you could do with the power\r\n% of MATLAB & CircleCI.\r\n##### SOURCE END ##### 81d5c9fd5ac94446bf1430eb59304bbe\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2021circle_GPU_View.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><p>CI services in the cloud. They are beautiful. All you need to do is drop a little bit o' yaml in your repository and a whole world of automated build and test infrastructure starts creating some good... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2021\/03\/17\/coming-around-full-circle\/\">read more >><\/a><\/p>","protected":false},"author":90,"featured_media":2610,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[22,4,7,10],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2600"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=2600"}],"version-history":[{"count":7,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2600\/revisions"}],"predecessor-version":[{"id":2626,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2600\/revisions\/2626"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media\/2610"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=2600"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=2600"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=2600"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}