https://gradle.com/ logo
Join Slack
Powered by
# plugin-development
  • a

    Alex Beggs

    05/08/2025, 8:56 PM
    I am working with a project that has composite builds. I wanted to write my code with regard to the best practices for Isolated Projects. I know this is still in transition and development, but I was wondering if someone had a suggestion. I have Project
    base
    • IncludeBuild
    second
    ◦ project
    a
    ◦ project
    b
    :second:a
    has a task for executing
    verifyPaparazzi
    however I can't call it on Project
    base
    verifyPaparazzi
    and subsequently execute Ba's
    verifyPaparrazi
    it complains that base doesn't have the task. I can call
    :second:a:verifyPaparrazi
    directly. Which means I can setup a task that is dependent on that task in the
    base
    project as suggested here My question is, how can I do this dynamically without violating the isolated project best practices. second/settings.gradle.kts
    Copy code
    gradle.lifecycle.afterProject {
        if (this.name == "second") {
            return@afterProject
        }
    
        if (this.rootProject.tasks.findByName("verifyPaparazzi") == null) {
            this.rootProject.tasks.register("verifyPaparazzi")
        }
        val task = this.rootProject.tasks.findByName("verifyPaparazzi")
        this.tasks.findByName("verifyPaparazzi")?.let {
            task!!.dependsOn(it)
        }
    
    }
    This then puts a
    verifyPaparazzi
    call at the
    :second:verifyPaparrazi
    level instead of
    :second:a:verifyPaparrazi
    and additional projects that might have it. Collectively putting them into one call at the root of the included build
    second
    The next step would be to add a task in the
    base
    project
    Copy code
    tasks.register("verifyPaparazzi") {
        dependsOn(gradle.includedBuild("second").task(":verifyPaparazzi"))
    }
    am I thinking about this all wrong, or is there currently no way to add task dependencies dynamically without violating the Isolated Projects?
    v
    e
    • 3
    • 26
  • f

    Francisco Prieto

    05/09/2025, 2:53 PM
    Hey everyone! I’m working on a Gradle plugin that registers some tasks using
    project.tasks.register
    , and it does it inside the
    onVariants
    lambda provided by AGP. One of these tasks has to search for another task by name, access its outputs, and map them as an input. Something like this:
    Copy code
    val targetTaskProvider = project.tasks.named("targetTask") // some task created by another plugin
    
    val myTask = project.tasks.register(...) { task ->
        task.input.set(targetTaskProvider.flatMap { // do some processing on task outputs }
    }
    When using
    project.tasks.named
    , if the task I’m looking for has not been registered yet, it will fail to find it. I found that wrapping everything in
    project.afterEvaluate
    will ensure that the task is already there, but it doesn’t seem optimal. Is there any other alternative?
    v
    m
    • 3
    • 36
  • y

    yjxf vf

    05/10/2025, 1:13 PM
    I want to use artifact transform to transform a dependency's classes and its sources ,but gradle only pass the classes jar to my transformation, so how can i ask gradle to give the sources jar
    project.getDependencies().registerTransform(
    AccessTransform.class,
    parameters -> {
    parameters.parameters(p -> {
    p.getAccessTransformerFiles().from(extension.getAccessTransformerFiles());
    });
    parameters.getFrom().attribute(
    ModAccessTransformExtension.TRANSFORM_ACCESS,
    false
    ).attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE);
    parameters.getTo().attribute(
    ModAccessTransformExtension.TRANSFORM_ACCESS,
    true
    ).attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE);
    }
    );
    m
    v
    j
    • 4
    • 28
  • j

    Jonathing

    05/13/2025, 7:10 PM
    Hello! I'm having difficulties with the Groovy DSL, specifically that I am unable to use the implicit
    it
    on actions. The script will compile and the
    doCall
    is intercepted to try and set the property of the current dynamic object. And this is not including types that are `DslObject`s or
    DynamicObjectAware
    . Both method calls and the short-hand for getters and setters don't work. Basically, this works:
    Copy code
    accessTransformers.register {
        it.config = project.file('accesstransformer.cfg')
    }
    and this doesn't:
    Copy code
    accessTransformers.register {
        config = project.file('accesstransformer.cfg')
    }
    why is that? and is there anything I can realistically do about this without needing to use something like a domain object container? For reference, this is the method they are calling in this example
    Copy code
    default AccessTransformersContainer register(Action<? super AccessTransformersContainer.Options> options) {
        return this.register(AccessTransformersExtension.DEFAULT_ATTRIBUTE, options);
    }
    and this is the exception being thrown:
    Copy code
    Caused by: groovy.lang.MissingPropertyException: Could not set unknown property 'config' for project ':at-gradle-demo' of type org.gradle.api.Project.
    	at org.gradle.internal.metaobject.AbstractDynamicObject.setMissingProperty(AbstractDynamicObject.java:118)
    	at org.gradle.groovy.scripts.BasicScript$ScriptDynamicObject.setMissingProperty(BasicScript.java:170)
    	at org.gradle.internal.metaobject.AbstractDynamicObject.setProperty(AbstractDynamicObject.java:76)
    	at org.gradle.api.internal.project.DefaultDynamicLookupRoutine.setProperty(DefaultDynamicLookupRoutine.java:42)
    	at org.gradle.groovy.scripts.BasicScript.setProperty(BasicScript.java:74)
    	at org.gradle.internal.classpath.declarations.GroovyDynamicDispatchInterceptors.callInstrumentedSetProperty(GroovyDynamicDispatchInterceptors.java:102)
    	at org.gradle.internal.classpath.declarations.GroovyDynamicDispatchInterceptors.intercept_setProperty(GroovyDynamicDispatchInterceptors.java:89)
    	at build_es5ivf5z9jwb4t9pnjernbno6$_run_closure1.doCall$original([path]/at-gradle-demo/build.gradle:9)
    If this is a bug, let me know so I can report it. But for now I'm under the assumption that there's a good reason for this.
    e
    a
    • 3
    • 9
  • g

    Giuseppe Barbieri

    05/16/2025, 7:41 AM
    In a plugin of mine, I'd like to have the same
    maven
    DSL of the publication task, so in my extension I simply wrote
    Copy code
    val maven = objects.newInstance<MavenArtifactRepository>()
    fun maven(action: Action<in MavenArtifactRepository>) = action.execute(maven)
    but I get: > Could not create an instance of type Library. > > Could not create an instance of type Library$Into. > > Could not create an instance of type org.gradle.api.artifacts.repositories.MavenArtifactRepository. > > Could not generate a decorated class for type MavenArtifactRepository. > > Cannot have abstract method AuthenticationSupported.getAuthentication(): AuthenticationContainer. Is there a way to achieve that?
    v
    • 2
    • 2
  • f

    Filip

    05/16/2025, 2:21 PM
    Hello there. I'm currently working on an Android multi-module project. Among those 42 modules, some are pure Kotlin modules, some are regular android modules and there are also few android modules with flavors. This results in 3 different names for the tasks to execute unit tests: Kotlin modules have just
    test
    , most android modules have
    testDebugUnitTest
    and the modules with flavors have also the flavor name inside the task name, like
    testStagingDebugUnitTest
    . Our goal however is be able to run all existing unit tests in a CI environment using a single command, e.g.
    runAllTest
    . Additionally, since there are different source sets in some of the flavor android modules, we'd like to have an option to configure what tasks in a given module should be executed to cover all source sets. What would be the recommended way of approaching this topic, that would follow the best practices and work properly with configuration avoidance and configuration cache? In the thread I'm pasting an initial draft of the solution, which definitely can be improved (it uses
    afterEvaluate
    , which I'm aware is not recommended). There's a convention plugin to register
    runAllTest
    task, making it dependent on the selected test task name and a custom extension to allow a module define its desired task name.
    e
    v
    a
    • 4
    • 8
  • f

    Francisco Prieto

    05/26/2025, 10:53 PM
    Hey everyone! Do you know if there’s anything similar to
    @SkipWhenEmpty
    for a single file? I’d like to configure the input of a task in such a way that the task is skipped if: • The file doesn’t exist. • The input is set with a
    provider { null }
    . I think this PR asks for something similar, but I couldn’t make it work with a file collection.
    v
    m
    • 3
    • 11
  • a

    Alexey Loubyansky

    05/31/2025, 6:38 AM
    Reading task dependencies in Isolated Projects mode I can't seem to get
    task.getTaskDependencies().getDependencies(task)
    to work when Isolated Projects are enabled. Is there a way or an alternative to that in Isolated Projects mode? Interestingly, while
    task.getTaskDependencies().getDependencies(task)
    return task dependencies,
    task.getDependsOn()
    returns an empty set. Thanks!
    m
    v
    a
    • 4
    • 44
  • m

    Marek

    06/02/2025, 6:18 PM
    Is there a good way to access constants defined in the included build, in the outer project buildscripts? I have started moving our multimodule Android project towards convention plugins. Before, all the configuration was done on the root project level via ext properties. So say we had
    ext.compileSdk = 23
    then subprojects could access it via
    rootProject.ext.compileSdk
    . Now moved the common plugin configurations to convention plugins in an included build. Say in the included build I have now
    Copy code
    object Constants {
      val compileSdk = 23
    }
    I use this value in the convention plugins, but for legacy reasons this value is also needed in some other buildscript in the project. I don't want to have it duplicated just for that. I think I am able to read that value directly in
    *.kts
    files but not in
    .gradle
    files. (Why?) I have figured out I can create some kind of ConstantsConventionPlugin
    Copy code
    class ConstantsConventionPlugin : Plugin<Project> {
    
        override fun apply(project: Project) {
            project.extensions.extraProperties.set("ANDROID_COMPILE_SDK", Constants.compileSdk)
        }
    }
    Can this be avoided? Is there a better alternative?
    e
    v
    • 3
    • 13
  • f

    Francois Dabonot (Frankois)

    06/07/2025, 7:47 AM
    Hi everyone, I have a question about using Symlink with a plugin. From my plugin spmForKmp, the user has a folder where he can add/edit swift file. Currently, the plugin copies these files inside a working directory made by the plugin where everything needed is stored. So the Swift compilation error targets the working directory instead of the original Swift directory. I would like to replace the copy by a symlink of the directory, I know it’s technically possible, but is it a good idea?
    v
    • 2
    • 12
  • f

    Felix de Souza

    06/09/2025, 4:44 PM
    not sure if it’s been asked before/paged out of search, but somewhere between 8.6/8.9 onwards, it became not possible to automatically download the sources for the gradle api in IntelliJ. I tried it for gradle-api-7.6.4.jar and it appears to download it from “somewhere” into
    ~/<user.home>/.ideaLibSources
    which IntelliJ seems to pick up. This does not happen with later versions of gradle for whatever reason. The workaround I’ve been doing is: • change the wrapper to
    -all
    distribution and refresh • go to a gradle class and select
    Choose sources
    • Go to
    ~/<user.home>/.gradle/wrapper/dists/gradle-<version>-all/<some-hash>/gradle-<version>/src
    and select that This obviously doesn’t scale when gradle versions update automatically + many different gradle plugin repositories that I work between. Trying to find an issue on YouTrack and Gradle’s github issue tracker has proven difficult since “gradle” and “intellij” are such common search terms 😅 has anyone actually figured out what the issue is and got it working again? I have a rough feeling that: • https://github.com/gradle/gradle/pull/29320 • https://github.com/gradle/gradle/issues/29483 are somewhat involved, but not sure, hoping someone will know 🙏
    same 1
  • k

    kyle

    06/10/2025, 5:35 PM
    Has anyone successfully accessed the test-retry (or develocity) plugin's Test task extension programmatically via a Java or Groovy binary plugin? I'm doing something like:
    Copy code
    project.tasks.register('myCustomTestTask', Test {
    
      TestRetryTaskExtension retry = it.extensions.getByType(TestRetryTaskExtension)
      ...
    }
    ... but this throws o.g.a.UnknownDomainObjectException: Extension of type 'TestRetryTaskExtension' does not exist.
    t
    • 2
    • 9
  • s

    Sergey Chelombitko

    06/16/2025, 4:06 PM
    Is it possible to apply
    kotlin-dsl
    plugin from a regular Project plugin with the default version? I tried this way, it requires adding an explicit dependency
    org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin
    which I want to avoid.
    Copy code
    class MyConventionPlugin : Plugin<Project> {
        override fun apply(project: Project) {
            project.pluginManager.apply("org.gradle.kotlin.kotlin-dsl")
        }
    }
    e
    a
    v
    • 4
    • 14
  • t

    tony

    06/28/2025, 8:45 PM
    how are people generally handling versioning with their Gradle plugins? is anyone doing strict semver where any breaking change to the public API (including but not limited to the plugin's tasks) triggers a major version bump? I'm finding myself hesitant to do a major version bump for each such change because most people don't actually use the plugin programmatically and when they see a major new release they're hesitant to adopt it and I end up doing all kinds of comms around how it's safe and won't be difficult etc
    m
    o
    +2
    • 5
    • 44
  • k

    Kelvin Chung

    07/03/2025, 6:35 AM
    Hey folks. I have a question loosely related to how things work with the Kotlin Multiplatform Plugin: I currently have this code:
    Copy code
    val testResultsElements = configurations.consumable("testResultsElementsForJvmTest") {
        // This configuration mimics that defined by the "test-suite-base" plugin
        description = "Binary results obtained from running the 'jvmTest' suites."
    
        attributes.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.VERIFICATION))
        attributes.attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, objects.named(VerificationType.TEST_RESULTS))
        // FIXME how do we accommodate multiple JVM targets and their respective test suites?
        attributes.attribute(TestSuiteName.TEST_SUITE_NAME_ATTRIBUTE, objects.named("test"))
    
        val binaryDir = tasks.named<Test>("jvmTest").flatMap { it.binaryResultsDirectory }
        outgoing.artifact(binaryDir) {
            type = ArtifactTypeDefinition.DIRECTORY_TYPE
        }
    }
    I'm wondering what I would have to change if I had two source sets that produced JVM code, so I would have two "testResults" configurations. And how that would relate to the test result aggregation plugin since I would need to differentiate them in such a way that the aggregation plugin could pick each of them separately.
    v
    • 2
    • 18
  • v

    Vampire

    07/09/2025, 11:28 PM
    Is there some recipe somewhere I forgot how to make a task / extension where the consumer can configure a copy-spec that is then accounted as input files for the task and can be used with
    with
    in the task implemenation?
    y
    • 2
    • 5
  • y

    ysb33r

    07/13/2025, 7:17 PM
    There are a number of external tools that produce results in JUnit XML and which can be called from Gradle. One example being
    terraform test -junit-xml
    . What I would like to do is to convert those XML files into HTML reports that look-and-feel the same as the ones generated by
    Test
    tasks. Does anyone know whether that can be achieved with what we have available in the Gradle API today (7.3+)?
    m
    s
    v
    • 4
    • 12
  • t

    Thomas Broyer

    07/15/2025, 3:27 PM
    How do you handle exceptions in WorkActions? I have a WorkAction that runs in a classLoaderIsolation or processIsolation WorkQueue, the code inside the WorkAction can throw exceptions. One of these exceptions (from a third-party library) computes its
    getMessage()
    lazily using a helper class (from that same third-party lib). The problem is that, if I don't do anything special, Gradle will somehow "copy" the exception outside of the classLoaderIsolation or back to the Gradle Daemon process, but won't "copy" that helper class, so when Gradle wants to print the error message to the console and calls the exception's
    getMessage()
    method, that one will throw a ClassNotFoundException that will shadow the actual error. How would you recommend handling this?
    ➕ 1
    t
    m
    • 3
    • 9
  • t

    Thomas Broyer

    07/16/2025, 3:09 PM
    Should
    ConfigurableFileCollection
    properties be initialized with
    .convention()
    or
    .from()
    ? What do you think? (I initially went with
    .convention()
    , but when the conventional value is a bit convoluted to compute –a file in the output of the
    processResources
    task– it's asking too much to the users if they just want to add to the file collection, while on the other hand if initialized with
    .from()
    and they don't want that value they can
    .setFrom()
    to reinitialize it; what would be the use cases for
    .convention()
    then?)
  • t

    Thomas Broyer

    07/16/2025, 3:40 PM
    Similar question about `MapProperty`: would you rather initialize it with
    convention()
    or
    putAll()
    ? (my use-case is initializing it with
    providers.gradlePropertiesPrefixedBy(…)
    ) I've found one instance of MapProperty in the Gradle codebase that's not left empty, and it's in the build logic (so not in a "public" plugin), and it uses a few calls to `put()`: https://github.com/gradle/gradle/blob/56ac845808133d19b7e03a3fcc1264f21122e37e/bui[…]/src/main/groovy/gradlebuild/docs/GradleReleaseNotesPlugin.java
    m
    s
    • 3
    • 8
  • m

    Martin

    07/17/2025, 12:03 PM
    MapProperty
    questions: • Is it possible to have
    null
    as a value? • Having
    MapProperty<String, Any?>
    displays an error in my IDE but compiles fine. Where is the disconnect? How come the KIJP knows that the bound is non nullable?
    v
    • 2
    • 25
  • j

    Jerome Haltom

    07/17/2025, 2:04 PM
    Hello. I have a plugin which adds an extension, upon which various settings can be configured by the user. Based on those settings I need to generate 1 or more tasks. The tasks only exist if the settings say they should. What I am having trouble doing is figuring out exactly where this code for building the tasks should be. I tried, on my custom extension objects, to do it in configureEach: except this seems to run before the user's build.gradle.kts file is processed, so the options the user sets aren't yet available. I did get it working by doing my work in project afterEvalute. But this is not ideal. Maybe I'm misunderstanding how this is supposed to be done.
    m
    t
    +4
    • 7
    • 100
  • a

    Alexey Loubyansky

    07/22/2025, 4:24 PM
    Adding a component variant w/o introducing ambiguity I am trying to add a component variant which uses
    runtime
    or
    runtimeElements
    as a base variant but that introduces an ambiguity, which i'm struggling to find a way to avoid. Is there an example how it's supposed to be done? Here is my playground plugin https://github.com/aloubyansky/playground/blob/gradle-comp-variants/plugin/src/main/java/org/example/PlaygroundPlugin.java And here is the outcome of running it https://github.com/aloubyansky/playground/tree/gradle-comp-variants. Thanks!
    t
    v
    • 3
    • 56
  • a

    Alexey Loubyansky

    07/23/2025, 8:49 PM
    Configuration.copyRecursive() and test-fixtures I'm trying to create a recursive copy of
    testRuntimeClasspath
    , resolve it and iterate through the resolved artifacts. But if there are test fixtures, it fails with
    Copy code
    > Could not resolve all artifacts for configuration ':app:testRuntimeClasspathCopy'.
       > Could not resolve project :app.
         Required by:
             project :app
          > Unable to find a variant with the requested capability: feature 'test-fixtures':
               - Variant 'testRuntimeClasspathCopy' provides 'playground:app:unspecified'
    It looks like something is missing from the copy of the original configuration. Is this expected? Thanks! I have a little playground project to reproduce the issue here https://github.com/aloubyansky/playground/tree/gradle-copyRecursive-test-fixtures Commenting out https://github.com/aloubyansky/playground/blob/gradle-copyRecursive-test-fixtures/plugin/src/main/java/org/example/GreetingTask.java#L21 works. (I realize referencing a
    Project
    from a task is a bad practice, this is just a reproducer).
    o
    v
    • 3
    • 12
  • j

    Jakub Chrzanowski

    07/28/2025, 7:38 PM
    Hey, folks! In my IntelliJ Platform Gradle Plugin, I've decided to bump the Gradle version from
    8.14.3
    to
    9.0.0-rc-4
    . When running integration tests against Gradle 8.x, the plugin fails on
    java.lang.NoSuchMethodError
    and
    java.lang.NoClassDefFoundError
    . In my code, I rely on
    sequenceOf()
    and
    yield()
    , whose signatures slightly changed in Kotlin 2.0:
    sequenceOf()
    Copy code
    * Exception is:
    java.lang.NoSuchMethodError: 'kotlin.sequences.Sequence kotlin.sequences.SequencesKt.sequenceOf(java.lang.Object)'
    	at org.jetbrains.intellij.platform.gradle.resolvers.path.ModuleDescriptorsPathResolver.<init>(ModuleDescriptorsPathResolver.kt:19)
    	at Build_gradle.<init>(build.gradle.kts:53)
    yield()
    Copy code
    * Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':signPlugin'.
    ....
    Caused by: java.lang.NoClassDefFoundError: kotlin/coroutines/jvm/internal/SpillingKt
    	at org.jetbrains.intellij.platform.gradle.tasks.SignPluginTask$arguments$1.invokeSuspend(SignPluginTask.kt:208)
    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    My first though was to build the Gradle plugin targeting Kotlin 1.8 (we support Gradle 8.5+) using:
    Copy code
    kotlin {
        jvmToolchain(17)
    
        compilerOptions {
            apiVersion = KotlinVersion.KOTLIN_1_8
            languageVersion = KotlinVersion.KOTLIN_1_8
        }
    }
    but this didn't really help. Any ideas on how to deal with that?
    m
    v
    v
    • 4
    • 21
  • k

    Kelvin Chung

    07/28/2025, 9:03 PM
    Question: Has there been any long-term thought into reworking
    RepositoryHandler
    so that it has more conventional
    NamedDomainObjectContainer
    semantics? It just seems like with the way Gradle has evolved over the years, something like
    Copy code
    repositories {
      maven(url) { name = "foobar" }
    }
    would be a bit clunky compared to
    Copy code
    repositories.register<MavenArtifactRepository>("foobar") {
      url.set(...)
    }
    Of course, I recognize that any effort to go in that direction would be nontrivial, since the API appears to not have a thing that is both "ordered" and "an extensible container", but one can dream, right?
  • e

    efemoney

    07/31/2025, 9:53 AM
    Hello everyone, I would like to know, foe each dependency in a project for instance, what repository it comes from. Is it possible to get this information from gradle (even internal APIs are fine with me)?
    n
    v
    t
    • 4
    • 15
  • s

    Steve Ebersole

    07/31/2025, 6:01 PM
    Having an interesting situation I cannot understand. As part of a plugin I register the following DSL extensions:
    Copy code
    public abstract class HibernateOrmSpec {
    	...
    
    	@Optional
    	abstract public Property<EnhancementSpec> getEnhancement();
    
    	public void enhancement(Action<EnhancementSpec> action) {
    		EnhancementSpec spec = getObjectFactory().newInstance( EnhancementSpec.class );
    		action.execute( spec );
    		getEnhancement().set( spec );
    	}
    }
    
    abstract public class EnhancementSpec {
    	abstract public Property<Boolean> getEnableLazyInitialization();
    	...
    }
    Later, I try to see if the user specified this "enhancement" extension :
    if ( !getEnhancement().isPresent() ) ...
    The odd part is this... This works as expected:
    Copy code
    hibernate {
        enhancement {
        }
    }
    However, this does not:
    Copy code
    hibernate {
        enhancement
    }
    Now I can easily accept that this second form is "not valid". But the problem I am having is actually being able to recognize this situation to properly handle it (whether that be treat it as the first form, throw an exception, etc.). The problem is that, as far as I can tell, Gradle just ignores it (it being the "enhancement" token). Its not added to ext properties or anything like that. Any idea what Gradle actually does with that?
    o
    • 2
    • 3
  • j

    Jerome Haltom

    07/31/2025, 7:40 PM
    Are there any services to consume to help implementing a per-file compilation avoidance cache? For a custom language or process.
    p
    v
    • 3
    • 18
  • y

    ysb33r

    08/08/2025, 3:26 PM
    Does
    -i
    affect a task's class path?
    That is the headline question, let me explain. I was testing up-to-date status of some tasks in plugin using testKit. Effectively, what I was doing in the test is something like
    Copy code
    GradleRunner.create().withArguments('task1')
    GradleRunner.create().withArguments('task2')
    basically
    task2
    depend on
    task1
    which depends on
    task0
    Thus in the first invocation
    task0
    and
    task1
    will have an outcome of
    SUCCESS
    . In the 2nd invocation, those two should have an outcome of
    UP_TO_DATE
    , and
    task2
    will be
    SUCCESS
    . Not problem with that, until I did...
    Copy code
    GradleRunner.create().withArguments('task1')
    GradleRunner.create().withArguments('task2', '-i')
    Suddenly, on the 2nd invocation the outcome of
    task0
    was
    SUCCESS
    instead of
    UP_TO_DATE
    and Gradle logs stated that
    Copy code
    Task ':task0' is not up-to-date because:
      Class path of task ':task0' has changed from 58046a25460590d169a1847f193c5177 to b72b7af69ca1f7306a1e3a2dcf54a21a.
    I find that unexpected behaviour. WDYT?
    👀 2
    v
    • 2
    • 3