Skip to content

Commit

Permalink
Refactor plugin lazy configuration (#29)
Browse files Browse the repository at this point in the history
Description
===========

The plugin as it is now relies heavily on `convention mapping`, a
technique which is not part of the public gradle API. This patch removes
all usages of `convention mapping` and uses the [`Provider`] API instead.
As of this moment this API is still in _incubation_ phase but is a
better alternative aready. This patch also means a breaking change not
only because of internal API changes but also because the new API in the
form of usage was introduced with gradle > 4.7

Changes
=======

![IMPROVE] use [`Provider`] API
![REMOVE] convention mapping
![BREAK] support with gradle < 4.7

[`Provider`]:    https://docs.gradle.org/current/userguide/lazy_configuration.html
  • Loading branch information
Larusso authored Apr 15, 2019
1 parent 990ef8a commit 9be2cba
Show file tree
Hide file tree
Showing 14 changed files with 709 additions and 781 deletions.
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,21 @@ Tested with Oracle JDK8
| Gradle Version | Works |
| :------------- | :---------: |
| <= 2.13 | ![no] |
| 2.14 | ![yes] |
| 3.0 | ![yes] |
| 3.1 | ![yes] |
| 3.2 | ![yes] |
| 3.4 | ![yes] |
| 3.4.1 | ![yes] |
| 3.5 | ![yes] |
| 3.5.1 | ![yes] |
| 4.0 | ![yes] |
| 4.1 | ![yes] |
| 4.2 | ![yes] |
| 4.3 | ![yes] |
| 4.4 | ![yes] |
| 4.5 | ![yes] |
| 4.6 | ![yes] |
| 2.14 | ![no] |
| 3.0 | ![no] |
| 3.1 | ![no] |
| 3.2 | ![no] |
| 3.4 | ![no] |
| 3.4.1 | ![no] |
| 3.5 | ![no] |
| 3.5.1 | ![no] |
| 4.0 | ![no] |
| 4.1 | ![no] |
| 4.2 | ![no] |
| 4.3 | ![no] |
| 4.4 | ![no] |
| 4.5 | ![no] |
| 4.6 | ![no] |
| 4.7 | ![yes] |
| 4.8 | ![yes] |
| 4.9 | ![yes] |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package wooga.gradle.github

import spock.lang.Unroll

class GithubPluginExtensionIntegrationSpec extends IntegrationSpec {

def setup() {
buildFile << """
${applyPlugin(GithubPlugin)}
""".stripIndent()
}

enum PropertyLocation {
none, script, property, env

String reason() {
switch (this) {
case script:
return "value is provided in script"
case property:
return "value is provided in props"
case env:
return "value is set in env"
default:
return "no value was configured"
}
}
}

enum PropertySetType {
setter, setMethod, propertySet

String reason() {
switch (this) {
case setter:
return "value is provided with setter"
case setMethod:
return "value is with set method"
case propertySet:
return "value is set in property with set"
}
}
}

String envNameFromProperty(String property) {
"GITHUB_${property.replaceAll(/([A-Z])/, "_\$1").toUpperCase()}"
}

@Unroll(":#property returns '#testValue' if #reason")
def "extension property :#property returns '#testValue' if #reason"() {
given:
buildFile << """
task(custom) {
doLast {
def value = "not set"
if(github.${property}.present) {
value = github.${property}.get()
}
println("github.${property}: " + value)
}
}
"""

and: "a gradle.properties"
def propertiesFile = createFile("gradle.properties")

def escapedValue = (value instanceof String) ? escapedPath(value) : value

switch (location) {
case PropertyLocation.script:
buildFile << "github.${property} = ${escapedValue}"
break
case PropertyLocation.property:
propertiesFile << "github.${property} = ${escapedValue}"
break
case PropertyLocation.env:
environmentVariables.set(envNameFromProperty(property), "${value}")
break
default:
break
}

when: ""
def result = runTasks("custom")

then:
result.success
result.standardOutput.contains("github.${property}: ${testValue}")

where:
property | value | expectedValue | providedValue | location
"repositoryName" | "testUser/testRepo" | _ | "testUser/testRepo" | PropertyLocation.property
"repositoryName" | "'testUser/testRepo'" | 'testUser/testRepo' | "testUser/testRepo" | PropertyLocation.script
"repositoryName" | null | "not set" | null | PropertyLocation.none

"username" | "testUser" | _ | "testUser" | PropertyLocation.property
"username" | "'testUser'" | 'testUser' | "testUser" | PropertyLocation.script
"username" | null | "not set" | null | PropertyLocation.none

"password" | "testPass" | _ | "testPass" | PropertyLocation.property
"password" | "'testPass'" | 'testPass' | "testPass" | PropertyLocation.script
"password" | null | "not set" | null | PropertyLocation.none

"token" | "accessToken" | _ | "accessToken" | PropertyLocation.property
"token" | "'accessToken'" | 'accessToken' | "accessToken" | PropertyLocation.script
"token" | null | "not set" | null | PropertyLocation.none

"baseUrl" | "https://api.github.com" | 'not set' | "https://api.github.com" | PropertyLocation.property
"baseUrl" | "'https://api.github.com'" | 'https://api.github.com' | "https://api.github.com" | PropertyLocation.script
"baseUrl" | null | "not set" | null | PropertyLocation.none

testValue = (expectedValue == _) ? value : expectedValue
reason = location.reason() + ((location == PropertyLocation.none) ? "" : " with '$providedValue'")
}

@Unroll
def "can set #property with #type"() {
given:
buildFile << """
task(custom) {
doLast {
def value = "not set"
if(github.${property}.present) {
value = github.${property}.get()
}
println("github.${property}: " + value)
}
}
"""

def escapedValue = (value instanceof String) ? escapedPath(value) : value

switch (type) {
case PropertySetType.setter:
buildFile << "github.${property} = ${escapedValue}"
break
case PropertySetType.setMethod:
buildFile << "github.${property} ${escapedValue}"
break
case PropertySetType.propertySet:
buildFile << "github.${property}.set(${escapedValue})"
break
}

when: ""
def result = runTasks("custom")

then:
result.success
result.standardOutput.contains("github.${property}: ${testValue}")

where:
property | value | expectedValue | type
"repositoryName" | "'testUser/testRepo'" | "testUser/testRepo" | PropertySetType.setter
"repositoryName" | "'testUser/testRepo'" | "testUser/testRepo" | PropertySetType.setMethod
"repositoryName" | "'testUser/testRepo'" | "testUser/testRepo" | PropertySetType.propertySet

"username" | "'testUser'" | "testUser" | PropertySetType.setter
"username" | "'testUser'" | "testUser" | PropertySetType.setMethod
"username" | "'testUser'" | "testUser" | PropertySetType.propertySet

"password" | "'testPass'" | "testPass" | PropertySetType.setter
"password" | "'testPass'" | "testPass" | PropertySetType.setMethod
"password" | "'testPass'" | "testPass" | PropertySetType.propertySet

"token" | "'accessToken'" | "accessToken" | PropertySetType.setter
"token" | "'accessToken'" | "accessToken" | PropertySetType.setMethod
"token" | "'accessToken'" | "accessToken" | PropertySetType.propertySet

"baseUrl" | "'https://api.github.com'" | "https://api.github.com" | PropertySetType.setter
"baseUrl" | "'https://api.github.com'" | "https://api.github.com" | PropertySetType.setMethod
"baseUrl" | "'https://api.github.com'" | "https://api.github.com" | PropertySetType.propertySet

testValue = (expectedValue == _) ? value : expectedValue
}

def "validates repoName property before set"() {
given: ""
buildFile << """
github.repositoryName = "${repositoryName}"
""".stripIndent()

when:
def result = runTasks("tasks")

then:
result.success == (expectedError == null)
if(!result.success) {
outputContains(result, expectedError)
}

where:
repositoryName | expectedError
'some value' | "Repository value 'some value' is not a valid github repository name. Expecting `owner/repo`"
}
}
Loading

0 comments on commit 9be2cba

Please sign in to comment.