Giter Club home page Giter Club logo

gradle-stutter's Introduction

gradle-stutter

NOTE: As of 0.7.0, gradle-stutter is published to Maven Central

Getting Help or Contributing

IMPORANT: I consider this plugin feature complete and don't spend a lot of time on maintenance due to other time commitments. While, I will eventually get to issues or PRs raised, do not expect a timely response. I'm not trying to be rude or dismissive, I only get back to this project periodically (on the order of months, in many cases). Please set your expectations appropriately as you file issues or open PRs.

Please use the repo's issues for all questions, bug reports, and feature requests.

Why do you care?

When writing a Gradle plugin you often want to run the same suite of tests against all versions you support. The Gradle TestKit gives you the tools to do this, but makes you write the scaffolding for which versions and which tests.

What is it?

gradle-stutter is a Gradle plugin plugin, org.ajoberstar.stutter, which does some common setup for testing Gradle plugins against multiple Gradle versions.

  • Extension for specifying Java and Gradle versions that are compatible with your plugin
  • Allows specifying different compatible versions for each Java version
  • Task to create lock file listing compatible Gradle versions
  • Generates a compatibility test task for your suite for each combination of supported Java version and Gradle version
  • Uses Gradle's toolchain feature to run each suite under the appropriate JDK

See java-gradle-plugin docs for more details on Gradle's out-of-the-box functionality.

Usage

See the Release Notes for updates on changes and compatibility with Java and Gradle versions.

Applying the Plugin

plugins {
    id 'org.ajoberstar.stutter' version '<version>'
}

Configuration

stutter {
  // if true, only match min/max within that otherwise matches your compatibility specs in each Gradle major version
  sparse = false // defaults to true

  matrices {
    // a matrix of tests running against Java 8
    java8 {
      javaToolchain {
        languageVersion = JavaLanguageVersion.of(8)
      }
      gradleVersions {
        compatibleRange '3.0', '4.0' // include 3.0 <= version < 4.0
        compatibleRange '4.2' // include 4.2 <= version
        compatible '2.14', '1.2' // include 2.14 and 1.12 specifically
        incompatible '3.3' // exclude 3.3 even if included above
      }
    }

    // name can be anything
    jdkNine {
      javaToolchain {
        languageVersion = JavaLanguageVersion.of(9)
      }
      gradleVersions {
        compatibleRange '4.0' // include 4.0 <= version
      }
    }
  }

  // You do have to specify compatible Gradle versions for all Java versions you run Gradle with

  // If you have a lot of tests, or otherwise just don't want to test every Gradle version that you say is compatible,
  // use sparse = true. This will greatly limit the number of versions you test against, but should do the job of
  // verifying compatibility.
  // e.g.  compatible '2.14' and compatibleRange '3.0'
  //       matches '2.14', '3.0', '3.5.1', '4.0', '4.7' (presuming 4.7 is the latest available 4.x)
}

Lock file

Lock files will be generated/used from the <project>/stutter.lockfile directory.

Lock files are generated with the stutterWriteLocks task based on the configuration of the stutter extension (see above).

./gradlew stutterWriteLocks

Tests

The plugin adds a compatTest source set that is configured via java-gradle-plugin as the source set for your plugin tests. This means you can leverage withPluginClasspath on the GradleRunner for your tests. The test kit dependency is not added by this plugin.

The following tasks are available:

  • One compatTest<matrix>Gradle<version> (e.g. compatTestJava8Gradle7.3.3) task per supported version (based on the compatible lock file -- see above for details)

  • A matrix-level compatTest<matrix> (e.g. compatTestJava8) task that depends on all specific Gradle versions tasks for that matrix. This allows you to run all of the tests for a given JDK matrix via one convenient task.

  • An overall compatTest which depends on all of the matrix-level tasks. This allows you to run all tests for all JDKs and Gradle versions.

  • check does not depend on compatTest by default, but you can add a dependency easily

    tasks.named("check") {
      dependsOn(tasks.named("compatTest"))
    }
    

Your tests should reference the compat.gradle.version system property when they specify a version on the GradleRunner:

GradleRunner.create()
    .withGradleVersion(System.getProperty("compat.gradle.version"))
    //...

Migrating from 0.6.0

  • Gradle must be run with Java 11 or higher
  • Lock files have moved from .stutter/ to stutter.lockfile (you should delete the .stutter/ directory)
  • sparse is now the default, you can still set it to false if you prefer
  • check does not depend on compatTest anymore. This gives you more flexibilty as to which tests are run by default.
  • Syntax changes in the stutter extension:

From:

stutter {
  sparse = true

  java(8) {
    compatibleRange '3.0', '4.0'
    compatibleRange '4.2'
    compatible '2.14', '1.2'
    incompatible '3.3'
  }

  java(9) {
    compatibleRange '4.0'
  }
}

To:

stutter {
  sparse = true

  matrices {
    java8 {
      javaToolchain {
        languageVersion = JavaLanguageVersion.of(8)
      }
      gradleVersions {
        compatibleRange '3.0', '4.0'
        compatibleRange '4.2'
        compatible '2.14', '1.2'
        incompatible '3.3'
      }
    }

    java9 {
      javaToolchain {
        languageVersion = JavaLanguageVersion.of(9)
      }
      gradleVersions {
        compatibleRange '4.0'
      }
    }
  }
}

Finding versions of grgit

Newest versions are on Maven Central

As of 0.7.0, gradle-stutter is published to Maven Central and not the Gradle Plugin Portal, but since the portal proxies Maven Central you can still access it through the portal. The only side effect is that the portal will no longer list the latest version. Use this repo or search.maven.org to find the latest version.

Old versions from Bintray/JCenter

This project was previously uploaded to JCenter, which was deprecated in 2021.

In the event that JCenter is unavailable and acess to past versions (0.6.0 and earlier) is needed, I've made a Maven repo available in bintray-backup. Add the following to your repositories to use it.

maven {
  name = 'ajoberstar-backup'
  url = 'https://ajoberstar.org/bintray-backup/'
}

Made possible by lacasseio/bintray-helper in case you have a similar need to pull your old Bintray artifacts.

Acknowledgements

Thanks to all of the contributors.

Alternatives

TestKit (out-of-the-box)

TestKit is built into Gradle, so it should be your first consideration. It provides a good interface to kick off full test builds and verify the output/tasks that ran. This tends to be a far more effective way to test Gradle plugin code than unit testing, due to the complexity of Gradle.

On top of TestKit, Stutter provides a convenient way to run a test suite against multiple versions of Gradle. This is very useful for verifying compatibility.

GradleTest

The org.ysb33r.gradletest plugin is optimized for creating and testing sample projects without you having to directly interact with TestKit. These can also be tested across multiple versions of Gradle providing helpful compatibility verification. GradleTest also provides the ability to test Gradle versions far older than Stutter does.

Stutter leaves the user to decide how to leverage TestKit, it just helps provide the ability to test multiple versions with the same suite. If your use case is more centered around samples or full project tests, GradleTest may be a better fit.

gradle-stutter's People

Contributors

ajoberstar avatar goooler avatar grv87 avatar twisterrob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

goooler

gradle-stutter's Issues

compatTest tasks resolve their config too eagerly

This grgit commit fails due to classpath issues because when compatTest tasks are created they set the task to use the runtime classpath of the source set. Grgit needs to add things to the runtimeClasspath in order to run properly, and this causes an ordering problem. In the old plugin there was more delay here.

Feature Request: Test against last patch versions only

It would be good to have an option to test against last patch versions only.
For example, I declare:

compatibleRange '4.9'

For now, there are the following Gradle versions: 4.9, 4.10, 4.10.1, 4.10.2.
4.10.1 and 4.10.2 are bug fixes for 4.10.

I would like to test against last patch version for each minor, i.e. 4.9 and 4.10.2 only.
I don't see a reason to support 4.10 and 4.10.1 and test against them:

  1. If my plugin works with 4.9 and 4.10.2, it is safe to assume that it works with 4.10 and 4.10.1 too, or 4.10 and 4.10.1 contain bugs and are not supported.
  2. It is not a problem for a user to update Gradle to next patch release.
  3. It is just another way to limit number of versions tested. For me, sparse seems to overly limit number of versions. I had problems with incompatibilities between minor versions in the past, so I would like to test against each minor. But not against each patch.

Right now this is impossible without manual coding.

The first and last versions in compatibleRange are not included

The first and last versions are not tested against!

  1. Create a project with Gradle 8.9 and id 'org.ajoberstar.stutter' version '1.0.0'
  2. Specify compatibleRange '6.0.0', '6.5':
stutter {
  //sparse = false // defaults to true
  matrices {
    java11 {
      javaToolchain {
        languageVersion = JavaLanguageVersion.of(11)
      }
      gradleVersions {
        compatibleRange '6.0.0', '6.5'
      }
    }
  }
  1. Perform stutterWriteLocks
  2. See the locks file after stutterWriteLocks:
$ cat stutter.lockfile 
# DO NOT MODIFY: Generated by Stutter plugin.
java11=6.0.1,6.4.1

Expected: both '6.0.0' and '6.5'` are included

Actual: neither '6.0.0' nor '6.5'` are included

The same misbehavior happens with sparse = false:

$ cat stutter.lockfile 
# DO NOT MODIFY: Generated by Stutter plugin.
java11=6.0.1,6.1.1,6.2.2,6.3,6.4.1

(My guess is that this is somehow related to using the last available patch.)

Use services.gradle to detect available versions

Make it easier for someone to test against the latest versions of Gradle. services.gradle.org provides APIs that could return all available versions. Maybe combining this with a minimum version and a list of known incompatible versions, you could just test all versions when they are available.

Plugin stopped working due to HTTP -> HTTPS redirect

> Task :stutterWriteLocks FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':stutterWriteLocks'.
> com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
   at [Source: (URL); line: 1, column: 0]

The reason is http://services.gradle.org/versions/all is now redirected to https://services.gradle.org/versions/all:

# curl -v http://services.gradle.org/versions/all
* Expire in 0 ms for 6 (transfer 0x55fcc0)
* Expire in 1 ms for 1 (transfer 0x55fcc0)
* Expire in 1 ms for 1 (transfer 0x55fcc0)
* Expire in 2 ms for 1 (transfer 0x55fcc0)
* Expire in 3 ms for 1 (transfer 0x55fcc0)
* Expire in 5 ms for 1 (transfer 0x55fcc0)
* Expire in 6 ms for 1 (transfer 0x55fcc0)
*   Trying 104.18.190.9...
* TCP_NODELAY set
* Expire in 149988 ms for 3 (transfer 0x55fcc0)
* Expire in 200 ms for 4 (transfer 0x55fcc0)
* Connected to services.gradle.org (104.18.190.9) port 80 (#0)
> GET /versions/all HTTP/1.1
> Host: services.gradle.org
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 21:57:22 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: max-age=3600
< Expires: Sun, 03 Nov 2019 22:57:22 GMT
< Location: https://services.gradle.org/versions/all
< Server: cloudflare
< CF-RAY: 53019a825bcdc429-LED
<
* Connection #0 to host services.gradle.org left intact

Such redirect (protocol change) isn't handled by Java by default.

StutterPlugin uses deprecated API: forUseAtConfigurationTime

This prevents users of your plugin from using org.gradle.warning.mode=fail. The fix is simple, see #33 (comment)

Warning: from build scan

Plugin:org.ajoberstar.stutter	
at org.gradle.api.internal.provider.AbstractMinimalProvider.forUseAtConfigurationTime(AbstractMinimalProvider.java:135)	
at org.ajoberstar.gradle.stutter.StutterPlugin.getLockedVersions(StutterPlugin.java:120)	
at org.ajoberstar.gradle.stutter.StutterPlugin.createCompatTestTasks(StutterPlugin.java:51)	
at org.ajoberstar.gradle.stutter.StutterPlugin.lambda$configureCompatTest$2(StutterPlugin.java:46)	
at org.gradle.api.internal.DefaultMutationGuard$1.execute(DefaultMutationGuard.java:45)	
at org.gradle.internal.code.DefaultUserCodeApplicationContext$CurrentApplication$1.execute(DefaultUserCodeApplicationContext.java:122)	
at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1.run(DefaultCollectionCallbackActionDecorator.java:110)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction.execute(DefaultCollectionCallbackActionDecorator.java:107)	
at org.gradle.internal.ImmutableActionSet$SetWithFewActions.execute(ImmutableActionSet.java:285)	
at org.gradle.api.internal.DefaultDomainObjectCollection.doAdd(DefaultDomainObjectCollection.java:262)	
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.doAdd(DefaultNamedDomainObjectCollection.java:124)	
at org.gradle.api.internal.DefaultDomainObjectCollection.add(DefaultDomainObjectCollection.java:256)	
at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.tryCreate(DefaultNamedDomainObjectCollection.java:1005)	
at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.calculateOwnValue(DefaultNamedDomainObjectCollection.java:990)	
at org.gradle.api.internal.provider.AbstractMinimalProvider.calculateValue(AbstractMinimalProvider.java:115)	
at org.gradle.api.internal.provider.Collectors$ElementFromProvider.collectEntries(Collectors.java:100)	
at org.gradle.api.internal.provider.Collectors$TypedCollector.collectEntries(Collectors.java:334)	
at org.gradle.api.internal.provider.Collectors$TypedCollector.collectInto(Collectors.java:329)	
at org.gradle.api.internal.collections.SortedSetElementSource.realize(SortedSetElementSource.java:141)	
at org.gradle.api.internal.collections.SortedSetElementSource.addPending(SortedSetElementSource.java:169)	
at org.gradle.api.internal.DefaultDomainObjectCollection.addLater(DefaultDomainObjectCollection.java:274)	
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.addLater(DefaultNamedDomainObjectCollection.java:157)	
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.createDomainObjectProvider(AbstractNamedDomainObjectContainer.java:122)	
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.register(AbstractNamedDomainObjectContainer.java:114)	
at org.ajoberstar.gradle.stutter.StutterPlugin.configureCompatTest(StutterPlugin.java:45)	
at org.ajoberstar.gradle.stutter.StutterPlugin.lambda$apply$0(StutterPlugin.java:29)	
at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:261)	
at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:258)	
at org.gradle.internal.code.DefaultUserCodeApplicationContext$CurrentApplication$1.execute(DefaultUserCodeApplicationContext.java:122)	
at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1.run(DefaultCollectionCallbackActionDecorator.java:110)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction.execute(DefaultCollectionCallbackActionDecorator.java:107)	
at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:161)	
at org.gradle.api.internal.plugins.DefaultPluginManager.withPlugin(DefaultPluginManager.java:264)	
at org.ajoberstar.gradle.stutter.StutterPlugin.apply(StutterPlugin.java:27)	
at org.ajoberstar.gradle.stutter.StutterPlugin.apply(StutterPlugin.java:20)	
at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)	
at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)	
at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:190)	
at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:54)	
at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:285)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:170)	
at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)	
at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:169)	
at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:148)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.lambda$applyLegacyPlugin$2(DefaultPluginRequestApplicator.java:191)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:232)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyLegacyPlugin(DefaultPluginRequestApplicator.java:189)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.access$300(DefaultPluginRequestApplicator.java:62)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator$1$1.lambda$addLegacy$0(DefaultPluginRequestApplicator.java:149)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.lambda$applyPlugins$0(DefaultPluginRequestApplicator.java:107)	
at java.lang.Iterable.forEach(Iterable.java:75)	
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:107)	
at org.gradle.kotlin.dsl.provider.PluginRequestsHandler.handle(PluginRequestsHandler.kt:44)	
at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator$InterpreterHost.applyPluginsTo(KotlinScriptEvaluator.kt:217)	
at Program.execute(Unknown Source)	
at org.gradle.kotlin.dsl.provider.StandardKotlinScriptEvaluator.evaluate(KotlinScriptEvaluator.kt:123)	
at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:51)	
at org.gradle.kotlin.dsl.provider.KotlinScriptPluginFactory$create$1.invoke(KotlinScriptPluginFactory.kt:48)	
at org.gradle.kotlin.dsl.provider.KotlinScriptPlugin.apply(KotlinScriptPlugin.kt:35)	
at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:68)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.configuration.BuildOperationScriptPlugin.lambda$apply$0(BuildOperationScriptPlugin.java:65)	
at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)	
at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:65)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:407)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:425)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:406)	
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:46)	
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:27)	
at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)	
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.lambda$run$0(LifecycleProjectEvaluator.java:109)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:407)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$fromMutableState$2(DefaultProjectStateRegistry.java:430)	
at org.gradle.internal.work.DefaultWorkerLeaseService.withReplacedLocks(DefaultWorkerLeaseService.java:360)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:430)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:406)	
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:100)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:72)	
at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:789)	
at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:155)	
at org.gradle.api.internal.project.ProjectLifecycleController.lambda$ensureSelfConfigured$2(ProjectLifecycleController.java:84)	
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)	
at org.gradle.internal.model.StateTransitionController.lambda$maybeTransitionIfNotCurrentlyTransitioning$10(StateTransitionController.java:199)	
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:34)	
at org.gradle.internal.model.StateTransitionController.maybeTransitionIfNotCurrentlyTransitioning(StateTransitionController.java:195)	
at org.gradle.api.internal.project.ProjectLifecycleController.ensureSelfConfigured(ProjectLifecycleController.java:84)	
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.ensureConfigured(DefaultProjectStateRegistry.java:381)	
at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:34)	
at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:48)	
at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:42)	
at org.gradle.configuration.BuildTreePreparingProjectsPreparer.prepareProjects(BuildTreePreparingProjectsPreparer.java:65)	
at org.gradle.configuration.BuildOperationFiringProjectsPreparer$ConfigureBuild.run(BuildOperationFiringProjectsPreparer.java:52)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)	
at org.gradle.configuration.BuildOperationFiringProjectsPreparer.prepareProjects(BuildOperationFiringProjectsPreparer.java:40)	
at org.gradle.initialization.VintageBuildModelController.lambda$prepareProjects$2(VintageBuildModelController.java:84)	
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)	
at org.gradle.internal.model.StateTransitionController.lambda$transitionIfNotPreviously$11(StateTransitionController.java:213)	
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:34)	
at org.gradle.internal.model.StateTransitionController.transitionIfNotPreviously(StateTransitionController.java:209)	
at org.gradle.initialization.VintageBuildModelController.prepareProjects(VintageBuildModelController.java:84)	
at org.gradle.initialization.VintageBuildModelController.prepareToScheduleTasks(VintageBuildModelController.java:71)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildModelController.prepareToScheduleTasks(ConfigurationCacheAwareBuildModelController.kt:49)	
at org.gradle.internal.build.DefaultBuildLifecycleController.lambda$prepareToScheduleTasks$6(DefaultBuildLifecycleController.java:175)	
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)	
at org.gradle.internal.model.StateTransitionController.lambda$maybeTransition$9(StateTransitionController.java:190)	
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:34)	
at org.gradle.internal.model.StateTransitionController.maybeTransition(StateTransitionController.java:186)	
at org.gradle.internal.build.DefaultBuildLifecycleController.prepareToScheduleTasks(DefaultBuildLifecycleController.java:173)	
at org.gradle.internal.buildtree.DefaultBuildTreeWorkPreparer.scheduleRequestedTasks(DefaultBuildTreeWorkPreparer.java:36)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildTreeWorkController$scheduleAndRunRequestedTasks$executionResult$1$result$1.invoke(ConfigurationCacheAwareBuildTreeWorkController.kt:48)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildTreeWorkController$scheduleAndRunRequestedTasks$executionResult$1$result$1.invoke(ConfigurationCacheAwareBuildTreeWorkController.kt:45)	
at org.gradle.configurationcache.DefaultConfigurationCache$loadOrScheduleRequestedTasks$1.invoke(DefaultConfigurationCache.kt:143)	
at org.gradle.configurationcache.DefaultConfigurationCache$loadOrScheduleRequestedTasks$1.invoke(DefaultConfigurationCache.kt:142)	
at org.gradle.configurationcache.DefaultConfigurationCache.runWorkThatContributesToCacheEntry(DefaultConfigurationCache.kt:310)	
at org.gradle.configurationcache.DefaultConfigurationCache.loadOrScheduleRequestedTasks(DefaultConfigurationCache.kt:142)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildTreeWorkController$scheduleAndRunRequestedTasks$executionResult$1.apply(ConfigurationCacheAwareBuildTreeWorkController.kt:45)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildTreeWorkController$scheduleAndRunRequestedTasks$executionResult$1.apply(ConfigurationCacheAwareBuildTreeWorkController.kt:44)	
at org.gradle.composite.internal.DefaultIncludedBuildTaskGraph.withNewWorkGraph(DefaultIncludedBuildTaskGraph.java:112)	
at org.gradle.configurationcache.ConfigurationCacheAwareBuildTreeWorkController.scheduleAndRunRequestedTasks(ConfigurationCacheAwareBuildTreeWorkController.kt:44)	
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$scheduleAndRunTasks$1(DefaultBuildTreeLifecycleController.java:76)	
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$runBuild$4(DefaultBuildTreeLifecycleController.java:119)	
at org.gradle.internal.model.StateTransitionController.lambda$transition$6(StateTransitionController.java:169)	
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)	
at org.gradle.internal.model.StateTransitionController.lambda$transition$7(StateTransitionController.java:169)	
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:44)	
at org.gradle.internal.model.StateTransitionController.transition(StateTransitionController.java:169)	
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.runBuild(DefaultBuildTreeLifecycleController.java:116)	
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.scheduleAndRunTasks(DefaultBuildTreeLifecycleController.java:76)	
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.scheduleAndRunTasks(DefaultBuildTreeLifecycleController.java:71)	
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)	
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)	
at org.gradle.internal.buildtree.ProblemReportingBuildActionRunner.run(ProblemReportingBuildActionRunner.java:49)	
at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:65)	
at org.gradle.tooling.internal.provider.FileSystemWatchingBuildActionRunner.run(FileSystemWatchingBuildActionRunner.java:140)	
at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:41)	
at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.lambda$execute$0(RootBuildLifecycleBuildActionExecutor.java:40)	
at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:123)	
at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.execute(RootBuildLifecycleBuildActionExecutor.java:40)	
at org.gradle.internal.buildtree.InitDeprecationLoggingActionExecutor.execute(InitDeprecationLoggingActionExecutor.java:62)	
at org.gradle.internal.buildtree.InitProblems.execute(InitProblems.java:38)	
at org.gradle.internal.buildtree.DefaultBuildTreeContext.execute(DefaultBuildTreeContext.java:40)	
at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.lambda$execute$0(BuildTreeLifecycleBuildActionExecutor.java:71)	
at org.gradle.internal.buildtree.BuildTreeState.run(BuildTreeState.java:60)	
at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.execute(BuildTreeLifecycleBuildActionExecutor.java:71)	
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$3.call(RunAsBuildOperationBuildActionExecutor.java:61)	
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$3.call(RunAsBuildOperationBuildActionExecutor.java:57)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)	
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)	
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)	
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)	
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor.execute(RunAsBuildOperationBuildActionExecutor.java:57)	
at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.lambda$execute$0(RunAsWorkerThreadBuildActionExecutor.java:36)	
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:264)	
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:128)	
at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.execute(RunAsWorkerThreadBuildActionExecutor.java:36)	
at org.gradle.tooling.internal.provider.continuous.ContinuousBuildActionExecutor.execute(ContinuousBuildActionExecutor.java:110)	
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecutor.execute(SubscribableBuildActionExecutor.java:64)	
at org.gradle.internal.session.DefaultBuildSessionContext.execute(DefaultBuildSessionContext.java:46)	
at org.gradle.tooling.internal.provider.BuildSessionLifecycleBuildActionExecuter$ActionImpl.apply(BuildSessionLifecycleBuildActionExecuter.java:92)	
at org.gradle.tooling.internal.provider.BuildSessionLifecycleBuildActionExecuter$ActionImpl.apply(BuildSessionLifecycleBuildActionExecuter.java:80)	
at org.gradle.internal.session.BuildSessionState.run(BuildSessionState.java:69)	
at org.gradle.tooling.internal.provider.BuildSessionLifecycleBuildActionExecuter.execute(BuildSessionLifecycleBuildActionExecuter.java:62)	
at org.gradle.tooling.internal.provider.BuildSessionLifecycleBuildActionExecuter.execute(BuildSessionLifecycleBuildActionExecuter.java:41)	
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:64)	
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)	
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:51)	
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:39)	
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:47)	
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:31)	
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:65)	
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:29)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)	
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)	
at org.gradle.util.internal.Swapper.swap(Swapper.java:38)	
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:64)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)	
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:84)	
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)	
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)	
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)	
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)	
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)	
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)	
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)	
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)

Add a helper library for tests

Should have a few features:

  • Create a GradleRunner with Gradle version and plugin classpath already populated
  • Support copying a test project and setting the project dir for the GradleRunner
  • (Possibly) A way to conditionally run a test based on the version

Disable compatibility testing with other Gradle versions from command line

check by default depends on compatTest. With local development I would like to run compatTests only with the current Gradle version leaving more thoroughgoing testing for CI (or for running them on demand after bigger changes). I cannot easily skip compatTest as my sanity tests defined there would not be executed at all. It is required to conditionally set compatibilityRange which is not elegant.

It would be useful to have a property in the extension to be able set in my build.gradle to indicate that compatTest should be only executed for the current Gradle version (false by default).

Point to other plugins in docs

Use cases can differ quite a bit between plugins, so these should be documented and point to other plugins that may better meet other uses.

  • ysb33r/gradleTest for auto-generated tests against wide ranges of version compatibility

stutter restrictions:

  • Only intended to support compatibility tests against Gradle 2.13+
  • Requires you to write your own tests

Sparse option to test fewer Gradle versions

Add a sparse option that only takes the lowest supported and highest within a major version range. Might want to keep any explicitly added ones too.

Might want to add a compatTestSparse and compatTestFull tasks regardless of the setting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.