Skip to content

Latest commit

 

History

History

cicd

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

CI/CD for Mobile

CI/CD for mobile app development has always been challenging due to the different machine configurations, hardware limitation and requirement, and OS environment for building the packages. Typically, for iOS app to be deployed for testing, developers have to spend about half an hour to manually prepare the “archive” IPA and upload them into TestFlight for user testing, and there is no automated ways to test their app in various iPhone and iOS versions. Similar to Android, the setup for CI/CD and builds for different app packages is not consistent & it's a constant painful process to maintain due to the platform updates and new features. With an increasing emphasis on mobile, the pressure to routinely update mobile apps & push new features means there is a need to embrace CI/CD methodologies in mobile development.

For our mobile application to compile into native APK(Android) and IPA (IOS), we need to detach it from Expo. Alternatively, Expo also provide IPA/APK building services using their exp publish command, but we are not using that for our lab.

So our workflow is as follows:

  1. Detach application from Expo
  2. Build a Docker container image that allows us to build APK from the React Native code.
  3. Build out a CI/CD pipeline using AWS CodePipeline, AWS CodeCommit, AWS CodeBuild and testing on AWS Device Farm. AWS Device Farm let you run your newly compiled apk on real Android devices.

Note: We will not be building IPA for IOS in this lab.

Detach from expo

In your docker container, quite React-Native packager (CRTL-C), but still stay within the Docker environment, run this command to detach your application from Expo:

exp detach

You need to login to your Expo account to detach.

An Expo user account is required to proceed.

? How would you like to authenticate? 
  Make a new Expo account 
❯ Log in with an existing Expo account 
  Cancel 

Since we are on AWS Cloud9/docker, we will skip IOS process. To proceed with Android build, we need to provide an Android package name, for example com.apk.mycoolmobileapp. This process will update your app.json file in the current directory.

Success. You are now logged in as asean.
[07:20:36] Making sure project is set up correctly...
\[07:20:39] Warning: Not using the Expo fork of react-native. See https://docs.expo.io/.
[07:20:47] Your project looks good!
Validating project manifest...
You have not specified a custom scheme for deep linking. A default value of expa9173199816248ed91b705996074b191 will be used. You can change this later by following the instructions in this guide: https://docs.expo.io/versions/latest/workflow/linking
Skipping iOS because you are not running macOS.
You'll need to specify an Android package name. See: https://docs.expo.io/versions/latest/guides/configuration.html#package
? What would you like your Android package name to be? com.apk.mycoolmobileapp
Moving Android project files...
Downloading Android code...
Updating Android app...
{ buildPhase: 'running shell app modifications' } 'Warning: No config file specified.'
Cleaning up Android...
Android detach is complete!

Writing ExpoKit configuration...
Installing the Expo fork of react-native...
Installing react-native@https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz using yarn...

Finished detaching your project! Look in the `android` and `ios` directories for the respective native projects. Follow the ExpoKit guide at https://docs.expo.io/versions/latest/guides/expokit.html to get your project running.

This will detach your React Native project from Expo. You will see a new android subdirectory created for you.

Create shell-app-manifest.json

  1. Notice that app.json now has a new line item:
publishManifestPath": "android/app/src/main/assets/shell-app-manifest.json"

We need to create this file under android/app/src/main/assets directory.

# copy  kernel-manifest.json as  shell-app-manifest.json
cd android/app/src/main/assets
cp kernel-manifest.json shell-app-manifest.json

Push your mobile application code to AWS CodeCommit

Before we commit our code to AWS CodeCommit, let's ommit some directories from git push using .gitignore.

Add .gitignore to your ~/environment/rn directory:

# expo
.expo/

# dependencies
/node_modules

# misc
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

Your code directory should look like so now:

  ls -a
.  ..  android  App.js  app.json  App.test.js  aws-exports.js  buildspec.yml  .expo  .expo-source  .git  .gitignore  native-base-theme  node_modules  package.json  src  yarn.lock

Create AWS CodeCommit Repository

Let's create a new AWS CodeCommit Repository for our application. Run this in a AWS Cloud9 Terminal (not your docker environment):

aws codecommit create-repository --repository-name jiojiome-mobile-app

Output of the command:

{
    "repositoryMetadata": {
        "repositoryName": "jiojiome-mobile-app", 
        "cloneUrlSsh": "ssh://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/jiojiome-mobile-app", 
        "lastModifiedDate": 1534061690.066, 
        "repositoryId": "87b338a8-0726-45e3-9ba4-6a73e4f406f1", 
        "cloneUrlHttp": "https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/jiojiome-mobile-app", 
        "creationDate": 1534061690.066, 
        "Arn": "arn:aws:codecommit:ap-southeast-1:XXXXXXXXXXXX:jiojiome-mobile-app", 
        "accountId": "XXXXXXXXXXX"
    }
}

Create git credential for AWS CodeCommit

Setup AWS Cloud9 so that you can use ssh to git push to the repository.

create ssh in iam

  • IAM -> User -> Security credential -> SSH keys for AWS CodeCommit -> Upload SSH public key

In AWS Cloud9

  • ssh-keygen (this creates a new ssh keypair)
  • edit ssh/config
Host git-codecommit.*.amazonaws.com
 User XXXXXXXXXX(from IAM)
 IdentityFile ~/.ssh/id_rsa (key pair created just now)
  • chmod 600 ssh/config

Push our code to AWS CodeCommit

Execute these commands at the top level of your code directory (~/environment/rn): This initialize our code as a git repository and set the remote repository to the newly created CodeCommit Repository.

Run this in a AWS Cloud9 Terminal (not your docker environment) to push the code to AWS CodeCommit:

git init
git commit -m "first commit"
git remote add origin ssh://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/jiojiome-mobile-app
git push -u origin master

Verify that your code is uploaded to AWS CodeCommit using the CodeCommit console

AWS Codebuild

Let's add buildspec.yml to the top level directory of our application (~/environment/rn). A Build Spec is a collection of build commands and related settings, in YAML format, that AWS CodeBuild uses to run a build. You can include a build spec as part of the source code. This buildspec.yml basically says that we will run gradlew to compile our Android apk file. Once compiled, this apk can be sent to AWS Device Farm for device testing, or installed on your own Android device. If all the test passed, you can proceed to submit this apk to Google Play Store.

buildspec.yml

version: 0.1
phases:
  build:
    commands:
      - cd android && ./gradlew assembleRelease
artifacts:
  files:
    - android/app/build/outputs/apk/app-prod-release-unsigned.apk

Let's commit this new file to CodeCommit. Execute these commands at the top level of your code directory (~/environment/rn):

git add buildspec.yml
git commit -am "added buildspec.yml"
git push

Build our apk using java8

To build our apk, we need a build environment which can compile an APK using Java8. We'll create such an environment using Docker inside AWS Cloud9 (as java8-android-localbuilder) and upload this Docker Image to Amazon ECR. AWS CodeBuild will pull this image from ECR to build our APK.

build java8-android-localbuilder

Take this Dockerfile and build out the java8-android-localbuilder container image. Name the image as java8-android-localbuilder.

docker build -t java8-android-localbuilder .

Push java8-android-localbuilder to AWS ECR

Execute these commands at the top level of your code directory (~/environment/rn):

# Login to Amazon ECR
`aws ecr get-login --no-include-email`

#Create a new ECR Repository
aws  ecr create-repository --repository-name java8-android-builder

You'll see:


{
    "repository": {
        "registryId": "XXXXXXXXXXX", 
        "repositoryName": "java8-android-builder", 
        "repositoryArn": "arn:aws:ecr:ap-southeast-1:XXXXXXXXXXX:repository/java8-android-builder", 
        "createdAt": 1534061289.0, 
        "repositoryUri": "XXXXXXXXXXX.dkr.ecr.ap-southeast-1.amazonaws.com/java8-android-builder"
    }
}

Replace XXXXXXXXXXX with your own 12-digit AWS Account Number.

docker tag java8-android-localbuilder XXXXXXXXXXX.dkr.ecr.ap-southeast-1.amazonaws.com/java8-android-builder
docker push XXXXXXXXXXX.dkr.ecr.ap-southeast-1.amazonaws.com/java8-android-builder

Assign Codebuild the permission to pull this image from ECR

AWS Codebuild Service need the permission to pull this specific image from Amaozn ECR. This is a bonus lab!

CodeBuild->java8-android-builder->Permissions-> ecr

Create a CICD Pipeline with AWS CodePipeline

  1. Goto AWS CodePipeline Console
  2. Click "Create pipeline"
  3. Name the new pipeline "my mobile pipeline" and click "Next Step"
  4. Select Source Provider as AWS CodeCommit, Select the CodeCommit Repository and set the Branch name to master. Click "Next Step"
  5. Select "AWS Codebuild" as the Build provider, click on "Create a new build project"
  6. Enter Project Name as "Mobile Codebuild for apk"
  7. Select "Specify a Docker image", Environment Type = Linux, Custom image type = ECR, ECR Repository = java8-android-builder , image = latest. 8 Set build specification as Use the buildspec.yml in the source code root directory 9 Under Advanced section, select Compute type as 15GB memory, 8vCPU and click "Save build project".
  8. Select "No Deployment" and click "Next Step"
  9. In AWS Service Role page, click "Create role and then "Next Step
  10. Click "Create pipeline"

Trigger the build!

You can now trigger a pipeline build by commit to the source code. eg: change a line of code and git commit to AWS CodeCommit.

How about Device Farm?

You can now integrate Device Farm as a test target inside AWS CodePipeline. Reference Blog post here