How to trigger a task during IDEA sync?

I want to execute some task right after user opens my project in IDEA or press the “sync” button:
2024-04-17_16-10-11

It seems that there’s no reliable way to do it since there’s no tasks triggered by IDEA. I find it out this way:

// build.gradle
// I have nothing in this file except things below
tasks.create("asd") {
    doLast {
        println("ASD")
    }
    doFirst {
        println("ASD")
    }
}
tasks.all { Task task ->
    task.dependsOn(tasks.named("asd").get())
}

After I pressed the “sync” button I have no output except this:

BUILD SUCCESSFUL in 118ms

The best workaround I found - check system properties and modify Gradle start parameters to trigger my tasks if there’s a property added by IDEA:

class LocalPropertiesPlugin implements Plugin<Project> {
    @Override
    public void apply(@NotNull Project target) {
        Idea.scheduleTaskAfterIDEASync(target, "mytask");
    }

    private static void scheduleTaskAfterIDEASync(Project target, String taskName) {
        if (isIdeaSync()) modifyGradleStartParameters(target, taskName);
    }

    private static void modifyGradleStartParameters(Project target, String taskName) {
        final StartParameter startParameter = target.getGradle().getStartParameter();
        System.out.println(startParameter);
        final List<TaskExecutionRequest> taskRequests = new ArrayList<>(startParameter.getTaskRequests());
        taskRequests.add(new DefaultTaskExecutionRequest(List.of(taskName)));
        startParameter.setTaskRequests(taskRequests);
    }

    private static boolean isIdeaSync() {
        return Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"));
    }
}

This doesn’t look like good and reliable solution. How to do it in proper way?

You should have a look at GitHub - JetBrains/gradle-idea-ext-plugin: Plugin to store IJ settings in gradle script, with that you can for example configure an afterSync task that IntelliJ will trigger.

If you don’t mind depending on implementation details, you could also switch to Kotlin DSL build scripts, because when syncing with them, IntelliJ is indeed executing a task that you could make depend on your task, but as I said, that is depending on implementation detail of the Gradle plugin in IntelliJ and could of course change anytime.

Thank you :+1:. Just have tried it.

There’s one big caveat with this plugin - settings are persisting in .idea/workspace.xm even if you remove idea.project.settings block from build.gradle. This side effect makes build process unreliable because it’s no more driven by build script.

// build.gradle
plugins {
	id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.8"
}

tasks.register("testest") {
	doFirst {
		println("TEST doFirst")
	}
	doLast {
		println("TEST doLast")
	}
}

// If you remove this block and re-evaluate your project - the "testtest" task would still starting
idea.project.settings {
	taskTriggers {
		afterSync tasks.getByName("testest")
	}
}

You could have made the same setting manually through the IntelliJ UI, so it can hardly remove it as IntelliJ cannot really know whether the setting was done manually or through that plugin. But if you are desperate you can of course use the XML-manipulation triggers of that plugin to remove the afterSync task from the file.

but as I said, that is depending on implementation detail of the Gradle plugin in IntelliJ and could of course change anytime

Can I be sure that this might break only if I dediced to update Gradle to newest versions? I mean, can I depend on the kotlinDslAccessorsReport task (comes from org.gradle.kotlin.dsl.provider.plugins.KotlinScriptRootPlugin) and expect that it will work fine withing the same Gradle version?

:man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: