© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
C. Chandrasekara, P. HerathHands-on GitHub Actionshttps://doi.org/10.1007/978-1-4842-6464-5_10

10. A Few Tips and a Mobile Build Example

Chaminda Chandrasekara1   and Pushpa Herath2
(1)
Dedigamuwa, Sri Lanka
(2)
Hanguranketha, Sri Lanka
 

The previous chapters of this book discussed GitHub Actions’ features, syntax, and usage to help you start implementing pipelines.

This chapter provides more useful information and looks at examples that help you further implement GitHub Actions workflows to build and deploy applications.

Variable Usage Differences

The way that you refer variables may differ in your workflows. It depends on your runner type. In some actions such as run commands, default variables cannot be used directly, as the variables are not evaluated in the action as expected. Let’s look at such few cases and identify workable implementation options.

Default Variables with $variablename Syntax

Let’s look at the following example workflow, which has three jobs using Ubuntu (Linux), macOS, and Windows runners.
on: [push]
jobs:
  ubuntu_var_test_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariablesubuntu
        run: echo $GITHUB_RUN_ID
                  $GITHUB_RUN_NUMBER
  macos_var_test_job:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariablesmacos
        run: echo $GITHUB_RUN_ID
                  $GITHUB_RUN_NUMBER
  windows_var_test_job:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariableswindows
        run: echo $GITHUB_RUN_ID
                  $GITHUB_RUN_NUMBER

Here, we are trying to print the same two default variables, GITHUB_RUN_ID and GITHUB_RUN_NUMBER, in each runner in the workflow.

Figure 10-1 shows that the values successfully printed in Ubuntu.
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig1_HTML.jpg
Figure 10-1

Default variables in Ubuntu

macOS works similar to Ubuntu (see Figure 10-2).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig2_HTML.jpg
Figure 10-2

Default variables in macOS

In Windows, however, the variables are not printing with values. The difference is that the Windows execution uses a PowerShell Core, whereas Ubuntu and macOS use the Bash shell (see Figure 10-3).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig3_HTML.jpg
Figure 10-3

Default variables not printed in Windows

Let’s run the command in the Bash shell in Windows and specify the shell in the run step, as shown next.
windows_var_test_job:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariableswindows
        shell: bash
        run: echo $GITHUB_RUN_ID
                  $GITHUB_RUN_NUMBER
Once this update is done in Windows, the run command executes in a Bash shell. The default variables' values can be successfully printed by using variables with a $ (see Figure 10-4).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig4_HTML.jpg
Figure 10-4

Default variables printed in Windows using Bash

When you use Bash to run commands, the default variables can be used with $variablename syntax on all three operating systems

Using Variables in PowerShell Core in Action Steps

Let’s look at using PowerShell Core variables since the $variablename syntax does not work in all three operating systems (see Figures 10-5 and 10-6).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig5_HTML.jpg
Figure 10-5

PowerShell Core not printing default variables in Ubuntu

../images/502534_1_En_10_Chapter/502534_1_En_10_Fig6_HTML.jpg
Figure 10-6

PowerShell Core not printing default variables in macOS

An attempt to use ${varname} syntax does not work in any of the three operating systems with PowerShell Core (see Figure 10-7).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig7_HTML.jpg
Figure 10-7

${varname} is not working

The ${env:varname} syntax works with PowerShell Core for all three operating systems, as shown in the following workflow (also see Figure 10-8).
on: [push]
jobs:
  ubuntu_var_test_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariablesubuntu
        shell: pwsh
        run: echo ${env:GITHUB_RUN_ID}
                  ${env:GITHUB_RUN_NUMBER}
  macos_var_test_job:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariablesmacos
        shell: pwsh
        run: echo ${env:GITHUB_RUN_ID}
                  ${env:GITHUB_RUN_NUMBER}
  windows_var_test_job:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v1
      - name: printdefualtvariableswindows
        shell: pwsh
        run: echo ${env:GITHUB_RUN_ID}
                  ${env:GITHUB_RUN_NUMBER}
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig8_HTML.jpg
Figure 10-8

${env.varname} works for PowerShell Core

These examples show that different syntaxes are used based on the operating system or the shells used to run commands in GitHub Actions. The default shell for Windows is PowerShell Core. The default shell for macOS and Linux is Bash. You need to keep these differences in mind when implementing GitHub Actions workflows.

Workflow Job Status Check

You can implement a status check for the previous job steps by using if condition checks and performing actions based on the status.

if: ${{ success() }} returns true if all the previous steps are successful and the current step executes.

if: ${{ failure() }} returns true if a previous step failed. It may execute a step to roll back in a failure situation.

if: ${{ always() }} always returns true and may execute a cleanup step.

if: ${{ cancelled() }} returns true if the workflow job is canceled. It may execute a cleanup action if a job is canceled.

For example, check the steps in the following workflow.
on: [push]
jobs:
  statuscheck_demo_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: failurestep
        shell: pwsh
        run: write-host 'not failing now'
      - name: runifsuccess
        if: ${{ success() }}
        shell: pwsh
        run: write-host 'run on prev steps success'
      - name: runiferror
        if: ${{ failure() }}
        shell: pwsh
        run: write-host 'run because faild step'
      - name: runalways
        if: ${{ always() }}
        shell: pwsh
        run: write-host 'run always'
When you successfully execute the workflow, all the steps run except the run on failure step (see Figure 10-9).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig9_HTML.jpg
Figure 10-9

Run success

If you have a failed step, like the following, the run-on success step does not run. But the run-on failure steps always run (see Figure 10-10).
on: [push]
jobs:
  statuscheck_demo_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: failurestep
        shell: pwsh
        run: write-error 'failing now'
      - name: runifsuccess
        if: ${{ success() }}
        shell: pwsh
        run: write-host 'run on prev steps success'
      - name: runiferror
        if: ${{ failure() }}
        shell: pwsh
        run: write-host 'run because failed step'
      - name: runalways
        if: ${{ always() }}
        shell: pwsh
        run: write-host 'run always'
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig10_HTML.jpg
Figure 10-10

Run failure

This section identified how to use job status checks and execute steps based on the job’s status.

Android Build and Push to MS App Center for Distribution

Microsoft App Center supports you in distributing and testing mobile applications. This section looks at building a sample Android mobile application and deploying it to MS App Center with GitHub Actions. For a mobile application’s code, you can fork the repository at https://github.com/chamindac/MobileActionsDemo.

To build a mobile application, you can use the following job steps.
jobs:
  Android:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v1
    - name: Android
      run: |
        cd AwesomeApp
        nuget restore
        cd AwesomeApp.Android
        msbuild AwesomeApp.Android.csproj /verbosity:normal /t:PackageForAndroid /p:Configuration=Debug
    - uses: actions/upload-artifact@v2
      with:
        name: my-artifact
        path: "**/bin/Debug/com.companyname.AwesomeApp.apk"
A macOS runner was used to build and push the APK package to the artifacts in this job. Once the Android job has completed, the artifact is available in the workflow (see Figure 10-11).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig11_HTML.jpg
Figure 10-11

Artifact

You can use the job dependency and execute, in sequence, first the Android job and then the App Center job.

The next job is a dependent setup that needs syntax. When you specify the Android job’s needs, the App Center push job waits for the Android job to complete.
AppCenterDistibute:
    runs-on: ubuntu-latest
    needs: Android
The following are the steps to download the artifact (APK) from GitHub and upload it to the App Center for distribution.
 steps:
    - uses: actions/download-artifact@v2
      with:
        name: my-artifact
    - name: App Center
      uses: wzieba/AppCenter-Github-Action@v1.0.0
      with:
        # App name followed by username
        appName: Ch-DemoOrg/demoapp
        # Upload token - you can get one from appcenter.ms/settings
        token: ${{ secrets.AppCenterAPIToken }}
        # Distribution group
        group: alphatesters
        # Artefact to upload (.apk or .ipa)
        file: AwesomeApp/AwesomeApp.Android/bin/Debug/com.companyname.AwesomeApp.apk
        # Release notes visible on release page
        releaseNotes: "demo test"
The following is the full workflow code.
name: myandroidbuild
on: [push]
jobs:
  Android:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v1
    - name: Android
      run: |
        cd AwesomeApp
        nuget restore
        cd AwesomeApp.Android
        msbuild AwesomeApp.Android.csproj /verbosity:normal /t:PackageForAndroid /p:Configuration=Debug
    - uses: actions/upload-artifact@v2
      with:
        name: my-artifact
        path: "**/bin/Debug/com.companyname.AwesomeApp.apk"
  AppCenterDistibute:
    runs-on: ubuntu-latest
    needs: Android
    steps:
    - uses: actions/download-artifact@v2
      with:
        name: my-artifact
    - name: App Center
      uses: wzieba/AppCenter-Github-Action@v1.0.0
      with:
        # App name followed by username
        appName: Ch-DemoOrg/demoapp
        # Upload token - you can get one from appcenter.ms/settings
        token: ${{ secrets.AppCenterAPIToken }}
        # Distribution group
        group: alphatesters
        # Artefact to upload (.apk or .ipa)
        file: AwesomeApp/AwesomeApp.Android/bin/Debug/com.companyname.AwesomeApp.apk
        # Release notes visible on release page
        releaseNotes: "demo test"
Figure 10-12 shows the MS App Center uploading with the APK built via GitHub Actions (see Figure 10-12).
../images/502534_1_En_10_Chapter/502534_1_En_10_Fig12_HTML.jpg
Figure 10-12

APK uploaded to App Center

Summary

This chapter provided a few tips on using variables and job status, which can help you implement GitHub Actions workflows. It also looked at an Android mobile application build and deployment to the MS App Center.

This book discussed the features and syntax that you need to know to create GitHub Actions workflows for your application build and deployment pipeline implementation. It also discussed caching dependencies and using GitHub package management. And it covered using self-hosted runners with GitHub Actions workflows and creating custom actions to enhance your workflows. These topics should get you started using GitHub Actions workflows and implementing your pipeline on GitHub.