pact-foundation / pact-jvm

JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://docs.pact.io
Apache License 2.0
1.08k stars 479 forks source link

Since 4.3.16 pact publish configuration can not be found #1634

Closed gedankennebel closed 1 year ago

gedankennebel commented 2 years ago

We updated from 4.3.15 to 4.3.16 and now see this issue You must add a pact publish configuration to your build before you can use the pactPublish task

Altough we have a pact publish configuration and it still works with 4.3.15. We use Gradle 7.5.1

Does may this commit has something to do with it: https://github.com/pact-foundation/pact-jvm/commit/e3dd8bf5d1cdaa263c428cb1e0fdc94196ce6fde?diff=split#diff-84994c4f13669c1feb65cf6db4a09398e94d9fef8d687329926cbd4547cb1370

Since 4.3.16 it seems like our pactPublish in this class is null https://github.com/pact-foundation/pact-jvm/blob/master/provider/gradle/src/main/groovy/au/com/dius/pact/provider/gradle/PactPublishTask.groovy#L41

We don´t use Configuration cache as also Gradle says it is an incubating feature. https://docs.gradle.org/current/userguide/configuration_cache.html

eloo commented 1 year ago

Looks like this is still broken in 4.4.2 using this example config

pact {

    broker {
        pactBrokerUrl = 'https://your-broker-url/'

        // To use basic auth
        pactBrokerUsername = '<USERNAME>'
        pactBrokerPassword = '<PASSWORD>'

        // OR to use a bearer token
        pactBrokerToken = '<TOKEN>'
    }

    publish {
        pactDirectory = '/pact/dir' // defaults to $buildDir/pacts
        pactBrokerUrl = 'http://pactbroker:1234'
    }

}
hirth-abi commented 1 year ago

Appending this to the previous example is a strange/buggy but working workaround:

pactPublish {
    pactPublish = project.pact.publish
}
gedankennebel commented 1 year ago

@rholshausen could someone please answer on this? is this really a bug regarding the task registration code change or do we miss something here ?

rholshausen commented 1 year ago

Sorry, I don't know what is causing this. As soon as I have some time, I'll try to replicate it.

rholshausen commented 1 year ago

I can't replicate this issue. 4.3.16 works fine on Pact-JVM project as well as my test project.

I created this empty Gradle project https://github.com/rholshausen/issue-1634 using Gradle 7.5.1 and Pact-JVM gradle plugin 4.3.16, added the snippet above, but it works without the error displayed above.

❯ ./gradlew tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project 'issue-1634'
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'issue-1634'.
dependencies - Displays all dependencies declared in root project 'issue-1634'.
dependencyInsight - Displays the insight into a specific dependency in root project 'issue-1634'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of root project 'issue-1634'.
projects - Displays the sub-projects of root project 'issue-1634'.
properties - Displays the properties of root project 'issue-1634'.
resolvableConfigurations - Displays the configurations that can be resolved in root project 'issue-1634'.
tasks - Displays the tasks runnable from root project 'issue-1634'.

Pact tasks
----------
canIDeploy - Check if it is safe to deploy by checking whether or not the specified pacticipant versions are compatible
pactPublish - Publish your pacts to a pact broker
pactVerify - Verify your pacts against your providers

To see all tasks and more detail, run gradlew tasks --all

To see more detail about a task, run gradlew help --task <task>

BUILD SUCCESSFUL in 303ms
1 actionable task: 1 executed

issue-1634 on  main via ☕ v11.0.12 via 💎 v2.7.6 
❯ ./gradlew pactPublish

BUILD SUCCESSFUL in 287ms
1 actionable task: 1 executed

issue-1634 on  main via ☕ v11.0.12 via 💎 v2.7.6 
❯
rholshausen commented 1 year ago

What JDK are you using? I was using 11.0.2

gedankennebel commented 1 year ago

17.0.4

rholshausen commented 1 year ago

I couldn't get 17.0.4, but I tried 17.0.5, and it worked ok, so that is not the issue

rholshausen commented 1 year ago

I have removed the @Optional from the PactPublish property, it seems to work the same without it. However, I can't replicate this issue, so I have no idea if that will fix it or not.

eloo commented 1 year ago

@rholshausen thanks for the investigation.. and together with your example project i have maybe found the issue.. but i really really don't know what the issue here is :D

we have the following plugin in our project which seems may to interfere with the latest changes to this plugin io.alcide.gradle-semantic-build-versioning

so to reproduce the issue you need to add the following to your example project

settings.gradle

/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'issue-1634'

buildscript {
    repositories {
        maven {
            url 'https://maven-central.tools.msi.audi.com'
        }
    }

    dependencies {
        classpath 'io.alcide:gradle-semantic-build-versioning:4.2.2'
    }
}

apply plugin: 'io.alcide.gradle-semantic-build-versioning'

semantic-build-versioning.gradle

the semantic-build-versioning.gradle can be empty.. but it must be available

maybe this helps to solve this issue

rholshausen commented 1 year ago

@eloo that looks like a different problem that the one originally reported. Adding that plugin causes Gradle to fail with java.lang.ClassCastException: class org.gradle.api.internal.project.DefaultProject_Decorated cannot be cast to class org.gradle.api.initialization.Settings, so it looks like it can't work with Gradle 7.5.1. I tried 6.5.8 too, and that also fails.

eloo commented 1 year ago

@rholshausen okay thats weird.. i'm using gradle 7.5 and i get exactly the error as reported in this issue.. i have not seen the cannot be cast... error..

Gradle 7.5 openjdk version "17.0.4" 2022-07-19

but the real question is what happen between 4.3.15 and 4.3.16 which causes such weird errors

rholshausen commented 1 year ago

You can check either the changelog or use GitHub to get all the differences between 4.3.15 and 4.3.16, but I expect it was this PR #1627

eloo commented 1 year ago

i'm not that familiar with gradle plugin development so i can't really see why this PR behaves likes this. But yes maybe https://github.com/pact-foundation/pact-jvm/pull/1627/files#diff-7b88de1074f577837d509b8f25ee577859c835364f2bad790a112f6a3435acf7R26 is only trying to fetch the

pactPublish {}

task on root level and not in

pact{
  publish {}
}
rholshausen commented 1 year ago

No, that is only a property on a task, and it is assigned when the task is registered. See https://github.com/pact-foundation/pact-jvm/blob/master/provider/gradle/src/main/groovy/au/com/dius/pact/provider/gradle/PactPlugin.groovy#L26 and it is meant to do the same as the fix above.

I have released a new version with the optional annotation removed, however, I have no idea if that will make a difference. More likely it will only change the error message.

What you can try do, fork the repo and change PactPlugin.groovy:26 to use project.pact.publish. You will need to build the Gradle plugin and install in to your local Maven repo, and then try use that version in your project.

rholshausen commented 1 year ago

Hmm, I wonder if the property having the same name as the task might be impacting things.

eloo commented 1 year ago

with the new version without optional i get a different error.. but its indicating the same.. the value is not set


A problem was found with the configuration of task ':pactPublish' (type 'PactPublishTask').
  - In plugin 'au.com.dius.pact' type 'au.com.dius.pact.provider.gradle.PactPublishTask' property 'pactPublish' doesn't have a configured value.

    Reason: This property isn't marked as optional and no value has been configured.

    Possible solutions:
      1. Assign a value to 'pactPublish'.
      2. Mark property 'pactPublish' as optional.

    Please refer to https://docs.gradle.org/7.5.1/userguide/validation_problems.html#value_not_set for more details about this problem.
eloo commented 1 year ago

So yes it looks like gradle is trying to resolve the property on root level and not inside the task configuration. but i really don't know why gradle is doing this

kevinbarbour commented 1 year ago

I am experiencing a similar issue to what @eloo posted above. Prior to version 4.3.16 we were using the following configuration:

pactPublish.dependsOn test

With the update to 4.3.16 and on 4.4.x I receive the following error whenever I try to run gradle pactPublish You must add a pact publish configuration to your build before you can use the pactPublish task

Trying on 4.5.0 I see the new error:

A problem was found with the configuration of task ':pactPublish' (type 'PactPublishTask').
  - In plugin 'au.com.dius.pact' type 'au.com.dius.pact.provider.gradle.PactPublishTask' property 'pactPublish' doesn't have a configured value.

    Reason: This property isn't marked as optional and no value has been configured.

    Possible solutions:
      1. Assign a value to 'pactPublish'.
      2. Mark property 'pactPublish' as optional.

    Please refer to https://docs.gradle.org/7.5.1/userguide/validation_problems.html#value_not_set for more details about this problem.

I tried using the workaround mentioned above, like so, but I still get the same error.

pactPublish {
    dependsOn test
    pactPublish = project.pact.publish
}

Is there a different way to specify a dependency that should be used in place of this? Prior to 4.3.16 it was all working as expected.

jiffle commented 1 year ago

@kevinbarbour The following seems to be working for me in the scenario you describe (Kotlin DSL): tasks.pactPublish { dependsOn(test) }

kingan379 commented 1 year ago

Any updates on this one? I'm also facing that issue with newer versions.

rholshausen commented 1 year ago

pactPublish.dependsOn test must come after the pact block.