Gitlab CI/CD

💡
BETA mode. Your feedback is highly appreciated!

Gitlab pipeline allows you to build and upload both Android & iOS apps to TestApp.io to notify your testers for testing and feedback.

Configuration

Key Description Env Var(s) Default
api_token You can get it from https://portal.testapp.io/settings/api-credentials TESTAPPIO_API_TOKEN
app_id You can get it from your app page at https://portal.testapp.io/apps TESTAPPIO_APP_ID
release It can be either both or Android or iOS TESTAPPIO_RELEASE
apk Path to the Android APK file TESTAPPIO_ANDROID_PATH
ipa Path to the iOS IPA file TESTAPPIO_IOS_PATH
release_notes Manually add the release notes to be displayed for the testers TESTAPPIO_RELEASE_NOTES
git_release_notes Collect release notes from the latest git commit message to be displayed for the testers: true or false TESTAPPIO_GIT_RELEASE_NOTES true
git_commit_id Include the last commit ID in the release notes (works with both release notes options): true or false TESTAPPIO_GIT_COMMIT_ID false
notify Send notifications to your team members about this release: true or false TESTAPPIO_NOTIFY false

Check TA-CLI for more info


iOS

Add macOS runner

A macOS computer is required to build and package your iOS apps (IPA); however, Gitlab does not provide such a runner for making your iOS apps. So we will create the runner ourselves and register to Gitlab as a runner.

More info: https://docs.gitlab.com/runner/install/osx.html

Install Xcode

Make sure that xcodebuild was using xcode rather than the command line tools

sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

Verify

xcode-select -p

Import the codesign certificate and provision profile to build & export the IPA file in Xcode.

Import the certificates for codesign and provision profile, make sure that you can archive & export IPA file Xcode manually.

Install Gitlab runner

macOS amd64

sudo curl --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64"

macOS Apple Silicon/arm64

sudo curl --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-arm64"

Make it executable

sudo chmod +x /usr/local/bin/gitlab-runner

Install as service

gitlab-runner install
gitlab-runner start

Check the status

gitlab-runner status

gitlab-runner: Service is running

And finally, register the runner

gitlab-runner register

Now the runner is registered. Let's go to the Gitlab project settings runner section to see if it succeeded.

Verify Gitlab Runner is working

Now the runner is ready, let's build and package our iOS apps with this runner.

Create global variables TESTAPPIO_API_TOKEN and TESTAPPIO_APP_ID

Go to Settings > CI/CD > Variables > Add variable. Set key field to TESTAPPIO_API_TOKEN; you could name it whatever you want, we will refer to it in the pipeline script. And put the API token in the value box. Uncheck Protect variable and check the Mask variable. And continue to add TESTAPPIO_APP_ID variable.

create the ExportOptions.plist file

A sample ExportOptions.plist file could look like the below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>compileBitcode</key>
	<true/>
	<key>destination</key>
	<string>export</string>
	<key>method</key>
	<string>development</string>
	<key>signingStyle</key>
	<string>automatic</string>
	<key>stripSwiftSymbols</key>
	<true/>
	<key>teamID</key>
	<string>WSNDX2Q2K9</string>
	<key>thinning</key>
	<string>&lt;thin-for-all-variants&gt;</string>
</dict>
</plist>

The easiest way to generate the ExportOptions.plist file is to export the IPA file through Xcode; once you have successfully exported your IPA file, it creates an ExportOptions.plist file for you. You can use that file for the CI pipeline.

Add the following script block to your pipeline script (.gitlab-ci.yml)

💡
Please pay attention to the tags field, and this is the one for our runner just created above. You need to change to tags you used while registering the runner.
stages:
  - build
  - archive
  - upload
variables:
  release: "ios"
  release_notes: "My release notes here..."
  notify: false
  ProjectName: "myproject"
  SchemeName: "myschema"
  

build-job:
  stage: build
  script:
    - xcodebuild clean -project $ProjectName.xcodeproj -scheme $SchemeName
    - xcodebuild test -project $ProjectName.xcodeproj -scheme $SchemeName -destination 'platform=iOS Simulator,name=iPhone 13,OS=15.2'
  tags:
    - ipa-macos

archive-job:
  stage: archive
  script:
    - xcodebuild clean archive -archivePath build/$ProjectName -scheme $SchemeName
    - xcodebuild -exportArchive -archivePath "build/$ProjectName.xcarchive" -exportPath "build/$ProjectName.ipa" -exportOptionsPlist "ExportOptions.plist"
  artifacts:
    paths:
      - build/$ProjectName.ipa
  tags:
    - ipa-macos

upload-job:
  stage: deploy
  before_script:
    - export INSTALL_DIR=$CI_PROJECT_DIR
    - curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
  script:
    - $CI_PROJECT_DIR/ta-cli publish --api_token=$TESTAPPIO_API_TOKEN --app_id=$TESTAPPIO_APP_ID --release=$release --ipa=$CI_PROJECT_DIR/build/$ProjectName.ipa --release_notes=$release_notes --notify=$notify --source="Gitlab"
  tags:
    - linux

Things to consider

  • Make sure to set variableProjectName with the name of your Xcode project; if you're using a different scheme than the default, then make sure you pass in the proper SchemeName too (the default is the same as the ProjectName).
  • In the xcodebuild test command, notice the -destination the option is set to launch an iPhone 13 image running iOS 15.2 in the Simulator; if you want to run a different device (iPad, for example), you'll need to change this.
  • If you're using a workspace rather than a project (e.g., because your app uses Cocoapods), change the -project ProjectName.xcodeproj options to -workspace WorkspaceName.xcworkspace. Several options are available to customize your build; run xcodebuild --help in the Terminal to explore these further.

Here is the sample project we used for demonstrating the process.


Android

It's much easier for Android projects; no customized runner or codesigns are required.

Create global variables TESTAPPIO_API_TOKEN and TESTAPPIO_APP_ID

Go to Settings > CI/CD > Variables > Add variable. Set key field to TESTAPPIO_API_TOKEN; you could name it whatever you want. We will refer to it in the pipeline script. And put the API token in the value box. Uncheck Protect variable and check the Mask variable. And continue to add TESTAPPIO_APP_ID variable.

Add the following code snippet to your pipeline script (.gitlab-ci.yml)

image: openjdk:11.0-jdk

variables:
  ANDROID_COMPILE_SDK: "28"
  ANDROID_BUILD_TOOLS: "28.0.2"
  release: "android"
  release_notes: "My release notes here..."
  notify: false

# install the android sdk
before_script:
  - apt-get --quiet update --yes
  - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
  - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip
  - unzip -d android-sdk-linux android-sdk.zip
  - mv android-sdk-linux/cmdline-tools android-sdk-linux/latest
  - mkdir -p android-sdk-linux/cmdline-tools
  - mv android-sdk-linux/latest android-sdk-linux/cmdline-tools/
  - echo y | android-sdk-linux/cmdline-tools/latest/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
  - echo y | android-sdk-linux/cmdline-tools/latest/bin/sdkmanager "platform-tools" >/dev/null
  - echo y | android-sdk-linux/cmdline-tools/latest/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
  - export ANDROID_HOME=$PWD/android-sdk-linux
  - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
  - chmod +x ./gradlew
  # temporarily disable checking for EPIPE error and use yes to accept all licenses
  - set +o pipefail
  - yes | android-sdk-linux/cmdline-tools/latest/bin/sdkmanager --licenses
  - set -o pipefail

stages:
  - build
  - upload
assembleDebug:
  stage: build
  script:
    - ./gradlew assembleDebug
  artifacts:
    paths:
      - app/build/outputs/

upload-job:
  stage: upload
  before_script:
    - export INSTALL_DIR=$CI_PROJECT_DIR
    - curl -Ls https://github.com/testappio/cli/releases/latest/download/install | bash
  script:
    - $CI_PROJECT_DIR/ta-cli publish --api_token=$TESTAPPIO_API_TOKEN --app_id=$TESTAPPIO_APP_ID --release=$release  --apk=$CI_PROJECT_DIR/app/build/outputs/apk/debug/app-debug.apk --release_notes=$release_notes --notify=$notify --source="Gitlab"


Feedback & Support

Developers built TestApp.io to solve the pain of app distribution for mobile app development teams.

Join our community for feedback and support.

Happy releasing 🎉