GitLab CI/CD

GitLab CI/CD pipelines allow you to build and upload both Android and iOS apps to TestApp.io, notifying your testers for testing and feedback.

Configuration

Key Description Env Var(s) Default
api_token You can get it from https://portal.testapp.io/profile/tokens 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

Using Fastlane?TestApp.io Fastlane pluginSetup iOS Project for Fastlane

Add macOS runner

A macOS computer is required to build and package your iOS apps (IPA); however, GitLab does not provide such a runner. We will create the runner ourselves and register it to GitLab.

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

Install Xcode

Make sure that xcodebuild is 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 provisioning profile to build and export the IPA file in Xcode.

Make sure that you can archive and export an IPA file from Xcode manually before setting up the pipeline.

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

The runner is now registered. Go to your GitLab project under Settings > CI/CD > Runners to verify it appears.

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 the key field to TESTAPPIO_API_TOKEN (you can name it whatever you want — we will refer to it in the pipeline script). Put the API token in the value box. Uncheck Protect variable and check Mask variable. Then add the TESTAPPIO_APP_ID variable the same way.

Create the ExportOptions.plist file

A sample ExportOptions.plist file:

<?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>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>YOUR_TEAM_ID</string>
	<key>thinning</key>
	<string>&lt;thin-for-all-variants&gt;</string>
</dict>
</plist>

Replace YOUR_TEAM_ID with your Apple Developer Team ID. The easiest way to generate the ExportOptions.plist file is to export the IPA through Xcode. Once you've successfully exported your IPA, Xcode creates an ExportOptions.plist file that you can use for the CI pipeline.

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

tags
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 15,OS=17.5'
  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: 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 --ipa=$CI_PROJECT_DIR/build/$ProjectName.ipa --release_notes=$release_notes --notify=$notify --source="Gitlab"
  tags:
    - linux

Things to consider

  • Make sure to set the variable ProjectName with the name of your Xcode project. If you're using a different scheme than the default, make sure you pass in the proper SchemeName too (the default is the same as the ProjectName).
  • In the xcodebuild test command, the -destination option is set to launch an iPhone 15 image running iOS 17.5 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. Run xcodebuild --help in the Terminal to explore more build options.

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


Android

It's much easier for Android projects — no custom runner or codesign setup is required.

Create global variables TESTAPPIO_API_TOKEN and TESTAPPIO_APP_ID

Go to Settings > CI/CD > Variables > Add variable. Set the key field to TESTAPPIO_API_TOKEN (you can name it whatever you want — we will refer to it in the pipeline script). Put the API token in the value box. Uncheck Protect variable and check Mask variable. Then add the TESTAPPIO_APP_ID variable the same way.

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

image: eclipse-temurin:17-jdk

variables:
  ANDROID_COMPILE_SDK: "34"
  ANDROID_BUILD_TOOLS: "34.0.0"
  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"

Tip:TestApp.io mobile appshare links

Need help? Contact us — we're happy to assist!