Monday, November 21, 2022
HomeWeb DevelopmentFlutter CI/CD utilizing GitHub Actions

Flutter CI/CD utilizing GitHub Actions


We’re in a state the place corporations are releasing software program and options inside minutes, and they’re doing so by following the Steady integration (CI) and steady supply (CD) set of working rules.

A CI/CD pipeline makes the automated supply of your software program extra frequent, dependable, and safe. It focuses on increased code high quality, and that’s why it’s critical for a cellular developer or group.

On this tutorial, you’ll learn to deploy your Flutter app following CI/CD rules with GitHub Actions as a instrument.

This tutorial requires a Google service account, which will probably be utilized in GitHub Actions to publish the Android construct to the Play Retailer, so to create a challenge in GCP, create a service account and choose your created challenge.

N.B., this tutorial assumes you could have some prior information of Flutter. In case you are new to Flutter, please undergo the official documentation to find out about it.

What’s GitHub Actions?

GitHub Actions is a CI/CD instrument that helps you construct, check, and deploy your modifications on manufacturing instantly out of your repository. You need to use it to arrange app releases on sure occasions like committing a tag in a sure department of your repository.

Moreover, one doesn’t should create a workflow for widespread issues throughout the tasks as GitHub has a market from which you should utilize current workflows developed by others.

The GitHub Actions workflow makes use of .yml (“YAML Ain’t Markup Language”) recordsdata, which will probably be saved within the .github listing on the root of your challenge.

Moreover, GitHub Actions helps completely different environments and containers like Linux, macOS, Home windows, and even VMS.

Getting began

Observe the beneath steps for preliminary setup:

  1. Arrange a brand new Flutter challenge utilizing your favorite IDE or utilizing the Flutter command-line instrument
  2. Initialize Git in your new challenge in your machine and create a brand new repository related together with your GitHub account
  3. Create the config listing within the root of your flutter challenge .github and a brand new listing known as workflows. The workflows right here will comprise all of your CI/CD workflows as .yml recordsdata

Use a fundamental Flutter motion to construct an Android launch

Now, you’ll create a fundamental Android workflow that will help you perceive how GitHub Actions works in constructing your Flutter app.

Create a .yml file, android-release.yml, inside workflows with the next code:

identify: Android Launch

# 1
on:
  # 2
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

  # 3
  workflow_dispatch:

# 4
jobs:
  # 5
  construct:
    # 6
    runs-on: ubuntu-latest

    # 7
    steps:
      # 8
      - makes use of: actions/[email protected]
      # 9
      - makes use of: actions/[email protected]
        with:
          distribution: 'zulu'
          java-version: "12.x"
      # 10   
      - makes use of: subosito/[email protected]
        with:
          # 11
          flutter-version: "3.0.0"
          channel: 'secure'
      # 12
      - identify: Get dependencies
        run: flutter pub get

      # Runs a set of instructions utilizing the runners shell
      - identify: Begin launch construct
        run: flutter construct appbundle

The above workflow:

  1. Controls when the workflow will run
  2. Triggers the workflow on push or pull request occasions for the "grasp" department; you may change it in accordance with your requirement
  3. Means that you can run this workflow manually from the Actions tab out of your GitHub repo (a workflow run is made up of a number of jobs that may run sequentially or in paralle)l
  4. Comprises a single job known as construct
  5. Comprises the kind of runner that the job will run on
  6. Makes use of steps to signify a sequence of duties that will probably be executed as a part of job
  7. Readies your repository beneath $GITHUB_WORKSPACE, so your job can entry it
  8. Units up Java so your job can use it for the Flutter app construct
  9. Units up Flutter utilizing the subosito Flutter workflow
  10. Adjusts to the Flutter model you might be working with
  11. Runs a single command utilizing the runner’s shell

Issues with this fundamental motion

The issue with this fundamental workflow is that everytime you push modifications within the grasp department, this workflow will set off and begin organising the Java SDK and Flutter SDK each time. So ultimately, it is going to result in the latency of constructing your software as you need to arrange companies each time.

How will you make your workflow sooner?

You may make your Flutter workflow sooner by caching the Java and Flutter SDKs in order that on the following run, it gained’t fetch the SDK instantly earlier than checking for the existence of the SDKs.

In your most important.yml file, make the next modifications:

      - makes use of: actions/[email protected]
        with:
          distribution: 'zulu'
          java-version: "12.x"
          cache: 'gradle' // 1
         
      - makes use of: subosito/[email protected]
        with:
          flutter-version: "3.0.0"
          channel: 'secure'
          cache: true // 2

You’ve up to date the SDK setup by offering Gradle to be cached with respect to the Java SDK (1) and enabling caching for the Flutter SDK (2).

Subsequent time you run the job publish, save the above modifications and observe the time spent; you will notice a time distinction from the essential movement.

Put together for the Play Retailer launch

Now you can be increasing your workflow to create an Android Play Retailer launch.

Generate a model quantity

For any new launch, it is best to have a brand new launch model quantity, so earlier than the construct, you must create a model quantity utilizing the beneath job:

# 1
model:
    identify: Create model quantity
    # The kind of runner that the job will run on
    runs-on: ubuntu-latest
    # Steps signify a sequence of duties that will probably be executed as a part of the job
    steps:
      - makes use of: actions/[email protected]
      # 2
      - identify: Set up GitVersion
        makes use of: gittools/actions/gitversion/[email protected]
        with:
          versionSpec: "5.x"
      - identify: Use GitVersion
        id: gitversion
        makes use of: gittools/actions/gitversion/[email protected]
      # 3
      - identify: Create model.txt with nuGetVersion
        run: echo ${{ steps.gitversion.outputs.nuGetVersion  }} > model.txt
      # 4
      - identify: Add model.txt
        makes use of: actions/[email protected]
        with:
          identify: gitversion
          path: model.txt

Within the above code, we did the next:

  1. Created a brand new job model that will probably be executed earlier than the construct job
  2. Put in the GitVersion, a instrument used for versioning by your Git historical past
  3. Posted utilizing GitVersion, putting the model in a model.textual content file
  4. Uploaded the model.textual content file as an artifact for the actions system with a reputation gitversion for use later within the construct job

Signal the app

To publish the app to Play Retailer, you must give your app a digital signature utilizing a keystore. Observe this official Flutter Doc on how to try this relying upon your machine:

keytool -genkey -v -keystore %userprofilepercentupload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias add

This can retailer a file with a .jks extension in your house listing or no matter path you offered.

N.B., be certain that so as to add the shop password, key password, and key alias in your GitHub repository secrets and techniques (from GitHub repository > Secrets and techniques > Actions)

Repository Secrets

Going through points whereas operating the keytool?

In case you are dealing with “’keytool’ just isn’t acknowledged as an inside or exterior command” challenge, then add the trail of the JDK bin to make use of surroundings variables, or else set up JDK and repeat the trail addition to surroundings variables.

Subsequent, create a brand new file key.properties beneath the Android listing of your app and supply the reference to your keystore generated earlier than:

storePassword=<password from earlier step>
keyPassword=<password from earlier step>
keyAlias=add
storeFile=<location of the important thing retailer file, corresponding to /Customers/<person identify>/your-keystore-file.jks>

To make use of this key when constructing your app in launch mode, replace your Android-level construct.gradle file as beneath:

  1. Outline the keyProperties variable to check with the key.properties file from the filesystem:
       def keystoreProperties = new Properties()
       def keystorePropertiesFile = rootProject.file('key.properties')
       if (keystorePropertiesFile.exists()) {
           keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
       }
  2. Replace the buildTypes and add the signingConfigs as beneath:
       signingConfigs {
           launch {
               keyAlias keystoreProperties['keyAlias']
               keyPassword keystoreProperties['keyPassword']
               storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
               storePassword keystoreProperties['storePassword']
           }
       }
       buildTypes {
           launch {
               signingConfig signingConfigs.launch
           }
       }

After this, your new construct will probably be created in launch mode utilizing the important thing.


Extra nice articles from LogRocket:


N.B., don’t commit the keystore key and the key.properties file and allow them to be non-public.

So that you is likely to be questioning, how can our job know whether or not this key exists within the filesystem and use it as a reference within the key.properties file?

To resolve this, do the next:

  1. Base64 encode your keystore file in your machine utilizing Git Bash or Bash:
    base64 <your-keystore-file.jks>
  2. Create a brand new secret ANDROID_KEYSTORE_BASE64 in your GitHub repository
  3. Copy the output and paste it as ANDROID_KEYSTORE_BASE64 in your GitHub repository; it’ll stay secure there

Now replace the construct job in your android-release.yml file:

construct:
    identify: Create Android Construct
    # 1
    wants: model
    runs-on: ubuntu-latest
    steps:
      - makes use of: actions/[email protected]
      # 2   
      - identify: Get model.txt
        makes use of: actions/[email protected]
        with:
          identify: gitversion
      # 3
      - identify: Create new file with out newline char from model.txt
        run: tr -d 'n' < model.txt > version1.txt
      # 4
      - identify: Learn model
        id: model
        makes use of: juliangruber/[email protected]
        with:
          path: version1.txt
      # 5
      - identify: Replace model in YAML
        run: sed -i 's/99.99.99+99/${{ steps.model.outputs.content material }}+${{ github.run_number }}/g' pubspec.yaml
      # 6
      - identify: Obtain Android keystore
        id: android_keystore
        makes use of: timheuer/[email protected]
        with:
          fileName: upload-keystore.jks
          encodedString: ${{ secrets and techniques.KEYSTORE_BASE64 }}
      # 7
      - identify: Create key.properties
        run: |
          echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties
          echo "storePassword=${{ secrets and techniques.STORE_PASSWORD }}" >> android/key.properties
          echo "keyPassword=${{ secrets and techniques.KEY_PASSWORD }}" >> android/key.properties
          echo "keyAlias=${{ secrets and techniques.KEY_ALIAS }}" >> android/key.properties
      - makes use of: actions/[email protected]
        with:
          distribution: 'zulu'
          java-version: "12.x"
          cache: gradle
      - makes use of: subosito/[email protected]
        with:
          flutter-version: "3.0.0"
          channel: 'secure'
          cache: true
     
      - identify: Get dependencies
        run: flutter pub get

      - identify: Begin Android Launch Construct
        run: flutter construct appbundle
      # 8
      - identify: Add Android Launch
        makes use of: actions/[email protected]
        with:
          identify: android-release
          path: construct/app/outputs/bundle/launch/app-release.aab

Within the above code, you carried out the next:

  1. Added dependency on the model job to run this one sequentially
  2. Downloaded the model file uploaded within the first job utilizing the identify gitversion
  3. Created a brand new file with out newline char from model.txt
  4. Learn the up to date model from version1.txt file
  5. Up to date the pubspec.yml file with the model ID having the model in it
  6. Decoded the base64 encoded keystore worth saved as a secret to ID android_keystore
  7. Created key.properties utilizing the secrets and techniques and android_keystore
  8. Uploaded the Android launch bundle as an artifact for use within the subsequent job

Deploy the app

Now, you must use the bundle and ship it to Play Retailer. Earlier than that, it’s time to make use of the service account that you simply created in the beginning of this tutorial. If the service account is created, copy the important thing for that account and retailer it in secrets and techniques as PLAYSTORE_ACCOUNT_KEY.

Subsequent, in your Google Play Console > Customers & Permissions, invite the person and add the service account person electronic mail right here.

In case you are not seeing your app in App permissions, ensure that the Google Play Developer API in GCP is enabled on your challenge.

Subsequent, replace the permission of the person in order that it has the entry to launch the app just like the admin function.

Now, add a brand new job deploy in your android-release movement:

deploy:
    identify: Deploy Android Construct
    # 1
    wants: construct
    runs-on: ubuntu-latest

    steps:
    - makes use of: actions/[email protected]
      # 2
    - identify: Get Android Construct from artifacts
      makes use of: actions/[email protected]
      with:
        identify: android-release
      # 3
    - identify: Launch Construct to inside observe
      makes use of: r0adkll/[email protected]
      with:
        serviceAccountJsonPlainText: ${{ secrets and techniques.PLAYSTORE_ACCOUNT_KEY }}
        packageName: <YOUR_PACKAGE_NAME>
        releaseFiles: app-release.aab
        observe: alpha
        standing: accomplished

Right here, you probably did the next:

  1. Added a dependency to run this job sequentially
  2. Downloaded the Android construct from artificats utilizing the identify android-release
  3. Used the [email protected] workflow with the PLAYSTORE_ACCOUNT_KEY secret, your app bundle identify, the observe during which you need to add the construct and its standing

After this, push your modifications to GitHub and see the workflow deploy your app to the Play Retailer.

Right here’s the whole workflow:

identify: Android Launch

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

  workflow_dispatch:

jobs:
  model:
    identify: Create model quantity
    runs-on: ubuntu-latest
    steps:
      - makes use of: actions/[email protected]
      - identify: Set up GitVersion
        makes use of: gittools/actions/gitversion/[email protected]
        with:
          versionSpec: "5.x"
      - identify: Use GitVersion
        id: gitversion
        makes use of: gittools/actions/gitversion/[email protected]
      - identify: Create model.txt with nuGetVersion
        run: echo ${{ steps.gitversion.outputs.nuGetVersion  }} > model.txt
      - identify: Add model.txt
        makes use of: actions/[email protected]
        with:
          identify: gitversion
          path: model.txt

  construct:
    identify: Create Android Construct
    wants: model
    runs-on: ubuntu-latest
    steps:
      - makes use of: actions/[email protected]
      - identify: Get model.txt
        makes use of: actions/[email protected]
        with:
          identify: gitversion
      - identify: Create new file with out newline char from model.txt
        run: tr -d 'n' < model.txt > version1.txt
      - identify: Learn model
        id: model
        makes use of: juliangruber/[email protected]
        with:
          path: version1.txt
      - identify: Replace model in YAML
        run: sed -i 's/99.99.99+99/${{ steps.model.outputs.content material }}+${{ github.run_number }}/g' pubspec.yaml
      - identify: Obtain Android keystore
        id: android_keystore
        makes use of: timheuer/[email protected]
        with:
          fileName: upload-keystore.jks
          encodedString: ${{ secrets and techniques.KEYSTORE_BASE64 }}
      - identify: Create key.properties
        run: |
          echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties
          echo "storePassword=${{ secrets and techniques.STORE_PASSWORD }}" >> android/key.properties
          echo "keyPassword=${{ secrets and techniques.KEY_PASSWORD }}" >> android/key.properties
          echo "keyAlias=${{ secrets and techniques.KEY_ALIAS }}" >> android/key.properties
      - makes use of: actions/[email protected]
        with:
          distribution: 'zulu'
          java-version: "12.x"
          cache: gradle
      - makes use of: subosito/[email protected]
        with:
          flutter-version: "3.0.0"
          channel: 'secure'
          cache: true
      
      - identify: Get dependencies
        run: flutter pub get

      - identify: Begin Android Launch Construct
        run: flutter construct appbundle

      - identify: Add Android Launch
        makes use of: actions/[email protected]
        with:
          identify: android-release
          path: construct/app/outputs/bundle/launch/app-release.aab

  deploy:
    identify: Deploy Android Construct
    wants: construct
    runs-on: ubuntu-latest
    steps:
    - makes use of: actions/[email protected]
    - identify: Get Android Construct from artifacts
      makes use of: actions/[email protected]
      with:
        identify: android-release
    - identify: Launch Construct to inside observe
      makes use of: r0adkll/[email protected]
      with:
        serviceAccountJsonPlainText: ${{ secrets and techniques.PLAYSTORE_ACCOUNT_KEY }}
        packageName: <YOUR_PACKAGE_NAME>
        releaseFiles: app-release.aab
        observe: alpha
        standing: accomplished

Be aware:

  • You possibly can mix all these jobs in a single and solely job so sharing recordsdata between jobs gained’t require artifacts publishing, which consumes a free utilization restrict
  • There’s a recognized challenge that generally the app just isn’t printed on the preliminary run. So, add an APKor appbundle constructed from this pipeline and roll it out for inside customers. After that, this workflow will be capable to launch apps with none points
  • In case you are nonetheless dealing with points throughout deployment, be certain that all config and permissions are appropriate, or test this points web page

Flutter internet launch to GitHub pages

Now create a brand new web-release.yml workflow and paste the next code:

identify: Net Launch

on:
  push:
    branches:  [ "master" ]

  pull_request:
    branches: [ "master" ]

  workflow_dispatch:

jobs:
  construct:
    identify: Create Net Construct
    runs-on: ubuntu-latest
    steps:
      - makes use of: actions/[email protected]
      - makes use of: actions/[email protected]
        with:
          distribution: 'zulu'
          java-version: "12.x"
          cache: gradle
      - makes use of: subosito/[email protected]
        with:
          flutter-version: "3.0.0"
          channel: 'secure'
          cache: true
      
      - identify: Get dependencies
        run: flutter pub get

      - identify: Begin Net Launch Construct
        run: flutter construct internet --release
     
      - identify: Add Net Construct Information
        makes use of: actions/[email protected]
        with:
          identify: web-release
          path: ./construct/internet

  deploy:
    identify: Deploy Net Construct
    wants: construct
    runs-on: ubuntu-latest

    steps:
    - identify: Obtain Net Launch
      makes use of: actions/[email protected]
      with:
        identify: web-release

    - identify: Deploy to gh-pages
      makes use of: peaceiris/[email protected]
      with:
        github_token: ${{ secrets and techniques.GITHUB_TOKEN }}
        publish_dir: ./

The above workflow is sort of just like the Android workflow, however right here you might be utilizing the Flutter internet construct command and later utilizing the peaceiris/[email protected] workflow to deploy the online construct to GitHub Pages.

Be aware:

  • The GITHUB_TOKEN just isn’t a private entry token. It will get mechanically created to authenticate in your workflow
  • Be sure the department within the GitHub Pages part in Settings is about to gh-pages

Conclusion

On this tutorial, you realized about find out how to arrange a GitHub Actions workflow to deploy your Flutter app throughout the Net and Android. For the following step, you may copy and modify the workflow to instantly launch the app to the app retailer or find out about different alternate options of GitHub Actions like CircleCI, GitLab CI, Jenkins, and extra.

We hope you loved this tutorial. Be happy to achieve out to us when you’ve got any queries. Thanks!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments