# Using locally published components in Fenix

It's often important to test work-in-progress changes to Application Services components against a real-world consumer project. The most reliable method of performing such testing is to publish your components to a local Maven repository, and adjust the consuming project to install them from there.

With support from the upstream project, it's possible to do this in a single step using our auto-publishing workflow.

## rust.targets

Both the auto-publishing and manual workflows can be sped up significantly by using the rust.targets property which limits which architectures the Rust code gets build against. You can set this property by creating/editing the local.properties file in the repository root and adding a line like rust.targets=x86,linux-x86-64. The trick is knowing which targets to put in that comma separated list:

• Use x86 for running the app on most emulators (in rare cases, when you have a 64-bit emulator, you'll want x86_64)
• If you're running the android-components or fenix unit tests, then you'll need the architecture of your machine:
• OSX running Intel chips: darwin-x86-64
• OSX running M1 chips: darwin-aarch64
• Linux: linux-x86-64

## Using the auto-publishing workflow

Some consumers (notably Fenix) have support for automatically publishing and including a local development version of application-services in their build. The workflow is:

1. Check out the consuming project.

2. Edit (or create) the file local.properties in the consuming project and tell it where to find your local checkout of application-services, by adding a line like:

autoPublish.application-services.dir=relative/path/to/your/checkout/of/application-services

Note that the path should be relative from the root of the consumer's directory. For example, if application-services and fenix are at the same level, the relative path would be ../application-services

3. Build the consuming project following its usual build procedure, e.g. via ./gradlew assembleDebug or ./gradlew test.

If all goes well, this should automatically build your checkout of application-services, publish it to a local maven repository, and configure the consuming project to install it from there instead of from our published releases.

## Using a manual workflow

Note: This is a bit tedious, and you should first try the auto-publishing workflow described above. But if the auto-publishing workflow fails then it's important to know how to do the publishing process manually. Since most consuming apps get their copy of application-services via a dependency on android-components, this procedure involves three separate repos:

1. Inside the application-services repository root:

1. In .buildconfig-android.yml, change libraryVersion to end in -TESTING$N 1, where$N is some number that you haven't used for this before.

Example: libraryVersion: 0.27.0-TESTING3

2. Run ./gradlew publishToMavenLocal. This may take between 5 and 10 minutes.

2. Inside the android-components repository root:

1. In .buildconfig.yml, change componentsVersion to end in -TESTING$N 1, where$N is some number that you haven't used for this before.

Example: componentsVersion: 0.51.0-TESTING3

2. Inside buildSrc/src/main/java/Dependencies.kt, change mozilla_appservices to reference the libraryVersion you published in step 1 part 1.

Example: const val mozilla_appservices = "0.27.0-TESTING3"

3. Inside build.gradle, add mavenLocal() inside allprojects { repositories { <here> } }.

4. Inside the android-components local.properties file, ensure autoPublish.application-services.dir is NOT set.

3. Inside the consuming project repository root:

1. Inside build.gradle, add mavenLocal() inside allprojects { repositories { <here> } }.

2. Ensure that local.properties does not contain any configuration to related to auto-publishing the application-services repo.

3. Inside buildSrc/src/main/java/AndroidComponents.kt, change the version numbers for android-components to match the new versions you defined above.

Example: const val VERSION = "0.51.0-TESTING3"

You should now be able to build and run the consuming application (assuming you could do so before all this).

### Caveats

1. This assumes you have followed the build instructions for Fenix
2. Make sure you're fully up to date in all repos, unless you know you need to not be.
3. This omits the steps if changes needed because, e.g. application-services made a breaking change to an API used in android-components. These should be understandable to fix, you usually should be able to find a PR with the fixes somewhere in the android-component's list of pending PRs (or, failing that, a description of what to do in the application-services changelog).

## Adding support for the auto-publish workflow

If you had to use the manual workflow above and found it incredibly tedious, you might like to try adding support for the auto-publish workflow to the consuming project! The details will differ depending on the specifics of the project's build setup, but at a high level you will need to:

apply from: "${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle" } For a multi-project build it should be applied to all subprojects, like: subprojects { if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) { ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir" apply from: "${rootProject.projectDir}/${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle" } } 3. Confirm that the setup is working, by adding autoPublish.application-services.dir to your local.properties file and running ./gradlew dependencies for the project. You should be able to see gradle checking the build status of the various application-services dependencies as part of its setup phase. When the command completes, it should print the resolved versions of all dependencies, and you should see that application-services components have a version number in the format 0.0.1-SNAPSHOT-{TIMESTAMP}. [1]: It doesn't have to start with -TESTING, it only needs to have the format -someidentifier. -SNAPSHOT$N is also very common to use, however without the numeric suffix, this has specific meaning to gradle, so we avoid it. Additionally, while the \$N we have used in our running example has matched (e.g. all of the identifiers ended in -TESTING3, this is not required, so long as you match everything up correctly at the end. This can be tricky, so I always try to use the same number).