Skip to main content

Mobile development with Harness

Harness CI supports mobile app development.

tip

If you don't have a Harness account yet, you can create one for free at app.harness.io.

Mobile app development guides

These guides contain a variety of information about mobile development with Harness CI, including installing dependencies, running tests, and distribution.

Plugins and scripts for mobile development

There are several ways to run scripts and use plugins in Harness CI. You can run Bitrise Steps, GitHub Actions, fastlane scripts, Firebase scripts, Xcode commands, and more.

Variables and secrets for mobile development

You can use Run steps to run all manner of commands or scripts. If your Run step defines or ingests a variable, make sure you understand how output variables and environment variables work in Run steps. You can also declare variables at the stage level and redefine their values in steps.

Store tokens, passwords, and other sensitive data as secrets and then use expressions to reference secrets in your pipelines. For example, you can use an expression as the value for a variable:

APP_STORE_PASSWORD=<+secrets.getValue("my_app_store_password_secret")>

App distribution with Harness CI

You can run distribution scripts for your preferred mobile development tool's CLI in a Run step.

For more information about the commands to use in your Run steps, refer to the provider's documentation. Here are some examples:

Mobile development YAML examples

Here are some examples of pipelines for mobile development. These pipelines are for example purposes only. They are meant to help you conceptualize how you can organize a Harness pipeline for mobile development.

This example builds an iOS app from an Xcode project and then uploads the artifact to JFrog Artifactory.

pipeline:
identifier: buildiOSApp
name: build-iOS-app
stages:
- stage:
identifier: Build_iOS_App
name: Build iOS App
type: CI
spec:
cloneCodebase: true
infrastructure: ## This examples uses a macOS VM build infrastructure.
type: VM
spec:
type: Pool
spec:
poolName: <+pipeline.variables.build_anka_image>
harnessImageConnectorRef: account.Jfrogartifactory
os: MacOS
execution:
steps:
- step:
identifier: Definevariables
name: Define variables
type: Run
spec:
shell: Sh
command: |-
## Insert script to populate variables required for the rest of the stage. Populated variables are declared in outputVariables so they are available to later steps. Variable values can change in later steps.
envVariables: ## These variables use Harness expressions for their values. Expressions beginning with stage.variables are references to stage variables.
PROVISIONING_PROFILE: <+stage.variables.xcode_provisioningProfile>
CERTPATH_PREFERENCE: <+stage.variables.certpath_preference>
PROFILES_PREFERENCE: <+stage.variables.profiles_preference>
EXPORTOPTIONS_PREFERENCE: <+exportoptions_preference>
SUPPRESS_COCOAPODS: <+stage.variables.suppress_cocoapods>
LOAD_CERTIFICATES: <+stage.variables.load_certificates>
outputVariables:
- name: XCODE_CERT_PATH
- name: XCODE_PROFILES_PATH
- name: XCODE_EXPORTOPTIONS_PATH
- name: XCODE_COCOAPOD_PATH
- name: XCODE_COCOAPOD_ENABLE
- name: XCODE_PROVISIONING_ID
- step:
identifier: Install_Certs_and_Provision_Profiles
name: Install Certs and Provision Profiles
type: Run
spec:
shell: Sh
command: |-
## Insert script to install certs and provision profiles.
envVariables: ## By declaring a variable in envVariables, the step can use that variable value in its command. For example, this step could use the LOAD_CERTIFICATES stage variable.
LOAD_CERTIFICATES: <+stage.variables.load_certificates>
- step:
identifier: Install_Cocoapods
name: Install Cocoapods
type: Run
spec:
shell: Sh
command: |-
## Insert script to install cocoapods.
when: ## This step only runs if all prior steps passed and the XCODE_COCOAPOD_ENABLE variable was set to true in the Definevariables step.
stageStatus: Success
condition: <+stage.spec.execution.steps.Definevariables.output.outputVariables.XCODE_COCOAPOD_ENABLE>
== "true"
- stepGroup: ## These steps are organized in a step group. This group of steps creates an .ipa file from an xcode project or workspace, depending on the value of the XCODE_TYPE variable.
identifier: Archive_and_Export_IPA
name: Archive and Export IPA
steps:
- parallel:
- step:
identifier: xcworkspace
name: xcworkspace
type: Run
spec:
shell: Sh
command: |-
## Insert script to build xcode archive and export the archive to .ipa. The following commands are shortened examples.

xcodebuild -list -workspace "<+stage.variables.xcode_xcworkspaceLocation>"

xcodebuild -workspace "<+stage.variables.xcode_xcworkspaceLocation>" -scheme ...

xcodebuild -exportArchive -archivePath "/tmp/harness/<+stage.variables.xcode_archivePath>" -exportPath . ...

envVariables:
schemeName: <+stage.variables.xcode_scheme>
XCODE_PROVISIONING_ID: <+stage.spec.execution.steps.Definevariables.output.outputVariables.XCODE_PROVISIONING_ID>
when: ## Run this step only if XCODE_TYPE is xcworkspace.
stageStatus: Success
condition: <+stage.variables.xcode_type> == "xcworkspace"
- step:
identifier: xcodeproj
name: xcodeproj
type: Run
spec:
shell: Sh
command: |-
## Insert script to build xcode archive and export the archive to .ipa. The following commands are shortened examples.

xcodebuild -list -workspace "<+stage.variables.xcode_xcworkspaceLocation>"

xcodebuild -workspace "<+stage.variables.xcode_xcworkspaceLocation>" -scheme ...

xcodebuild -exportArchive -archivePath "/tmp/harness/<+stage.variables.xcode_archivePath>" -exportPath . ...

envVariables:
schemeName: <+pipeline.stages.Build_iOS_app.variables.xcode_scheme>
password: <+secrets.getValue("my_password_secret")>
when:
stageStatus: Success
condition: <+stage.variables.xcode_type> == "xcproject"
- step:
identifier: Extract_Build_Settings
name: Extract Build Settings
type: Run
spec:
shell: Sh
command: |-
## Insert script to extract build settings to variable values. Populated variables are declared in the outputVariables so they can be referenced in later steps.
outputVariables:
- name: PRODUCT_BUNDLE_IDENTIFIER
- name: PRODUCT_NAME
- name: FULL_PRODUCT_NAME
- name: PRODUCT_SETTINGS_PATH
- name: TARGETED_DEVICE_FAMILY
- name: MARKETING_VERSION
- name: CURRENT_PROJECT_VERSION
- step:
identifier: Tag_Artifact
name: Tag Artifact
type: Run
spec:
shell: Sh
command: |-
## Insert script to tag final build artifact. For example, rename the exported .ipa.
- stepGroup: ## This step group uploads the final artifact to JFrog. The destination depends on the value of the jfrog_InstanceType variable.
identifier: Upload_Artifact
name: Upload Artifact
steps:
- parallel:
- step:
identifier: Upload_IPA_to_Artifactory
name: Upload to Cloud Artifactory
type: Run
spec:
shell: Sh
command: |-
## Insert commands to upload the artifact to JFrog artifactory. You could also use the built-in Upload Artifact to JFrog Artifactory step, instead of a Run step.
when: ## Run this step only if the jfrog_InstanceType is saas.
stageStatus: Success
condition: <+stage.variables.jfrog_InstanceType> ==
"saas"
- step:
identifier: Upload_IPA_to_onPrem_Artifactory
name: Upload to onPrem Artifactory
type: Run
spec:
shell: Sh
command: |-
## Insert commands to upload the artifact to JFrog artifactory. You could also use the built-in Upload Artifact to JFrog Artifactory step, instead of a Run step.
when: ## Run this step only if the jfrog_InstanceType is onprem.
stageStatus: Success
condition: <+stage.variables.jfrog_InstanceType> ==
"onprem"
when: ## Run this step group only if the jfrog_uploadArtifact variable is true.
stageStatus: Success
condition: <+stage.variables.jfrog_uploadArtifact> == "true"
failureStrategies: []
variables:
- name: xcode_scheme
type: String
description: ""
value: my_xcode_scheme
- name: xcode_provisioningProfile
type: String
description: ""
value: my_app.provisioning.profile
- name: jfrog_InstanceType
type: String
description: ""
value: saas
- name: xcode_xcworkspaceLocation
type: String
description: ""
value: my.xcworkspace
- name: xcode_archivePath
type: String
description: ""
value: my.xcarchive
- name: xcode_type
type: String
description: ""
value: xcworkspace
- name: jfrog_uploadArtifact
type: String
description: ""
value: "true"
- name: certpath_preference
type: String
description: ""
value: Profiles
- name: profiles_preference
type: String
description: ""
value: Profiles
- name: exportoptions_preference
type: String
description: ""
value: Profiles
- name: suppress_cocoapods
type: String
description: ""
value: "true"
- name: load_certificates
type: String
description: ""
value: "true"
delegateSelectors:
- macos-ci-delegate
delegateSelectors:
- macos-ci-delegate
variables:
- name: build_anka_image
type: String
description: ""
value: osx-pool
properties:
ci:
codebase:
connectorRef: YOUR_CODEBASE_CONNECTOR_ID
repoName: YOUR_CODEBASE_REPO_NAME
build:
type: tag
spec:
tag: 1.2.3456
tags: {}
projectIdentifier: default
orgIdentifier: default