January 12, 2023
  • All
  • Announcements
  • Product
  • trapeze

Introducing Trapeze: Easy iOS and Android Project Configuration

Max Lynch

CEO

Trapeze

Today I’m excited to announce the public availability of Trapeze, our new open-source project that makes it easy to manage native and cross-platform mobile projects from a simple YAML-based configuration-file format.

Through this configuration file, Trapeze can work with the common file formats found in native iOS and Android projects, such as Gradle, XML, JSON, XCConfig, Strings, PBXProj, PList, Android Resources, and others. Trapeze supports traditional iOS and Android apps, and cross-platform frameworks like Ionic, Capacitor, React Native, and Flutter.

Trapeze was built to solve key challenges the mobile community faces when managing mobile projects at scale, especially in Mobile CI/CD workflows. Read on to learn more about Trapeze and where we’re taking it.

Solving Mobile Project Automation

As apps become more complex, teams need to manage their project configuration in safer, more automated ways. For example, keeping an auto-incrementing build number, or applying a set of project changes for a while-labeled app. These tasks are slow and error-prone to do by hand, and the current best alternative is to write custom configuration scripts that are hard to build and even harder to maintain.

With Trapeze, these tasks are as simple as defining the changes in a YAML file and running the Trapeze Configure tool. For example, the incrementBuild operation increments the build number each time the tool is run:

platforms:
  ios:
	incrementBuild: true
npx trapeze run config.yml

Trapeze comes with a large set of supported operations across iOS and Android, as well as some other useful operations that can work across projects.

Common Tasks

Some examples of tasks that Trapeze is well suited for:

Build Settings

Adjusting build settings and basic app configuration can be done in a central place:

vars:
  BUNDLE_ID:
	default: io.ionic.app
  PACKAGE_NAME:
	default: io.ionic.app

platforms:
  ios:
	targets:
  	App:
    	bundleId: $BUNDLE_ID
    	version: 16.4
    	buildNumber: 198
    	productName: Awesome App
    	displayName: My Awesome App

  android:
	packageName: $PACKAGE_NAME
	versionName: 5.2.1
	versionCode: 197

Build-specific Configuration Files

Apps often have to provide different configuration files and values when building for different environments (dev/qa/prod/etc). For example, swapping out values in a google-services.json file depending on the environment:

vars:
  GOOGLE_PROJECT_ID:
	default: "default_id"

platforms:
  android:
	json:
  	- file: google-services.json
    	set:
      	project_info:
        	project_id: $GOOGLE_PROJECT_ID
  ios:
	targets:
  	App:
    	json:
      	- file: google-services.json
        	set:
          	project_info:
            	project_id: $GOOGLE_PROJECT_ID

i18n and l10n

Swapping out translations and other localized values can be done by modifying the relevant platform-specific files (such as .strings on iOS and XML resource files on Android):

platforms:
  ios:
	targets:
  	App:
    	strings:
      	- file: App/Lang/fr.strings
        	set:
          	"App name": Name
  android:
	- resFile: values-fr/strings.xml
  	target: resources/string[@name="app_name"]
  	replace: |
    	<string name="app_name">Name</string>

This is just a taste of the use-cases for Trapeze!

Support for Environment Variables

Trapeze can work with Environment variables, including complex JSON-valued ones. When running interactively, Trapeze can prompt the user to provide values for all specified variables, if they aren’t already defined in the environment. For JSON values, Trapeze supports substituting in portions of the YAML configuration for complex variable substitution.

vars:
	KEYCHAIN_GROUPS:
  	default:
    	[
      	'$BUNDLE_ID',
    	]

platforms:
  ios:
	targets:
  	App:
    	entitlements:
      	- keychain-access-groups: $KEYCHAIN_GROUPS

CI/CD Ready

As more teams start to adopt a Mobile CI/CD workflow, such as those using our Appflow Mobile CI/CD service, we’ve seen a rise in questions around automating project configuration in these systems.

Trapeze was built with CI/CD in mind, and is a perfect fit for Appflow. For example, here is how developers would run a Trapeze configuration step in their build pipeline, before the app is packaged by Appflow:

  "scripts": {
	"appflow:build": "npx trapeze run appflow.yml -y && npm run build"
  },

For Plugin Authors

Another key audience we have in mind for Trapeze are plugin authors. Often, plugins require some manual project configuration in order to install. This can be difficult for users of these plugins and result in incorrectly configured apps and increased support burden.

To fix this, plugin authors can ship a Trapeze YAML file and then apply it after plugin install. Combined with interactive environment variable support, users of the plugin can be prompted to customize the values their project will be configured with.

Let’s look at two real plugin examples to see how this might be used.

The first one is the Capacitor Camera plugin. On iOS and Android some additional permission configuration needs to be set by the developer before the plugin can be used. We could supply a Trapeze configuration file to prompt the user for these values and modify the project for them automatically:

platforms:
  ios:
    targets:
      App:
        plist:
          - entries:
              - NSCameraUsageDescription: "Take photos"
              - NSPhotoLibraryAddUsageDescription: "Add  photos"
              - NSPhotoLibraryUsageDescription: "Access photos"
  android:
    manifest:
      - file: AndroidManifest.xml
        target: manifest/application
        inject:
          <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

On another one of Ionic’s plugins, a set of build options and Android manifest changes need to be applied after the plugin is installed.

platforms:
  ios:
	targets:
  	App:
    	buildSettings:
      	ENABLE_BITCODE: false
      	STRIP_SWIFT_SYMBOLS: false

    	plist:
      	replace: false
      	entries:
        	- CFBundleURLTypes:
            	- CFBundleURLSchemes:
                	- msauth.$(PRODUCT_BUNDLE_IDENTIFIER)
                	- msauth.$(PRODUCT_BUNDLE_IDENTIFIER)-intunemam
                	- msauth.com.microsoft.intunemam
  android:
	manifest:
  	- file: AndroidManifest.xml
    	target: manifest
    	inject: |
      	<queries>
        	<!-- ... -->
      	</queries>

Both of these file can be run by the user after installing the plugin or automatically using postinstall hooks.

What’s Next?

The goal for Trapeze is to support all of the file formats and project automation tasks that mobile developers need. Early growth is exciting and we are frequently adding new features based on feedback.

To give Trapeze a try, visit trapeze.dev and install the tool to start running project modification tasks. The project is 100% free and open source and we’d love your feedback on the GitHub repo.


Max Lynch

CEO