Skip to content

Commit

Permalink
Add support for providerVersionBranches pact-foundation#1554
Browse files Browse the repository at this point in the history
  • Loading branch information
TGNThump committed May 19, 2022
1 parent 36788ed commit 98be066
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ interface IPactBrokerClient {
providerName: String,
selectors: List<ConsumerVersionSelector>,
providerTags: List<String> = emptyList(),
providerBranches: List<String> = emptyList(),
enablePending: Boolean = false,
includeWipPactsSince: String?
): Result<List<PactBrokerResult>, Exception>
Expand Down Expand Up @@ -305,12 +306,14 @@ open class PactBrokerClient(
providerName: String,
selectors: List<ConsumerVersionSelector>,
providerTags: List<String>,
providerBranches: List<String>,
enablePending: Boolean,
includeWipPactsSince: String?
): Result<List<PactBrokerResult>, Exception> {
val halClient = when (val navigateResult = handleWith<IHalClient> { newHalClient().navigate() }) {
is Err<Exception> -> return navigateResult
is Ok<IHalClient> -> navigateResult.value
else -> throw RuntimeException(navigateResult.toString())
}
val pactsForVerification = when {
halClient.linkUrl(PROVIDER_PACTS_FOR_VERIFICATION) != null -> PROVIDER_PACTS_FOR_VERIFICATION
Expand All @@ -320,9 +323,9 @@ open class PactBrokerClient(
return if (pactsForVerification != null) {
val selectorsRawJson = System.getProperty("pactbroker.consumerversionselectors.rawjson")
if(!selectorsRawJson.isNullOrBlank()){
fetchPactsUsingNewEndpointRaw(selectorsRawJson, enablePending, providerTags, includeWipPactsSince, halClient, pactsForVerification, providerName)
fetchPactsUsingNewEndpointRaw(selectorsRawJson, enablePending, providerTags, providerBranches, includeWipPactsSince, halClient, pactsForVerification, providerName)
} else {
fetchPactsUsingNewEndpointTyped(selectors, enablePending, providerTags, includeWipPactsSince, halClient, pactsForVerification, providerName)
fetchPactsUsingNewEndpointTyped(selectors, enablePending, providerTags, providerBranches, includeWipPactsSince, halClient, pactsForVerification, providerName)
}
} else {
handleWith {
Expand All @@ -347,31 +350,34 @@ open class PactBrokerClient(
selectorsTyped: List<ConsumerVersionSelector>,
enablePending: Boolean,
providerTags: List<String>,
providerBranches: List<String>,
includeWipPactsSince: String?,
halClient: IHalClient,
pactsForVerification: String,
providerName: String
): Result<List<PactBrokerResult>, Exception> {
val selectorsJson = jsonArray(selectorsTyped.map { it.toJson() })
return fetchPactsUsingNewEndpoint(selectorsJson, enablePending, providerTags, includeWipPactsSince, halClient, pactsForVerification, providerName)
return fetchPactsUsingNewEndpoint(selectorsJson, enablePending, providerTags, providerBranches, includeWipPactsSince, halClient, pactsForVerification, providerName)
}

private fun fetchPactsUsingNewEndpointRaw(
selectorsRaw: String,
enablePending: Boolean,
providerTags: List<String>,
providerBranches: List<String>,
includeWipPactsSince: String?,
halClient: IHalClient,
pactsForVerification: String,
providerName: String
): Result<List<PactBrokerResult>, Exception> {
return fetchPactsUsingNewEndpoint(JsonParser.parseString(selectorsRaw), enablePending, providerTags, includeWipPactsSince, halClient, pactsForVerification, providerName)
return fetchPactsUsingNewEndpoint(JsonParser.parseString(selectorsRaw), enablePending, providerTags, providerBranches, includeWipPactsSince, halClient, pactsForVerification, providerName)
}

private fun fetchPactsUsingNewEndpoint(
selectorsJson: JsonValue,
enablePending: Boolean,
providerTags: List<String>,
providerBranches: List<String>,
includeWipPactsSince: String?,
halClient: IHalClient,
pactsForVerification: String,
Expand All @@ -385,6 +391,7 @@ open class PactBrokerClient(
body["includePendingStatus"] = enablePending
if (enablePending) {
body["providerVersionTags"] = jsonArray(providerTags)
body["providerVersionBranches"] = jsonArray(providerBranches)
if (includeWipPactsSince.isNotEmpty()) {
body["includeWipPactsSince"] = includeWipPactsSince
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ class PactBrokerClientSpec extends Specification {
}
def selectors = [ new ConsumerVersionSelector('DEV', true, null, null) ]
def json = '{"consumerVersionSelectors":[{"latest":true,"tag":"DEV"}],"includePendingStatus":true,' +
'"includeWipPactsSince":"2020-24-06","providerVersionTags":[]}'
'"includeWipPactsSince":"2020-24-06","providerVersionTags":[],"providerVersionBranches":[]}'
def jsonResult = JsonParser.INSTANCE.parseString('''
{
"_embedded": {
Expand Down
3 changes: 2 additions & 1 deletion docs/system-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ Theses are all the system properties used by Pact-JVM
| pactbroker.auth.password | Verification (JUnit, JUnit 5) | string value | n | y | n | Password to use when fetching pacts to verify. |
| pactbroker.auth.token | Verification (JUnit, JUnit 5) | string value | n | y | n | Bearer token to use when fetching pacts to verify. |
| pactbroker.enableInsecureTls | Verification (JUnit, JUnit 5) | true, false | n | y | n | Enabling insecure TLS by setting this to true will disable hostname validation and trust all certificates. Use with caution. |
| pactbroker.enablePending | Verification (JUnit, JUnit 5) | true, false | n | y | n | If the pending pacts feature should be enabled when fetching pacts to verify. When this is set to true, the provider tags property also needs to be set (pactbroker.providerTags). |
| pactbroker.enablePending | Verification (JUnit, JUnit 5) | true, false | n | y | n | If the pending pacts feature should be enabled when fetching pacts to verify. When this is set to true, the provider tags or provider branches property also needs to be set (pactbroker.providerTags or pactbroker.providerBranches). |
| pactbroker.providerTags | Verification (JUnit, JUnit 5) | tag names | y | y | n | Provider Tags to use to evaluate pending pacts when fetching pacts to verify. |
| pactbroker.providerBranches | Verification (JUnit, JUnit 5) | branch names | y | y | n | Provider Branches to use to evaluate pending pacts when fetching pacts to verify. |
| pactbroker.includeWipPactsSince | Verification (JUnit, JUnit 5) | ISO date (YYYY-MM-DD) | n | y | n | The earliest date WIP pacts should be included (ex: YYYY-MM-DD). If no date is provided, WIP pacts will not be included. |
| pact.verification.reportDir | Verification (JUnit, JUnit 5) | Directory name | n | y | n | Sets the directory to write any configured verification reports to. |
| pactfolder.path | Verification (JUnit, JUnit 5) | Directory name | n | y | n | Directory to fetch pacts from when using the folder loader. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.github.michaelbull.result.Err
import com.github.michaelbull.result.Ok
import spock.lang.Specification

@SuppressWarnings(['UnnecessaryGetter', 'LineLength', 'NestedBlockDepth', 'AbcMetric', 'MethodSize', 'ClassSize'])
@SuppressWarnings(['GroovyAssignabilityCheck','UnnecessaryGetter', 'LineLength', 'NestedBlockDepth', 'AbcMetric', 'MethodSize', 'ClassSize'])
class PactBrokerClientPactSpec extends Specification {

private PactBrokerClient pactBrokerClient
Expand Down Expand Up @@ -917,7 +917,7 @@ class PactBrokerClientPactSpec extends Specification {
def result = pactBroker.runTest { server, context ->
def consumerPacts = pactBrokerClient.fetchConsumersWithSelectors('Activity Service', [
new ConsumerVersionSelector('test', true, null, null)
], [], false, '')
], [], [], false, '')
assert consumerPacts instanceof Ok
assert consumerPacts.value.size == 2
assert !consumerPacts.value[0].pending
Expand Down Expand Up @@ -960,7 +960,8 @@ class PactBrokerClientPactSpec extends Specification {
latest true
}
])
providerVersionTags(['master'])
providerVersionTags(['tag'])
providerVersionBranches(['master'])
includePendingStatus true
}
willRespondWith(status: 200)
Expand Down Expand Up @@ -1030,7 +1031,7 @@ class PactBrokerClientPactSpec extends Specification {
def result = pactBroker.runTest { server, context ->
def consumerPacts = pactBrokerClient.fetchConsumersWithSelectors('Activity Service', [
new ConsumerVersionSelector('test', true, null, null)
], ['master'], true, '')
], ['tag'], ['master'], true, '')
assert consumerPacts instanceof Ok
assert consumerPacts.value.size == 2
assert !consumerPacts.value[0].pending
Expand Down Expand Up @@ -1073,7 +1074,8 @@ class PactBrokerClientPactSpec extends Specification {
latest true
}
])
providerVersionTags(['master'])
providerVersionTags(['tag'])
providerVersionBranches(['master'])
includePendingStatus true
includeWipPactsSince '2020-06-24'
}
Expand Down Expand Up @@ -1154,7 +1156,7 @@ class PactBrokerClientPactSpec extends Specification {
def result = pactBroker.runTest { server, context ->
def consumerPacts = pactBrokerClient.fetchConsumersWithSelectors('Activity Service', [
new ConsumerVersionSelector('test', true, null, null)
], ['master'], true, '2020-06-24')
], ['tag'], ['master'], true, '2020-06-24')
assert consumerPacts instanceof Ok
assert consumerPacts.value.size == 2
assert !consumerPacts.value[0].wip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,11 @@ open class GradleProviderInfo(name: String, val project: Project) : ProviderInfo

val pending = brokerConfig!!.enablePending ?: false
if (pending && (brokerConfig!!.providerTags.isNullOrEmpty() ||
brokerConfig!!.providerTags!!.any { it.trim().isEmpty() })) {
brokerConfig!!.providerTags!!.any { it.trim().isEmpty() }) && (brokerConfig!!.providerBranches.isNullOrEmpty() ||
brokerConfig!!.providerBranches!!.any { it.trim().isEmpty() })) {
throw 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 or providerBranches: 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 @@ -8,7 +8,8 @@ import au.com.dius.pact.core.pactbroker.ConsumerVersionSelector
data class PactBrokerConsumerConfig @JvmOverloads constructor(
var selectors: List<ConsumerVersionSelector>? = listOf(),
var enablePending: Boolean? = false,
var providerTags: List<String>? = listOf()
var providerTags: List<String>? = listOf(),
var providerBranches: List<String>? = listOf()
) {
companion object {
@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ class GradleProviderInfoSpec extends Specification {
selectors = latestTags('test')
enablePending = true
providerTags = ['master']
providerBranches = ['master']
}

then:
provider.brokerConfig == new PactBrokerConsumerConfig([new ConsumerVersionSelector('test', true, null, null)],
true, ['master'])
true, ['master'], ['master'])
}

@Unroll
def 'fromPactBroker throws an exception if pending pacts is enabled but there are no provider tags'() {
def 'fromPactBroker throws an exception if pending pacts is enabled but there are no provider tags or provider branches'() {
given:
def provider = new GradleProviderInfo('provider', Mock(Project))

Expand All @@ -49,16 +50,18 @@ class GradleProviderInfoSpec extends Specification {
selectors = latestTags('test')
enablePending = true
providerTags = tags
providerBranches = branches
}

then:
def ex = thrown(GradleScriptException)
ex.message.trim().startsWith('No providerTags: To use the pending pacts feature, you need to provide the list of ' +
ex.message.trim().startsWith('No providerTags or providerBranches: To use the pending pacts feature, you need to provide the list of ' +
'provider names')

where:

tags << [null, [], ['']]
branches << [null, [], ['']]
}

def 'supports specifying a fallback tag'() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ PactBrokerAuth authentication() default @PactBrokerAuth(username = "${pactbroker
*/
String[] providerTags() default "${pactbroker.providerTags:}";

/**
* Provider Branches to use to evaluate pending pacts
*/
String[] providerBranches() default "${pactbroker.providerBranches:}";

/**
* The earliest date WIP pacts should be included (ex: YYYY-MM-DD). If no date is provided, WIP pacts will not be
* included.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ data class PactBrokerOptions @JvmOverloads constructor(
val enablePending: Boolean = false,

/**
* Provider tags. Required if pending pacts are enabled
* Provider tags. Either this or providerBranches if pending pacts are enabled
*/
val providerTags: List<String> = listOf(),

/**
* Provider branches. Either this or providerTags if pending pacts are enabled
*/
val providerBranches: List<String> = listOf(),

/**
* Only include WIP pacts since the provided date. Dates need to be in ISO format (YYYY-MM-DD).
* See https://docs.pact.io/pact_broker/advanced_topics/wip_pacts/
Expand Down
14 changes: 10 additions & 4 deletions provider/src/main/kotlin/au/com/dius/pact/provider/ProviderInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ open class ProviderInfo @JvmOverloads constructor (
} else {
emptyList()
}
val providerBranches = if (enablePending) {
options["providerBranches"] as List<String>?
} else {
emptyList()
}
val includePactsSince = Utils.lookupInMap(options, "includeWipPactsSince", String::class.java, "")
val pactBrokerOptions = PactBrokerOptions(enablePending, providerTags.orEmpty(), includePactsSince, false,
val pactBrokerOptions = PactBrokerOptions(enablePending, providerTags.orEmpty(), providerBranches.orEmpty(), includePactsSince, false,
PactBrokerOptions.parseAuthSettings(options))

return hasPactsFromPactBrokerWithSelectors(pactBrokerUrl, selectors, pactBrokerOptions)
Expand All @@ -90,14 +95,15 @@ open class ProviderInfo @JvmOverloads constructor (
selectors: List<ConsumerVersionSelector>,
options: PactBrokerOptions
): List<ConsumerInfo> {
if (options.enablePending && options.providerTags.isEmpty()) {
throw RuntimeException("No providerTags: To use the pending pacts feature, you need to provide the list of " +
if (options.enablePending && options.providerTags.isEmpty() && options.providerBranches.isEmpty()) {
throw RuntimeException("No providerTags or providerBranches: 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")
}
val client = pactBrokerClient(pactBrokerUrl, options)
val consumersFromBroker = client.fetchConsumersWithSelectors(name, selectors, options.providerTags,
val consumersFromBroker = client.fetchConsumersWithSelectors(name, selectors, options.providerTags, options.providerBranches,
options.enablePending, options.includeWipPactsSince)
.map { results -> results.map { ConsumerInfo.from(it) } }

return when (consumersFromBroker) {
is Ok<List<ConsumerInfo>> -> {
val list = consumersFromBroker.value
Expand Down
Loading

0 comments on commit 98be066

Please sign in to comment.