Skip to content

Commit

Permalink
feat: add support for pending pacts with the Maven plugin #1033
Browse files Browse the repository at this point in the history
  • Loading branch information
Ronald Holshausen committed May 11, 2020
1 parent 7d33369 commit daac69f
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class GradleProviderInfo extends ProviderInfo {
brokerConfig.providerTags.findAll { !it.trim().empty }.empty)) {
throw new GradleScriptException(
'''
|No providerTags: To use the pending pacts feature, you need to provide the list of provider names for the provider application version that will be published with the verification results
|No providerTags: To use the pending pacts feature, you need to provide the list of provider names for the provider application version that will be published with the verification results.
|
|For instance:
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package au.com.dius.pact.provider.maven

import java.net.URL

data class EnablePending @JvmOverloads constructor(val providerTags: List<String> = emptyList())

/**
* Bean to configure a pact broker to query
*/
data class PactBroker @JvmOverloads constructor(
val url: URL? = null,
val tags: List<String>? = emptyList(),
val authentication: PactBrokerAuth? = null,
val serverId: String? = null
val serverId: String? = null,
var enablePending: EnablePending? = null
)

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package au.com.dius.pact.provider.maven

import au.com.dius.pact.core.pactbroker.ConsumerVersionSelector
import au.com.dius.pact.core.support.toUrl
import au.com.dius.pact.provider.ConsumerInfo
import au.com.dius.pact.provider.IConsumerInfo
Expand All @@ -8,6 +9,7 @@ import au.com.dius.pact.provider.IProviderVerifier
import au.com.dius.pact.provider.PactVerifierException
import au.com.dius.pact.provider.ProviderUtils
import au.com.dius.pact.provider.ProviderVerifier
import au.com.dius.pact.provider.VerificationResult
import au.com.dius.pact.provider.reporters.ReporterManager
import org.apache.maven.plugin.MojoFailureException
import org.apache.maven.plugins.annotations.Mojo
Expand Down Expand Up @@ -53,7 +55,6 @@ open class PactProviderMojo : PactBaseMojo() {
System.setProperty(property, value)
}

val failures = mutableMapOf<String, Any>()
val verifier = providerVerifier().let { verifier ->
verifier.projectHasProperty = Function { p: String -> this.propertyDefined(p) }
verifier.projectGetProperty = Function { p: String -> this.property(p) }
Expand Down Expand Up @@ -82,7 +83,7 @@ open class PactProviderMojo : PactBaseMojo() {
}

try {
serviceProviders.forEach { provider ->
val failures = serviceProviders.flatMap { provider ->
val consumers = mutableListOf<IConsumerInfo>()
consumers.addAll(provider.consumers)
if (provider.pactFileDirectory != null) {
Expand All @@ -109,12 +110,15 @@ open class PactProviderMojo : PactBaseMojo() {

provider.consumers = consumers

failures.putAll(verifier.verifyProvider(provider) as Map<String, Any>)
}
verifier.verifyProviderReturnResult(provider)
}.filterIsInstance<VerificationResult.Failed>()

if (failures.isNotEmpty()) {
verifier.displayFailures(failures)
throw MojoFailureException("There were ${failures.size} pact failures")
val nonPending = failures.filterNot { it.pending }
if (nonPending.isNotEmpty()) {
throw MojoFailureException("There were ${nonPending.sumBy { it.failures.size }} non-pending pact failures")
}
}
} finally {
verifier.finaliseReports()
Expand Down Expand Up @@ -146,12 +150,31 @@ open class PactProviderMojo : PactBaseMojo() {
options["authentication"] = listOf("basic", serverDetails.username, result.server.password)
}

if (pactBroker?.tags != null && pactBroker.tags.isNotEmpty()) {
pactBroker.tags.forEach { tag ->
consumers.addAll(provider.hasPactsFromPactBrokerWithTag(options, pactBrokerUrl.toString(), tag))
when {
pactBroker?.enablePending != null -> {
if (pactBroker.enablePending!!.providerTags.isEmpty()) {
throw MojoFailureException("""
|No providerTags: To use the pending pacts feature, you need to provide the list of provider names for the provider application version that will be published with the verification results.
|
|For instance, if you tag your provider with 'master':
|
|<enablePending>
| <providerTags>
| <tag>master</tag>
| </providerTags>
|</enablePending>
""".trimMargin())
}
val selectors = pactBroker.tags?.map { ConsumerVersionSelector(it, true) } ?: emptyList()
consumers.addAll(provider.hasPactsFromPactBrokerWithSelectors(options +
mapOf("enablePending" to true, "providerTags" to pactBroker.enablePending!!.providerTags),
pactBrokerUrl.toString(), selectors))
}
pactBroker?.tags != null && pactBroker.tags.isNotEmpty() -> {
val selectors = pactBroker.tags.map { ConsumerVersionSelector(it, true) }
consumers.addAll(provider.hasPactsFromPactBrokerWithSelectors(options, pactBrokerUrl.toString(), selectors))
}
} else {
consumers.addAll(provider.hasPactsFromPactBroker(options, pactBrokerUrl.toString()))
else -> consumers.addAll(provider.hasPactsFromPactBrokerWithSelectors(options, pactBrokerUrl.toString(), emptyList()))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package au.com.dius.pact.provider.maven

import au.com.dius.pact.core.pactbroker.ConsumerVersionSelector
import au.com.dius.pact.provider.ConsumerInfo
import au.com.dius.pact.provider.IProviderVerifier
import org.apache.maven.plugin.MojoFailureException
Expand Down Expand Up @@ -30,7 +31,8 @@ class PactProviderMojoSpec extends Specification {
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([:], 'http://broker:1234') >> [ new Consumer(name: 'test consumer') ]
1 * provider.hasPactsFromPactBrokerWithSelectors([:], 'http://broker:1234', []) >>
[ new Consumer(name: 'test consumer') ]
list.size() == 1
list[0].name == 'test consumer'
}
Expand All @@ -45,7 +47,7 @@ class PactProviderMojoSpec extends Specification {
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([:], 'http://broker:1234') >> [ new Consumer() ]
1 * provider.hasPactsFromPactBrokerWithSelectors([:], 'http://broker:1234', []) >> [ new Consumer() ]
list
}

Expand All @@ -59,7 +61,7 @@ class PactProviderMojoSpec extends Specification {
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([:], 'http://broker:1234') >> [ new Consumer() ]
1 * provider.hasPactsFromPactBrokerWithSelectors([:], 'http://broker:1234', []) >> [ new Consumer() ]
list
}

Expand All @@ -68,12 +70,13 @@ class PactProviderMojoSpec extends Specification {
def provider = Spy(new Provider('TestProvider', null as File, null as URL,
new PactBroker(new URL('http://broker:1234'), null, new PactBrokerAuth('basic', null, 'test', 'test'), null)))
def list = []
def map = [authentication: ['basic', 'test', 'test']]

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([authentication: ['basic', 'test', 'test']], 'http://broker:1234') >> [
1 * provider.hasPactsFromPactBrokerWithSelectors(map, 'http://broker:1234', []) >> [
new Consumer()
]
list
Expand All @@ -84,12 +87,13 @@ class PactProviderMojoSpec extends Specification {
def provider = Spy(new Provider('TestProvider', null as File, null as URL,
new PactBroker(new URL('http://broker:1234'), null, new PactBrokerAuth('bearer', 'test', null, null), null)))
def list = []
def map = [authentication: ['bearer', 'test']]

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([authentication: ['bearer', 'test']], 'http://broker:1234') >> [
1 * provider.hasPactsFromPactBrokerWithSelectors(map, 'http://broker:1234', []) >> [
new Consumer()
]
list
Expand All @@ -101,12 +105,13 @@ class PactProviderMojoSpec extends Specification {
new PactBroker(new URL('http://broker:1234'), null,
new PactBrokerAuth(null, 'test', null, null), null)))
def list = []
def map = [authentication: ['bearer', 'test']]

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBroker([authentication: ['bearer', 'test']], 'http://broker:1234') >> [
1 * provider.hasPactsFromPactBrokerWithSelectors(map, 'http://broker:1234', []) >> [
new Consumer()
]
list
Expand All @@ -117,14 +122,13 @@ class PactProviderMojoSpec extends Specification {
def provider = Spy(new Provider('TestProvider', null as File, null as URL,
new PactBroker(new URL('http://broker:1234'), ['1', '2', '3'], null, null)))
def list = []
def selectors = ['1', '2', '3'].collect { new ConsumerVersionSelector(it, true) }

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBrokerWithTag([:], 'http://broker:1234', '1') >> [new Consumer()]
1 * provider.hasPactsFromPactBrokerWithTag([:], 'http://broker:1234', '2') >> []
1 * provider.hasPactsFromPactBrokerWithTag([:], 'http://broker:1234', '3') >> []
1 * provider.hasPactsFromPactBrokerWithSelectors([:], 'http://broker:1234', selectors) >> [new Consumer()]
list.size() == 1
}

Expand All @@ -146,8 +150,8 @@ class PactProviderMojoSpec extends Specification {
then:
1 * settings.getServer('test-server') >> serverDetails
1 * decrypter.decrypt({ it.servers == [serverDetails] }) >> decryptResult
1 * provider.hasPactsFromPactBroker([authentication: ['basic', 'MavenTest', 'MavenPassword']],
'http://broker:1234') >> [
1 * provider.hasPactsFromPactBrokerWithSelectors([authentication: ['basic', 'MavenTest', 'MavenPassword']],
'http://broker:1234', []) >> [
new Consumer()
]
list
Expand All @@ -163,11 +167,42 @@ class PactProviderMojoSpec extends Specification {
mojo.loadPactsFromPactBroker(provider, list, [authentication: ['bearer', '1234']])

then:
1 * provider.hasPactsFromPactBroker([authentication: ['bearer', '1234']],
'http://broker:1235') >> [ new Consumer() ]
1 * provider.hasPactsFromPactBrokerWithSelectors([authentication: ['bearer', '1234']],
'http://broker:1235', []) >> [ new Consumer() ]
list
}

def 'configures pending pacts if the option is set'() {
given:
def provider = Spy(new Provider('TestProvider', null as File, null as URL,
new PactBroker(new URL('http://broker:1234'), ['1', '2', '3'], null, null,
new EnablePending(['master']))))
def list = []
def selectors = ['1', '2', '3'].collect { new ConsumerVersionSelector(it, true) }
def map = [enablePending: true, providerTags: ['master']]

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
1 * provider.hasPactsFromPactBrokerWithSelectors(map, 'http://broker:1234', selectors) >> [new Consumer()]
list.size() == 1
}

def 'throws an exception if pending pacts enabled and there are no provider tags'() {
given:
def provider = Spy(new Provider('TestProvider', null as File, null as URL,
new PactBroker(new URL('http://broker:1234'), ['1', '2', '3'], null, null,
new EnablePending([]))))
def list = []

when:
mojo.loadPactsFromPactBroker(provider, list, [:])

then:
thrown(MojoFailureException)
}

def 'load pacts from multiple directories'() {
given:
def dir1 = 'dir1' as File
Expand All @@ -176,7 +211,7 @@ class PactProviderMojoSpec extends Specification {
def provider = new Provider('TestProvider', dir3, null, null)
provider.pactFileDirectories = [dir1, dir2]
def verifier = Mock(IProviderVerifier) {
verifyProvider(provider) >> [:]
verifyProviderReturnResult(provider) >> []
}
mojo = Spy(PactProviderMojo) {
loadPactFiles(provider, _) >> []
Expand Down Expand Up @@ -221,7 +256,7 @@ class PactProviderMojoSpec extends Specification {
given:
def provider = new Provider('TestProvider', 'dir' as File, null, null)
def verifier = Mock(IProviderVerifier) {
verifyProvider(provider) >> [:]
verifyProviderReturnResult(provider) >> []
}
mojo = Spy(PactProviderMojo) {
loadPactFiles(provider, _) >> []
Expand All @@ -244,7 +279,7 @@ class PactProviderMojoSpec extends Specification {
given:
def provider = new Provider('TestProvider', 'dir' as File, null, null)
def verifier = Mock(IProviderVerifier) {
verifyProvider(provider) >> [:]
verifyProviderReturnResult(provider) >> []
}
mojo = Spy(PactProviderMojo) {
loadPactFiles(provider, _) >> []
Expand All @@ -269,7 +304,7 @@ class PactProviderMojoSpec extends Specification {
given:
def provider = new Provider('TestProvider', 'dir1' as File, null, null)
def verifier = Mock(IProviderVerifier) {
verifyProvider(provider) >> [:]
verifyProviderReturnResult(provider) >> []
}
mojo = Spy(PactProviderMojo) {
loadPactFiles(provider, _) >> []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import au.com.dius.pact.provider.IProviderVerifier
import au.com.dius.pact.provider.VerificationResult
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.isNotEmpty
import com.github.salomonbrys.kotson.jsonArray
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.obj
Expand Down Expand Up @@ -74,17 +75,21 @@ class JsonReporter(
}

override fun finaliseReport() {
if (reportFile.exists() && reportFile.length() > 0) {
val existingContents = JsonParser().parse(reportFile.readText())
if (providerName == existingContents["provider"].obj["name"].string) {
existingContents["metaData"] = jsonData["metaData"]
existingContents["execution"].array.addAll(jsonData["execution"].array)
reportFile.writeText(existingContents.toString())
} else {
reportFile.writeText(jsonData.toString())
if (jsonData.isNotEmpty()) {
when {
reportFile.exists() && reportFile.length() > 0 -> {
val existingContents = JsonParser.parseString(reportFile.readText())
if (existingContents.isJsonObject && existingContents.obj.has("provider") &&
providerName == existingContents["provider"].obj["name"].string) {
existingContents["metaData"] = jsonData["metaData"]
existingContents["execution"].array.addAll(jsonData["execution"].array)
reportFile.writeText(existingContents.toString())
} else {
reportFile.writeText(jsonData.toString())
}
}
else -> reportFile.writeText(jsonData.toString())
}
} else {
reportFile.writeText(jsonData.toString())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ class MarkdownReporter(
private var pw: PrintWriter? = null

override fun initialise(provider: IProviderInfo) {
if (pw != null) {
pw!!.close()
}

pw?.close()
reportDir!!.mkdirs()
reportFile = File(reportDir, provider.name + ext)
pw = PrintWriter(BufferedWriter(FileWriter(reportFile, true)))
Expand All @@ -65,7 +62,7 @@ class MarkdownReporter(
}

override fun finaliseReport() {
pw!!.close()
pw?.close()
}

override fun reportVerificationForConsumer(consumer: IConsumerInfo, provider: IProviderInfo, tag: String?) {
Expand Down

0 comments on commit daac69f

Please sign in to comment.