Add Respresso sync to your Gradle build

Before adding a Respresso sync task to your Gradle build, you should configure the sync.

Once you installed the Respresso CLI to your machine and created a proper respresso.json configuration file, you can easily execute a sync from your Gradle.

You just need to create a new Exec task in your app/module level build.gradle :

task respressoSync(type: Exec) {
  commandLine 'respresso', 'sync' // You can pass other options, like `--log-level debug`
}

This will add a task named respressoSync that can be executed separately, or you can run it before each preBuild using the following line:

preBuild.dependsOn respressoSync

Please note that if you add the sync as the dependency of the build, it will fail on machines where the Respresso CLI is not available.

Let's put those together:

task respressoSync(type: Exec) {
  commandLine 'respresso', 'sync'
}
preBuild.dependsOn respressoSync

You can read more about the Exec task options in the Gradle docs.

Modular project structure with multi project sync [Advanced]

The above example works fine for monolithic projects or where all the resources are synced to a single module. (If each module has a separate respresso.json config it also works.)

If you want a single respresso.json config that contains all the Respresso projects of your modules, you will need to use a bit more complex Gradle setup.

If you setup all modules to use the same config and lock file and execute the sync in parallel, it will cause problems. Fortunately, there are multiple ways you can handle this problem.

For the workarounds bellow, we will use a similar config:

respresso.json
{
  "projects": [
    {
      "name": "module1"
      "token": "..."
      "target": "./module1/src/main",
      "resources": [
        // ... Module 1 resources
      ]
    },
    {
      "name": "module2"
      "token": "..."
      "target": "./module2/src/main",
      "resources": [
        // ... Module 2 resources
      ]
    }
  ]
}

Solution 1 - Force serialized execution of module sync tasks

In this workaround we will configure Gradle to serialize the Respresso sync tasks. This means that it will only execute the necessary module sync tasks but never in parallel.

A simple setup would look like this:

build.gradle
task respressoSync(type: Exec) {
    commandLine 'respresso', 'sync'
}

def lastConfiguredSyncTask = null;

allprojects {
    afterEvaluate { project ->
        def syncTask = project.tasks.find { it.name == "respressoSync" }
        if(syncTask != null && project !== rootProject) {
            if(lastConfiguredSyncTask != null) {
                println "Serializing sync: $syncTask must run after $lastConfiguredSyncTask"
                syncTask.mustRunAfter lastConfiguredSyncTask
            }
            lastConfiguredSyncTask = syncTask
        }
    }
}
module1/build.gradle
task respressoSync(type: Exec) {
  workingDir '../'
  commandLine 'respresso', 'sync', '--only-project', 'module1'
}
preBuild.dependsOn respressoSync // Add this line only if you want auto sync before each build
module2/build.gradle
task respressoSync(type: Exec) {
  workingDir '../'
  commandLine 'respresso', 'sync', '--only-project', 'module2'
}
preBuild.dependsOn respressoSync // Add this line only if you want auto sync before each build

You can sync a module's resources separately using the gradle :module1:respressoSync command (gradlew :module1:respressoSync on Windows).

Similarly, you can sync all the modules using the gradle respressoSync command (gradlew respressoSync on Windows).

Solution 2 - Sync all modules at once, each time

In this workaround we will configure Gradle to sync all modules at once if any of the modules are built. This means that it will execute the full sync each time you run a build.

A simple setup would look like this:

build.gradle
task respressoSync(type: Exec) {
    commandLine 'respresso', 'sync'
}

allprojects {
    afterEvaluate { project ->
        if(project != rootProject && project.tasks.any { it.name == "respressoSync"}) {
            project.tasks.find { it.name == "preBuild" }?.dependsOn rootProject.tasks.respressoSync
        }
    }
}
module1/build.gradle
task respressoSync(type: Exec) {
  workingDir '../'
  commandLine 'respresso', 'sync', '--only-project', 'module1'
}
// Do NOT add the respressoSync task as a dependency to the build task!
module2/build.gradle
task respressoSync(type: Exec) {
  workingDir '../'
  commandLine 'respresso', 'sync', '--only-project', 'module2'
}
// Do NOT add the respressoSync task as a dependency to the build task!

You can sync a module's resources separately using the gradle :module1:respressoSync command (gradlew :module1:respressoSync on Windows).

Similarly, you can sync all the modules using the gradle respressoSync command (gradlew respressoSync on Windows).

Legacy Gradle plugin for Android

The previous version of the Respresso sync client was packed in a Gradle plugin, so you cloud add it to your build.gradle.

We decided to go to a cross-platform direction instead of making multiple sync clients for each platform and implementing the same features multiple times. This is the reason we are deprecating the Gradle plugin. This also means, we can unify the sync experience of all platforms. Thanks to this, you won't need to learn and install multiple tools for different platforms.

We won't support the legacy plugin, but you can still use it. You will find its usage instructions and documentation on GitHub. New features won't be implemented, e.g. named versions will fail to sync using this legacy Gradle plugin.