Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

How-to Github Actions: Build Matrix

 

 
Nicola Corti
Kotlin GDE | Android Infra @Spotify | ex @Yelp | Open-source Lover | Community craftsman
Published: November 27, 2020
Tweet
Share
 

Kubuswoningen — Rotterdam, The Netherlands

 

My favorite feature of Github Action is: build matrix.

A build matrix is a set of keys and values that allows you to spawn several jobs starting from a single job definition. The CI will use every key/value combination performing value substitution when running your job. This allows you to run a job to test different versions of a language, a library, or an operating system.

In this blog-post, you will discover how to create a build matrix for your workflow with two real-world examples.

 

This blog-post is part of a blogpost series: How-to Github Actions. 
You can find the other posts of this series here:
* Building your Android App (Introduction)
* Build Matrix — This blogpost

 

Setup a Build Matrix

You can define a build matrix when defining your job in your workflow file:

 

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}

 

In this example, the build matrix has one variable os and three possible values ( ubuntu-latest , macos-latest, and windows-latest). This will result in Github Actions running a total of three separate jobs, one for each value of the os variable.

With this configuration, you can run our workflow on all the operating systems supported by Github Actions workers.

If you wish to also test several versions of our language (e.g. Python), you can add another variable to our build matrix:

 

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python: [2.7, 3.6, 3.8]

 

In this case, Github Actions will run a job for every combination, resulting in a total of nine jobs executed. The value of the python variable will be available inside the workflow definition as ${{ matrix.python }}

By default, Github Actions will fail your workflow and will stop all the running jobs if any of the jobs in the matrix fails. This can be annoying as you probably want to see the outcome of all your jobs. The change this behavior you can use the fail-fast property:

 

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        ...

 

Let’s see a real-world example of a build matrix in action with Detekt.

Example: Detekt

If you don’t know detekt/detekt, is a static analyzer for Kotlin.

 

detekt/detekt

Meet detekt, a static code analysis tool for the Kotlin programming language. It operates on the abstract syntax tree…

github.com

 

Historically, the project used to run on a mixture of CIs: Travis CI for Linux/macOS builds and AppVeyor for Windows builds. Having two separate CI services was inconvenient as they have slightly different syntax for their build files. Moreover, it required more effort to maintain them in sync.

Early this year we decided to migrate to Github Actions. A build matrix allowed us to migrate to a single CI that would run all our jobs.

The resulting configuration looks like this (simplified for brevity):

 

 

 

 

In this workflow, we define a build matrix that allows us to test across every operating system and three different versions of java (Java 8, 11 & 14).

We use the value of the jdk variable in a couple of places:

  • An assignment to an environment variable JDK_VERSION.
  • Inside the actions/setup-java action to configure the Java version.

You can find the actual workflow file here.

This setup helps us ensure that detekt runs correctly on the majority of our users.

 

Shadow CI Jobs

A great use case for build matrix is the setup of shadow CI jobs đź‘».

A shadow job is a job that tests your project against an unreleased/unstable version of a dependency of your project. This helps you spot integration problems and regressions early on.

Generally, you want to treat a failure in a shadow job like a warning and don’t fail your whole workflow. This because you just want to get notified of a potential failure in the future, once a dependency becomes stable.

With such a setup, you could reach out to the library maintainer and notify them about unexpected problems or breaking changes.

To achieve this, you can use the include key together with continue-on-error:

 

jobs:
  build:
    strategy:
      matrix:
        python: [2.7, 3.6]
        experimental: [false]
        include:
          - python: 3.8
            experimental: true
  continue-on-error: ${{ matrix.experimental }}

 

With include, you can add an entry to the build matrix. In our example, the matrix would normally trigger two builds ( python:2.7, experimental:false and python:3.6, experimental:false). In this case include will add the python:3.8, experimental:true entry to the build matrix.

With continue-on-error, you can specify if a failure in the job should trigger a failure in the whole workflow.

Thanks to this setup, you can add shadow jobs to the matrix with the experimental key set to true. Those jobs will run without invalidating the whole workflow if they happen to fail due to an unstable dependency.

Let’s see a real-world example of a shadow CI jobs in action with AppIntro.

 

Example: AppIntro

AppIntro/AppIntro it’s a library to create intro carousels for Android Apps:

 

AppIntro/AppIntro

AppIntro is an Android Library that helps you build a cool carousel intro for your App. AppIntro has support for…

github.com

 
 

In AppIntro we use a build matrix to build a debug APK of our library against:

  • Unreleased versions of the Android Gradle Plugin (AGP)
  • EAP versions of Kotlin

Our workflow file looks like this:

 

 

 

 

As mentioned before, we use include and continue-on-error to add two experimental entries to our build matrix.

Here we also specify a name key to make our job easier to recognize:

 

name: Build Debug APK - ${{ matrix.name }} - Experimental ${{ matrix.experimental }}

 

The values of the build matrix keys are then passed as environment variables here:

 

env:
  VERSION_AGP: ${{ matrix.agp }}
  VERSION_KOTLIN: ${{ matrix.kotlin }}

 

Those environment variables are then accessed in the build.gradle file:

 

buildscript {
    ext.kotlin_version = "1.4.10"	
    
    ext {
        kotlin_version = System.getenv("VERSION_KOTLIN") ?: "1.4.10"
        agp_version = System.getenv("VERSION_AGP") ?: "4.1.0"
    }

    dependencies {
        classpath "com.android.tools.build:gradle:$agp_version"
        ...
    }
}

 

For the regular job, the ${{ matrix.agp }} key is empty (""). This causes the System.getenv("VERSION_AGP") to return null and the resulting version is the stable one (specified in the build.gradle).

For the shadow job instead, the ${{ matrix.agp }} key is 4.2.+. This causes the dependency string to be resolved to:

 

com.android.tools.build:gradle:4.2.+

 

Here we use Gradle dynamic versions, to specify a version range: 4.2.+. This allows us to test on the latest installment of AGP 4.2 without having to update the workflow file for every alpha/beta/RC release.

You can find the actual workflow file here.

A similar mechanism can be used to test your Android App against:

  • An upcoming versions of Gradle
  • A bump of targetSdkVersions
  • A snapshot of a library that is not released yet

and much more.

 

Conclusions

Github Actions’ build matrixes are a great tool to help you build & test your project against several versions of a language, a library, or an operating system.

Shadow jobs take build matrixes a step further, allowing you to test against unreleased versions of such languages or libraries.

Make sure you don’t miss the upcoming articles, you can find me as @cortinico on Twitter .

Other articles on this series are available here:

 

How-to Github Actions: Building your Android App

Setting up a Continuous Integration system for your Android App on Github has never been so easy with Github Actions

proandroiddev.com

 

Originally published at https://ncorti.com on November 2, 2020.
 

Some rights reserved

 

 

 

Tags: Android,Continuous Integration,Android App Development,AndroidDev,DevOps

 

View original article at: 


 

Originally published: November 02, 2020

Android News
Evolution of Android Update SystemEvolution of Android Update System
Evolution of Android Update SystemEvolution of Android Update System

By Ivan Kuten

So, how can you update Android on mobile devices? While developing software for Smart TVs and Android-based set-top boxes, we’ve narrowed it down to four ways, discarding some very exotic options:

By ProAndroidDev -
Android News
Happy Railway
Happy Railway

By Hadi Lashkari Ghouchani

This post is on the tail of Railway Oriented Programming in Kotlin by Antony Harfield. So you need to read it first and continue here. As it’s obvious I really liked it and tried it out. It needs every process have a result like

By ProAndroidDev -
Android News
Unit Tests and Concurrency
Unit Tests and Concurrency

By Stojan Anastasov

Once Retrofit added RxJava support, RxJava became my go-to concurrency framework for writing Android apps. One of the great things about RxJava is the excellent testing support. It includes TestObserver, TestScheduler, RxJavaPlugins so you can switch your schedulers in tests.

By ProAndroidDev -
Android News
When Compat libraries will not save you
When Compat libraries will not save you

By Danny Preussler

And why you should avoid using the “NewApi” suppression! The idea of “Compat” libraries was probably one of the key aspects of Android dominating the mobile space. Other than with iOS, Android users often could not update their operating system after a new version launch, simply as their phones won’t allow them to, the Android problem of fragmentation.

 

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One