Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements #325 rejectVersionIf { ... } #340

Merged
merged 12 commits into from
Sep 10, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 92 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,48 +85,112 @@ The strategy can be specified either on the task or as a system property for ad
```groovy
gradle dependencyUpdates -Drevision=release
```


The latest versions can be further filtered using [Component Selection Rules][component_selection_rules].
The current version of a component can be retrieved with `currentVersion` property. For example, to
disallow release candidates as upgradable versions from stable versions, a selection rule could be
defined as:
To further define which version to accept, you need to define what means an unstable version. Sadly, there are
no agreed standard on this, but this is a good starting point:

<details open>
<summary>Groovy</summary>

```groovy
dependencyUpdates.resolutionStrategy {
componentSelection { rules ->
rules.all { ComponentSelection selection ->
def isNonStable = { String version ->
['alpha', 'beta', 'rc', 'cr', 'm', 'preview', 'b', 'ea'].any { qualifier ->
version ==~ /(?i).*[.-]$qualifier[.\d-+]*/
}
}
def isNonStable = { String version ->
def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) }
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
def regex = /^[0-9,.v-]+$/
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
return !stableKeyword && !(version ==~ /^[0-9,.v-]+$/)
}
```

if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
selection.reject('Release candidate')
}
}
</details>
<details>
<summary>Kotlin</summary>

```kotlin
fun isNonStable(version: String): Boolean {
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) }
val regex = "^[0-9,.v-]+$".toRegex()
val isStable = stableKeyword || regex.matches(version)
return isStable.not()
}
```

</details>

You can then configure [Component Selection Rules][component_selection_rules].
The current version of a component can be retrieved with the `currentVersion` property.
You can either use the simplified syntax `rejectVersionIf { ... }` or configure a complete resolution strategy.


<details open>
<summary>Groovy</summary>

```groovy
dependencyUpdates {
// Example 1: reject all non stable versions
rejectVersionIf { selection ->
isNonStable(candidate.version)
}

// Example 2: disallow release candidates as upgradable versions from stable versions
rejectVersionIf { selection ->
isNonStable(candidate.version) && !isNonStable(currentVersion)
}

// Example 3: using the full syntax
resolutionStrategy {
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
componentSelection { rules ->
rules.all { ComponentSelection selection ->
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
selection.reject('Release candidate')
}
}
}
}
}
```

If using Gradle's [kotlin-dsl][kotlin_dsl], you could configure the `dependencyUpdates` like this:
</details>
<details>
<summary>Kotlin</summary>

```kotlin
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask

tasks.named<DependencyUpdatesTask>("dependencyUpdates") {
resolutionStrategy {
componentSelection {
all {
fun isNonStable(version: String) = listOf("alpha", "beta", "rc", "cr", "m", "preview", "b", "ea").any { qualifier ->
version.matches(Regex("(?i).*[.-]$qualifier[.\\d-+]*"))
}
if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
reject("Release candidate")
tasks.withType<DependencyUpdatesTask> {
// Example 1: reject all non stable versions
rejectVersionIf { selection ->
isNonStable(selection.candidate.version)
}

// Example 2: disallow release candidates as upgradable versions from stable versions
rejectVersionIf { selection ->
isNonStable(selection.candidate.version) && !isNonStable(selection.currentVersion)
}

// Example 3: using the full syntax
resolutionStrategy {
componentSelection {
all {
if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
reject("Release candidate")
}
}
}
}
}
}
}
```

</details>

#### Kotlin DSL

If using Gradle's [kotlin-dsl][kotlin_dsl], you could configure the `dependencyUpdates` like this:

```kotlin
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask

tasks.withType<DependencyUpdatesTask> {

// optional parameters
checkForGradleUpdate = true
outputFormatter = "json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
package com.github.benmanes.gradle.versions.updates

import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentFilter
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionRulesWithCurrent
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ResolutionStrategyWithCurrent
import groovy.transform.TypeChecked
import org.gradle.api.Action
Expand Down Expand Up @@ -91,6 +94,18 @@ class DependencyUpdatesTask extends DefaultTask {
this.resolutionStrategy = null
}

void rejectVersionIf(final ComponentFilter filter) {
resolutionStrategy { ResolutionStrategyWithCurrent strategy ->
strategy.componentSelection { ComponentSelectionRulesWithCurrent selection ->
selection.all { ComponentSelectionWithCurrent current ->
if (filter.reject(current)) {
current.reject("Rejected by rejectVersionIf ")
}
}
}
}
}

/** Returns the resolution revision level. */
String revisionLevel() { System.properties['revision'] ?: revision }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.github.benmanes.gradle.versions.updates.resolutionstrategy

interface ComponentFilter {
jmfayard marked this conversation as resolved.
Show resolved Hide resolved

boolean reject(ComponentSelectionWithCurrent candidate)

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,48 @@
package com.github.benmanes.gradle.versions.updates.resolutionstrategy

import groovy.transform.TupleConstructor
import com.thoughtworks.xstream.mapper.Mapper
import org.gradle.api.artifacts.ComponentMetadata
import org.gradle.api.artifacts.ComponentSelection
import org.gradle.api.artifacts.component.ModuleComponentIdentifier

@TupleConstructor(includeFields=true)
class ComponentSelectionWithCurrent {
import javax.annotation.Nullable

final String currentVersion
class ComponentSelectionWithCurrent implements ComponentSelection {

ComponentSelectionWithCurrent(String currentVersion, ComponentSelection delegate) {
this.currentVersion = currentVersion
this.delegate = delegate
}

@Delegate
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
final String currentVersion
private final ComponentSelection delegate

ModuleComponentIdentifier getCandidate() {
return delegate.candidate
}

@Nullable
ComponentMetadata getMetadata() {
return delegate.metadata
}

def <T> T getDescriptor(Class<T> descriptorClass) {
return delegate.getDescriptor(descriptorClass)
}

void reject(String reason) {
delegate.reject(reason)
}


@Override
public String toString() {
jmfayard marked this conversation as resolved.
Show resolved Hide resolved
final StringBuffer sb = new StringBuffer("ComponentSelectionWithCurrent{");
sb.append("group=").append(getCandidate().group);
sb.append(", module=").append(getCandidate().module);
sb.append(", version=").append(getCandidate().version)
sb.append(", currentVersion='").append(currentVersion).append('\'');
sb.append('}');
return sb.toString();
}
}