avatarsimbu

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

9286

Abstract

j85Mw.png"><figcaption></figcaption></figure><p id="fc2b">Checkout the documentation for more info on common Environment Variables:</p><ul><li><a href="https://docs.codemagic.io/variables/environment-variable-groups/#example-for-ios-builds">iOS</a></li><li><a href="https://docs.codemagic.io/variables/environment-variable-groups/#example-for-android-builds">Android</a></li></ul><p id="85fe">We can now start adding the tasks tasks to our Codemagic integration workflow.</p><p id="e1c1">You can access the the workflow code anytime in the <a href="https://gitlab.com/simbu-mobile/digestibleme">DigestableMe project</a> on GitLab in the <a href="https://gitlab.com/simbu-mobile/digestibleme/-/blob/main/codemagic.yaml">codemagic.yaml</a> file.</p><h2 id="80b4">Task — Check Code Quality</h2><p id="cc0c">This task will run code analysis on the project and highlight code that will be difficult to maintain or puts the codebase at risk.</p><p id="1e50">The task is added to the <b>scripts</b> section in codebase.yaml</p><figure id="7364"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*txueuCKrzcXq3Le1mF8Z6w.png"><figcaption></figcaption></figure><p id="b34d">The rules are add to the project pubspec.yaml file.</p><figure id="7881"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Kg5w3MiBqDitoDNG1x8OzA.png"><figcaption></figcaption></figure><p id="6fad">The output is save as a build artifact:</p><figure id="3c5e"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*wLZcW-vGz1XIHhGVQggWag.png"><figcaption></figcaption></figure><h2 id="aa5d">Task — Run local unit and widget tests</h2><p id="8530">This task will pick up any unit or widget tests files under the /test directory of the project that end in _test.dart</p><p id="475f">Task script:</p><figure id="55a1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*4v2dy1FOHeHrQ5xPagGi5g.png"><figcaption></figcaption></figure><p id="f3d7">Artifact:</p><figure id="3e21"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*QIRrpXZ5zWLuxNnxtglr0A.png"><figcaption></figcaption></figure><h2 id="bba4">Task — Sign and build an iOS version of the application</h2><p id="9078">Script Tasks:</p><figure id="a18d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ALk7RvMu94G9a5F4zpU4pQ.png"><figcaption></figcaption></figure><p id="86ec">Artifact:</p><figure id="47af"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*CWKGALEfGrffmszU3FTpMw.png"><figcaption></figcaption></figure><p id="9367">Codemagics API to integrate with Apple really helps you out with the signing process.</p><p id="c3b7">It will work out what the app needs and create any certificates to complete the signing, amazing…</p><figure id="154b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*m-UESt4d9kVVbaDs-mXiJg.png"><figcaption></figcaption></figure><h2 id="d203">Task — Sign and build an Android version of the application</h2><p id="2992">Script Tasks:</p><figure id="cff1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*xj4EJANoqsM1nOoJs-_BNQ.png"><figcaption></figcaption></figure><figure id="4f07"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*P600vL6Kgi-2cQRw3fW6Kg.png"><figcaption></figcaption></figure><p id="3501">Artifact:</p><figure id="76b1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*UMP3_3HJMLZRuFE0lnn8OA.png"><figcaption></figcaption></figure><h2 id="9d3a">Task — TestLab</h2><p id="760b">With the Google’s Firebase TestLab you can run your coded integration tests on multiple real devices and run a <i>robo</i> test that will discover and run through all the screens in your app, again on multiple devices.</p><p id="822e">Powerful stuff that will give you confidence that you application can run on devices that you wish to support.</p><p id="5791">The flip side is these valuable tests take time to run and that comes with a £ cost for using the service.</p><p id="c25a">To setup integrations tests and get your project ready for Firebase TestLab run through the <a href="https://www.youtube.com/watch?v=izajHHFSa8o">Flutter Integration Test Tutorial</a>.</p><p id="2220">Once setup add the two scripts to the integration workflow:</p><figure id="0bd1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*r1d5ZkjJQjLakfauUyYbbg.png"><figcaption></figcaption></figure><p id="433c">See the sections under <a href="#XP">XP</a> below for details on how to run TestLab locally.</p><h2 id="b09e">Ta Da</h2><p id="946f">Built and Regression Tested!</p><figure id="3d67"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*LoeHehEyIy6piMIW_4XK_g.png"><figcaption></figcaption></figure><p id="b6db">When everything passes and the testers are notified by email with links to install the version locally on their devices!</p><figure id="e05b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*-nlmQCt-Y2AzvUqhy0VIsQ.png"><figcaption></figcaption></figure><h2 id="4874">Service Access</h2><h2 id="98e7">App Store Connect Access</h2><figure id="8e24"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*aGPPxOIe-MqaBcLunH0cZg.png"><figcaption></figcaption></figure><p id="0329">See the <a href="https://docs.codemagic.io/yaml-code-signing/signing-ios/">Codemagic instructions</a> for more details.</p><p id="cb6b">NB: You may need to refresh the page after creation before the download link becomes visible.</p><p id="a1df">Collect the secret values:</p><div id="0232"><pre>APP<span class="hljs-emphasis">STORE_CONNECT_ISSUER_ID APP_STORE_CONNECT_KEY_IDENTIFIER APP_STORE_CONNECT_PRIVATE_KEY CERTIFICATE_PRIVATE_KEY BUNDLE</span>ID</pre></div><p id="5395">The issuer id and key identifier are values you saved during the creation of the API key.</p><p id="43a8">The ‘APP_STORE_CONNECT_PRIVATE_KEY’ is the key you download from the App Store Connect after creating the API key, the <hash>.p8 file. Just copy the contents directly into the environment variable value.</hash></p><p id="e4ba">The ‘CERTIFICATE_PRIVATE_KEY’ is an RSA 2048 bit private key to be included in the signing certificate that Codemagic creates. You can use an existing key or create a new 2048 bit RSA key:</p><div id="7930"><pre>ssh-keygen -<span class="hljs-built_in">t</span> rsa -b <span class="hljs-number">2048</span> -m PEM -f ~/Desktop/codemagic_private_key -q -<span class="hljs-built_in">N</span> <span class="hljs-string">""</span></pre></div><p id="1a6b">Copy the all the content from the private key file into the environment variable value.</p><p id="71b6">BUNDLE_ID is the unique id for application and you define it when you create an identity in your Apple developer account.</p><p id="85ef">You can find the iOS bundle id in your apple developer account under identifiers.</p><figure id="5425"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*olxgZy3mvNc72ow000oEJQ.png"><figcaption></figcaption></figure><p id="f783">Apple recommend using a reverse-domain name style string i.e.</p><p id="b104"><i>icom.domainname.appname</i></p><p id="6c93">It cannot contain an asterisk.</p><h2 id="42f6">Firebase Access for TestLab</h2><p id="bd8c">You will need to set up the following in the Firebase console.</p><ul><li>Create a Firebase project.</li><li><a href="https://docs.codemagic.io/knowledge-base/google-services-authentication/">Create a service account</a> with Editor permissions and download the JSON key file so you can authenticate with Firebase Test Lab during the build.</li><li><a href="https://console.cloud.google.com/apis/library/toolresults.googleapis.com?pli=1&amp;project=woven-voyage-217607&amp;folder=&amp;organizationId=">Enable the Cloud Tools Results API.</a></li></ul><p id="af12">Collect the secret values:</p><div id="1fe5"><pre>GCLOUD<span class="hljs-emphasis">KEY_FILE FIREBASE</span>PROJECT</pre></div><p id="69fe">Where:</p><p id="7c60">GCLOUD_KEY_FILE — service account JSON key file, FIREBASE_PROJECT — your Firebase Project ID, you can find it under project-settings-general in the Firebase console.</p><figure id="64b9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*iYWGlz4VHMRAI31oBWViKg.png"><figcaption></figcaption></figure><h2 id="8d7e">Play Store Access & Signing</h2><p id="54ca">Google allows you to <a href="https://docs.codemagic.io/flutter-code-signing/android-code-signing/#generating-a-keystore">manage your signing credentials locally</a>, but it’s better to let Google <a href="https://docs.flutter.dev/deployment/android#signing-the-app">manage them in the cloud</a> like the Apple App Store does.</p><p id="4937">For this workflow we will just create a default debug keystore directly in the codebase.yaml file, which will be fine for integration and ad-hoc testing.</p><p id="1a20">When we need to deploy to the Play Store we will setup the keystore in the Google cloud, this will be covered in the continuous deployment post.</p><h2 id="04bd">XP</h2><h2 id="3565">Codemagic</h2><p id="991c">I found most difficult thing at first was to understand the sections in codebase.yaml file.</p><p id="7f12">In addition to the <a href="https://docs.codemagic.io/yaml/yaml-getting-started/">official documentation</a> and google, a

Options

few of things really helped with this.</p><p id="15b0">Firstly you can setup workflow using the UI and then switch to yaml configuration and export the values from the workflow you have setup.</p><figure id="d759"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*39NHTHJw7trutCTvZfCpYg.png"><figcaption></figcaption></figure><figure id="38b5"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Lkdc6jBWlj3l6qR--8QM-A.png"><figcaption></figcaption></figure><p id="d020">You can use builder mode to give some contextual help.</p><figure id="b7c6"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*aynfrY40YA77zBCK7VmTDg.png"><figcaption></figcaption></figure><figure id="e079"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*w68Jmrw7h3cqq-P1FeustA.png"><figcaption></figcaption></figure><p id="27f3">When things go a little tougher like integrating with TestLab I eventually had to download the Firebase CLI and get the script running locally before going back to the workflow and plugging it in.</p><h2 id="b069">Firebase</h2><p id="1c84">I needed to install the API to list device models for TestLab and run tests without going through CodeMagic that was costing a lot of build minutes.</p><p id="01f4">See <a href="https://firebase.google.com/docs/cli">Firebase CLI reference </a>for more details. On the Mac you can install it with the this command.</p><p id="3d3c"><code>curl -sL https://firebase.tools | bash</code></p><p id="f020">Then login with this command.</p><p id="17c4"><code>firebase login</code></p><p id="7d37">Install gcloud</p><p id="8c25"><code>curl https://sdk.cloud.google.com | bash</code></p><p id="b376">Login</p><p id="8c6b"><code>gcloud auth login</code></p><p id="16f3">And list device models with this.</p><p id="013e"><code>gcloud firebase test android models list</code></p><p id="8d08">Note you can change the gcloud login account(email) with</p><p id="89e0"><code>gcloud config set account ACCOUNT</code></p><h2 id="567f">Firebase TestLab</h2><p id="6ae4">On the free spark plan you have the following allowance</p><figure id="7231"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*mIBerp_cs9lM6NvFGHn3Tg.png"><figcaption></figcaption></figure><p id="d245">Once you have the firebase and gcloud CLI’s installed you can run TestLab tests directly and plug the commands back into the codemagic.yaml file.</p><p id="95dd">To run the tests you will need to set the project id first:</p><p id="4ece"><code>gcloud config set project PROJECT_ID</code></p><p id="9fda">You can find the project id by list all projects in your firebase console.</p><p id="59f2">Do this by downloading the Android build artifacts and then modifying the codemagic.yaml command from</p><figure id="5932"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*aUy063gtVJWosxlgJRXCeg.png"><figcaption></figcaption></figure><p id="aa03">To</p><div id="393c"><pre>gcloud firebase <span class="hljs-keyword">test</span> android <span class="hljs-keyword">run</span>
--<span class="hljs-keyword">type</span> instrumentation
--<span class="hljs-keyword">app</span> <span class="hljs-keyword">app</span>-debug.apk
--<span class="hljs-keyword">test</span> <span class="hljs-keyword">app</span>-debug-androidTest.apk
--timeout 3m</pre></div><p id="f584">So that it points at the download build artifacts.</p><p id="1730">You can specify a device using — device, can be added multiple times for multiple devices.</p><div id="dca6"><pre>--device <span class="hljs-attribute">model</span>=redfin,orientation=portrait </pre></div><p id="2721">Be careful to choose a device that supports your SDK, when devices have multiple then you need to specify one:</p><div id="b01d"><pre><span class="hljs-params">--device</span> model=redfin,<span class="hljs-keyword">version</span>=28 </pre></div><p id="4c97">See <a href="https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run">gcloud firebase test android run command documentation</a> for more command options.</p><p id="e56f">Once you have the tests setup and passing make the changes back to codemagic.yaml and you are good to go.</p><h2 id="fa84">BackBurner</h2><h2 id="de03">Local Integration Tests</h2><p id="0f8b">If you run up an emulator or attach a device then you can run all the integrations tests locally.</p><p id="53da">I would have liked to run local integration tests before the TestLab tests to catch breaking tests earlier and avoid running breaking tests on multiple devices, which is costly, time and money.</p><p id="f763">You can run the tests local using this command, but you need a device or emulator running.</p><div id="d5c6"><pre>flutter drive <span class="hljs-attribute">--driver</span>=test_driver/integration_driver.dart <span class="hljs-attribute">--target</span>=integration_test/app_test.dart</pre></div><h2 id="b0f2">Web Integration</h2><p id="ea2e">I ran out of time to add the following actions to my CI workflow.</p><ul><li>Build a website version.</li><li>Run integration tests BrowserStack or other test tool.</li></ul><h2 id="2ac2">Google Play Store — Automatic cloud managed signing</h2><p id="68d8">Implement <a href="https://support.google.com/googleplay/android-developer/answer/7384423?hl=en">automatic cloud managed signing</a> as described in the <a href="https://docs.flutter.dev/deployment/android#signing-the-app">Flutter documentation</a> to sign an Android app.</p><p id="c05e">For now I’ve just created a debug version of the keystore, directly in the codemagic.yaml file.</p><h2 id="84ed">Integrate iOS app with Firebase Test Lab.</h2><p id="b93d">The <a href="https://docs.codemagic.io/yaml-testing/firebase-test-lab/">official documentation</a> requires a manual step to build the iOS runner for integration and upload to Firebase as a zipped file.</p><figure id="e7d0"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*bZo-OGUQC_A1NDWeKsLRtg.png"><figcaption></figcaption></figure><p id="d999">For now I’ve decided to integrate the Android package and come back to this.</p><p id="30f1">Ideally I will be able to create a script to package the iOS application for Firebase TestLab.</p><p id="0ce7">One of the options I will consider when returning to this is integrate with FastLane and use the plugin to integrate with Firebase TestLabs</p><p id="c5fc"><a href="https://github.com/fastlane/fastlane-plugin-firebase_test_lab">Fastlane plugin — Firebase TestLab</a></p><h2 id="afd9">Sound & Vision</h2><figure id="a049"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*4jZPeroWeDpxAwl11WN9iA.png"><figcaption></figcaption></figure><figure id="1afd"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*l8X2KPxb5LTlIqE0aQLK2w.png"><figcaption></figcaption></figure><figure id="a83b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*g73MYkf1OiSaV4GWR6NQ3g.jpeg"><figcaption></figcaption></figure><h2 id="976a">Links</h2><ul><li><a href="https://youtu.be/1SXpE08hvGs">The Gitflow workflow in less than five minutes</a></li><li><a href="https://readmedium.com/4-branching-workflows-for-git-30d0aaee7bf">4 Git branching workflows</a></li><li><a href="https://readmedium.com/streamline-a-super-efficient-branching-and-ci-strategy-ffa864aa99d4">Streamline: A super-efficient branching and CI strategy</a></li><li><a href="https://docs.codemagic.io/yaml/yaml-getting-started/">Using Codemagic yaml</a></li><li><a href="https://docs.codemagic.io/yaml-code-signing/signing-android/">CodeMagic Signing Android Apps</a></li><li><a href="https://docs.codemagic.io/flutter-code-signing/ios-code-signing/">CodeMagic iOS code signing</a></li><li><a href="https://blog.codemagic.io/app-store-connect-api-codemagic-cli-tools/">How to set up automatic iOS code signing using App Store Connect API keys</a></li><li><a href="https://docs.codemagic.io/yaml-testing/firebase-test-lab/">Integrate Firebase TestLab with Codemagic</a></li><li><a href="https://support.google.com/firebase/answer/6386654?hl=en#zippy=%2Cin-this-article">Run tests with Firebase Test Lab for Android</a></li><li><a href="https://www.youtube.com/watch?v=izajHHFSa8o">Flutter Integration Test Tutorial Inc. Firebase & Codemagic</a></li><li><a href="https://youtu.be/D6V-pyE_ywA">Firebase Test Lab: using Robo Tests (Firecasts)</a></li><li><a href="https://youtu.be/yX1truEFmQ4">Faster release builds and better integration tests with Flutter</a></li></ul><h2 id="18df">One more thing…</h2><blockquote id="3740"><p>Generally, the best way to learn git is probably to first only do very basic things and not even look at some of the things you can do until you are familiar and confident about the basics.</p></blockquote><p id="83e6">_Linus Torvalds</p><h1 id="398c">Other posts in the series</h1><p id="7b3e">Development</p><ul><li><a href="/@simbu/flutter-layout-aca3bbe4714d">Layout</a></li><li><a href="/@simbu/709f87b6a244?source=your_stories_page-m">Lists</a></li></ul><p id="b232">DevOps:</p><ul><li><a href="/@simbu/flutter-ci-workflow-460a00eb782e">Continuous Integration — Workflow</a></li><li><a href="/@simbu/flutter-ci-web-8d081bcbec5">Continuous Integration — Web</a></li></ul></article></body>

Join Medium to view all my articles.

Flutter — CI Workflow

I didn’t expect that this would be the first blog post in the series!

In order to get Flutter accepted and approved at my company, I’ve been asked to demonstrate the end process of testing and deploying a flutter application.

Feel free to come back to this blog post when you’re closer to shipping your shiny new Flutter application.

TL;DR; Code: codemagic.yaml Read From: Setting up the CI workflow

Focus and the amount of Friction are two key things I look at when thinking about design, workflows and changes to them.

There is a tendency to only care about deployment and environments when they don’t work, and to make do for as long as possible.

This can be very costly as they can easily become 80% of your development effort if you make it difficult, overly bespoke or include numerous manual steps.

You won’t regret the effort or cost to set up a good CI/CD workflow, using the best available tools, you can then get back to building great Flutter applications.

I started by reviewing the tools recommend by Flutter for continuous integration and delivery.

I choose GitLab, having had some experience of it before, for its powerful yaml configuration, large feature set and great integrations.

It’s an all in one DevOps platform delivered as a single application, you can move really fast with GitLab.

CodeMagic has great built in support for Flutter, is highly configurable and has a set of virtual Mac’s that allows you to build & sign applications for Apple devices and the App store.

It makes the whole process much simpler and integrates well with GitLab.

Git is great, Git is powerful, but it will let you create an indecipherable mess when working with a team on many projects and features.

If it’s just you, check into one branch, usually called master or main and deploy from it. Super simple, on you go.

With a team/s there are many features, projects, people and releases that need coordinated and controlled, you will require a branch structure and a process around it.

Lots of teams are successfully using Gitflow, but it takes a little time to get developers rowing in the same direction, requires lots of merges and makes the history tricky to understand.

I wanted something simple like the single branch that would work for teams and I’ve chosen the Streamline git workflow.

If it causing friction we can adjust and if it morphs back to Gitflow in the end so be it, we have made the leap in understanding.

So now we have the tool chain to build the workflows:

The continuous integration workflow will be triggered when developers check in to any feature branch with a ÏTag beginning “CI”.

Future posts will cover the continuous deployment workflow, automated versioning and integration and deployment for a website version.

Toolset Cost Justification

GitLab & CodeMagic

Gitlab is single application that covers the total development and operations cycle and can run advanced security tests on the software you write.

It integrates easily with most other frameworks and services allowing you to move fast and create a fully automated system in no time.

CodeMagic targets mobile integration and deployment and brings some powerful tools and features to the table:

  • API’s to communicate with Apple and Google, so you can sign and build apps automatically.
  • A farm of Macs to allow you to build for iOS and macOS from any device.
  • Strong integration with Google cloud to give you access to the Firestore services.
  • GitLab and CodeMagic integrate seamlessly together.

Whilst you could manually create servers and scripts to cover the tasks these services provide and hook them up in other CI/CD services like TFS or Jenkins, you would have to maintain them along with a number of virtual Mac agents and without support.

Even if you managed to find one person to cover this work at a modest salary of £20k per annum that would be a much greater cost.

Setting up the CI workflow

Ok enough talk lets go!

I started out by writing the list of actions I wanted the Integration workflow to carry out:

  • Check code quality.
  • Run Unit and Widget tests.
  • Sign and build an iOS version of the app.
  • Sign and build an Android version of the app.
  • Run Integration tests using Google’s Firebase TestLab.
  • Send an install on device link to testers when a build succeeds.

All of these tasks are setup in the codemagic.yaml file that you add to the root of your flutter process and configured with the Integration and Deployment tasks that you require.

The structure of the file is:

  • We will create the CI workflow under my-workflows.
  • Use the environment section to import secret values to use API’s to search and control external services including the App Store, Play Store and Firebase.
  • Add script tasks under scripts to build and sign the application for each platform required.
  • Configure artifacts to make the outputs available when the build completes.
  • Add recipients under email to send an email with app install links out to the testers

Setup — Service Access

In order to setup the workflow we will need access to Cloudmagic, the App Store, Play Store and Firebase services so we can use their API’s.

You will need to have or setup the service accounts before continuing, the apple developer account costs £79 per year, the google developer account is a $25 registration fee and Firebase and Cloudmagic have a free tier to get you started.

Follow the instructions in the section Service Access below, and gather the secrets:

appstore_credentials

APP_STORE_CONNECT_ISSUER_ID
APP_STORE_CONNECT_KEY_IDENTIFIER
APP_STORE_CONNECT_PRIVATE_KEY 
CERTIFICATE_PRIVATE_KEY
BUNDLE_ID

firebase_credentials

GCLOUD_KEY_FILE
FIREBASE_PROJECT

I stored the secret info and corresponding Environment Vars Names in secure notes in my Apple account Keychain, its up to you but I would recommend you keep them safe and secure.

Setup — Adding secrets as Environment Variables

Use the Codemagic UI to easily create the group and secure environment variables:

Then include the groups in the environment section of the codemagic.yaml workflow:

Checkout the documentation for more info on common Environment Variables:

We can now start adding the tasks tasks to our Codemagic integration workflow.

You can access the the workflow code anytime in the DigestableMe project on GitLab in the codemagic.yaml file.

Task — Check Code Quality

This task will run code analysis on the project and highlight code that will be difficult to maintain or puts the codebase at risk.

The task is added to the scripts section in codebase.yaml

The rules are add to the project pubspec.yaml file.

The output is save as a build artifact:

Task — Run local unit and widget tests

This task will pick up any unit or widget tests files under the /test directory of the project that end in _test.dart

Task script:

Artifact:

Task — Sign and build an iOS version of the application

Script Tasks:

Artifact:

Codemagics API to integrate with Apple really helps you out with the signing process.

It will work out what the app needs and create any certificates to complete the signing, amazing…

Task — Sign and build an Android version of the application

Script Tasks:

Artifact:

Task — TestLab

With the Google’s Firebase TestLab you can run your coded integration tests on multiple real devices and run a robo test that will discover and run through all the screens in your app, again on multiple devices.

Powerful stuff that will give you confidence that you application can run on devices that you wish to support.

The flip side is these valuable tests take time to run and that comes with a £ cost for using the service.

To setup integrations tests and get your project ready for Firebase TestLab run through the Flutter Integration Test Tutorial.

Once setup add the two scripts to the integration workflow:

See the sections under XP below for details on how to run TestLab locally.

Ta Da

Built and Regression Tested!

When everything passes and the testers are notified by email with links to install the version locally on their devices!

Service Access

App Store Connect Access

See the Codemagic instructions for more details.

NB: You may need to refresh the page after creation before the download link becomes visible.

Collect the secret values:

APP_STORE_CONNECT_ISSUER_ID
APP_STORE_CONNECT_KEY_IDENTIFIER
APP_STORE_CONNECT_PRIVATE_KEY 
CERTIFICATE_PRIVATE_KEY
BUNDLE_ID

The issuer id and key identifier are values you saved during the creation of the API key.

The ‘APP_STORE_CONNECT_PRIVATE_KEY’ is the key you download from the App Store Connect after creating the API key, the .p8 file. Just copy the contents directly into the environment variable value.

The ‘CERTIFICATE_PRIVATE_KEY’ is an RSA 2048 bit private key to be included in the signing certificate that Codemagic creates. You can use an existing key or create a new 2048 bit RSA key:

ssh-keygen -t rsa -b 2048 -m PEM -f ~/Desktop/codemagic_private_key -q -N ""

Copy the all the content from the private key file into the environment variable value.

BUNDLE_ID is the unique id for application and you define it when you create an identity in your Apple developer account.

You can find the iOS bundle id in your apple developer account under identifiers.

Apple recommend using a reverse-domain name style string i.e.

icom.domainname.appname

It cannot contain an asterisk.

Firebase Access for TestLab

You will need to set up the following in the Firebase console.

Collect the secret values:

GCLOUD_KEY_FILE
FIREBASE_PROJECT

Where:

GCLOUD_KEY_FILE — service account JSON key file, FIREBASE_PROJECT — your Firebase Project ID, you can find it under project-settings-general in the Firebase console.

Play Store Access & Signing

Google allows you to manage your signing credentials locally, but it’s better to let Google manage them in the cloud like the Apple App Store does.

For this workflow we will just create a default debug keystore directly in the codebase.yaml file, which will be fine for integration and ad-hoc testing.

When we need to deploy to the Play Store we will setup the keystore in the Google cloud, this will be covered in the continuous deployment post.

XP

Codemagic

I found most difficult thing at first was to understand the sections in codebase.yaml file.

In addition to the official documentation and google, a few of things really helped with this.

Firstly you can setup workflow using the UI and then switch to yaml configuration and export the values from the workflow you have setup.

You can use builder mode to give some contextual help.

When things go a little tougher like integrating with TestLab I eventually had to download the Firebase CLI and get the script running locally before going back to the workflow and plugging it in.

Firebase

I needed to install the API to list device models for TestLab and run tests without going through CodeMagic that was costing a lot of build minutes.

See Firebase CLI reference for more details. On the Mac you can install it with the this command.

curl -sL https://firebase.tools | bash

Then login with this command.

firebase login

Install gcloud

curl https://sdk.cloud.google.com | bash

Login

gcloud auth login

And list device models with this.

gcloud firebase test android models list

Note you can change the gcloud login account(email) with

gcloud config set account ACCOUNT

Firebase TestLab

On the free spark plan you have the following allowance

Once you have the firebase and gcloud CLI’s installed you can run TestLab tests directly and plug the commands back into the codemagic.yaml file.

To run the tests you will need to set the project id first:

gcloud config set project PROJECT_ID

You can find the project id by list all projects in your firebase console.

Do this by downloading the Android build artifacts and then modifying the codemagic.yaml command from

To

gcloud firebase test android run \
          --type instrumentation \
          --app app-debug.apk \
          --test app-debug-androidTest.apk \
          --timeout 3m

So that it points at the download build artifacts.

You can specify a device using — device, can be added multiple times for multiple devices.

--device model=redfin,orientation=portrait  \

Be careful to choose a device that supports your SDK, when devices have multiple then you need to specify one:

--device model=redfin,version=28  \

See gcloud firebase test android run command documentation for more command options.

Once you have the tests setup and passing make the changes back to codemagic.yaml and you are good to go.

BackBurner

Local Integration Tests

If you run up an emulator or attach a device then you can run all the integrations tests locally.

I would have liked to run local integration tests before the TestLab tests to catch breaking tests earlier and avoid running breaking tests on multiple devices, which is costly, time and money.

You can run the tests local using this command, but you need a device or emulator running.

flutter drive --driver=test_driver/integration_driver.dart --target=integration_test/app_test.dart

Web Integration

I ran out of time to add the following actions to my CI workflow.

  • Build a website version.
  • Run integration tests BrowserStack or other test tool.

Google Play Store — Automatic cloud managed signing

Implement automatic cloud managed signing as described in the Flutter documentation to sign an Android app.

For now I’ve just created a debug version of the keystore, directly in the codemagic.yaml file.

Integrate iOS app with Firebase Test Lab.

The official documentation requires a manual step to build the iOS runner for integration and upload to Firebase as a zipped file.

For now I’ve decided to integrate the Android package and come back to this.

Ideally I will be able to create a script to package the iOS application for Firebase TestLab.

One of the options I will consider when returning to this is integrate with FastLane and use the plugin to integrate with Firebase TestLabs

Fastlane plugin — Firebase TestLab

Sound & Vision

Links

One more thing…

Generally, the best way to learn git is probably to first only do very basic things and not even look at some of the things you can do until you are familiar and confident about the basics.

_Linus Torvalds

Other posts in the series

Development

DevOps:

Recommended from ReadMedium