szpak/gradle-pitest-plugin

Do not require repository for root build.gradle

kelemen opened this issue · 12 comments

As is now, the plugin forces me to have a block like this in the beginning of root build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
}

This is inconvenient when the project is setup to rely on buildSrc (the buildscript block is more restricting).

szpak commented

Yes, the plugin creates the new configuration in the buildscript in the root project and adds there PIT dependencies.

It was done 2 years ago and I cannot call if there was a problem in putting it only in the modules with the PIT plugin applied not just once in the root project. AFAIR someone already complained on that in the past. It could be changed. However, it would break a backward compatibility as developers can use pitest configuration to add their own runtime dependencies (e.g. the PIT plugins) which probably is not used to often.

Nevertheless, I'm not getting completely the whole configuration problem in your project. Gradle plugins are usually defined as a dependency in the root projects and later applied in desired modules. Where would you like to define buildscript { dependencies { classpath: gradle-pitest-plugins... } }? Could you write more about your project?

I simply apply dependencies in the buildSrc project and the dependencies of buildSrc will be visible in all build scripts. Given that I almost always have a buildSrc project, it just doesn't make sense to declare some of the things in the root build.gradle (also declaring the repositories again). Especially, since the buildscript block is much more limited in what you can do there.

Though I haven't thought everything through but would it be possible to have 'info.solidsoft.gradle.pitest:gradle-pitest-plugin' depend on the artifact you manually add ('org.pitest:pitest-command-line')? That way, you don't have to mutate the build script's class loader. I personally would also be ok (as a workaround), if I could manually apply the dependency instead (even if that means a little extra configuration on my part).

szpak commented

As mentioned by @remal in #155 (comment) it may cause The configuration :pitest was resolved without accessing the project in a safe manner warning in Gradle 6.

I plan to come back to that conception in the next iteration.

szpak commented

I finally took a closer look at that and it doesn't seem to be too problematic. I moved the configuration from the buildscript scope for the root project to the regular scope for the current project (the same as the Codenarc plugin made by the Gradle team). I'm not sure about the side effects of using a regular configuration instead of buildscript one.

@kelemen @remal You may want to test 1.5.0-SNAPSHOT I've just uploaded:

buildscript {
    repositories {
        mavenCentral()
        //Needed only for SNAPSHOT versions
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath 'info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.5.0-SNAPSHOT'
    }
}

In the simple case, the required change is just to move the configuration out of the buildscript (and to subprojects if available):

configurations.create('pitest')
dependencies {
   pitest 'org.pitest:pitest-junit5-plugin:0.12'
}

It shouldn't be required to create the configuration as the plugin creates it, however, it seems to be created too late as I register my plugin right after JavaPlugin has been applied:

project.plugins.withType(JavaPlugin).configureEach { ...
            project.tasks.register(PITEST_TASK_NAME, PitestTask) { t ->
                addPitDependencies(configuration())
...

I will think if it can be simplified.

For using the new 1.4.7+ syntax for JUnit 5 plugin or no using plugin at all, in the majority of cases it should just work without any change.

remal commented

@szpak Could you please write how the usage will look like now?

Can I use the plugin in this manner?

apply plugin: "info.solidsoft.pitest"
dependencies {
    pitest "org.pitest:pitest-command-line"
    pitest "org.pitest:pitest-junit5-plugin"
}
pitest {
    testPlugin = "junit5"
}
szpak commented
apply plugin: "info.solidsoft.pitest"

configurations.create('pitest')
dependencies {
//    pitest "org.pitest:pitest-command-line" //why did you need it?
    pitest "org.pitest:pitest-junit5-plugin"
}
pitest {
    testPlugin = "junit5"
}

Btw, with changes in 1.4.7 it should be as easy as:

apply plugin: "info.solidsoft.pitest"
pitest {
    junit5PluginVersion = '0.12'
}

(but please also change the first construction to confirm that it works in general).

remal commented
configurations.create('pitest')

Why do you need it? Isn't the configuration created by the plugin itself?

 

dependencies {
    pitest "org.pitest:pitest-command-line"
}

Usually plugins add "optional dependencies" (see how it's done in SpotBugs) I thought that you're using the same mechanism, in this case I have to put default dependency myself... What am I missing here?

 

pitest {
    junit5PluginVersion = '0.12'
}

Unfortunately, tools like Dependabot or Renovate won't handle it. They handle only dependencies written in common manner.

szpak commented

Why do you need it? Isn't the configuration created by the plugin itself?

Please take a look at my previous message where I explain why I suspect it fails without that (II plan to take a look at that, but please propose the change in code to fix it if you know a simple solution).

Usually plugins add "optional dependencies" (see how it's done in SpotBugs) I thought that you're using the same mechanism, in this case I have to put default dependency myself... What am I missing here?

I didn't know that mechanism. When I started writing my plugin it most likely didn't exist :-). However, I add that dependency when plugin is applied, based on pitest.pitestVersion configuration property. You shouldn't need to do that (unless the next point holds).

Unfortunately, tools like Dependabot or Renovate won't handle it. They handle only dependencies written in common manner.

I know, the support for Gradle is much worse than for Maven. On the other hand, to keep the configuration simple, how often JUnit 5 plugin for PIT is updated? Maybe in that case it would be more feasible to subscribe to updates in that repo with https://gitpunch.com/ or GitHub releases itself and 2 times a year craft a PR manually?

remal commented

BTW How about including JUnit5 into Gradle plugin? It won"t consume much space and will make configuration easier

szpak commented

I do not understand what do you exactly would like to achieve. The following would be hard to beat :-).

apply plugin: "info.solidsoft.pitest"
pitest {
    junit5PluginVersion = '0.12'
}

(it's enough to have PIT with the JUnit 5 plugin up and running in the simple case)

szpak commented

Unless you wanted to suggest its addition to PIT itself (the same as the TestNG plugin). However, it more question to Henry.

szpak commented

Guys, I've just uploaded the new SNAPSHOT with removed the need to create the pitest configuration manually and added the migration in the changelog. If you have any other comments/suggestions please write it here. I plan to release the 1.5.0 version tomorrow.

apply plugin: "info.solidsoft.pitest"
dependencies {
    pitest 'org.example.pit.plugins:pitest-custom-plugin:0.42'
}
pitest {
    testPlugin = 'custom'
    //...
}