Gradle plugin configuration in kotlin script - gradle

I'm trying to configure Kotlin net.researchgate.release plugin. I have following setup (kts script):
plugins {
...
id("net.researchgate.release") version "2.8.1"
}
In the same script I'm trying to configure plugin:
release {
svn {
username = "some"
password = System.getenv("SOME")
pinExternals = false
}
}
During build I've got:
Unresolved reference: svn
How would I configure this plugin?

That plugin does not support the Kotlin DSL. The reason is that it uses Groovy meta-programming constructs to configure the nested extensions, and you are not using Groovy.
There are two open issues for this problem: 281 and 288. The former suggests a few different work-arounds, including configuring the SVN adapter like this:
release {
with (propertyMissing("svn") as SvnAdapter.SvnConfig) {
username = "some"
// etc...
}
}

Related

How to centralize Gradle build settings?

Say I'm using the palantir/gradle-git-version Gradle plugin, and have the following code in build.gradle.kts to determine the project version:
// If release branch, return after incrementing patch version.
// Else, return $lastTag-SNAPSHOT.
val projectVersion: String by lazy {
val versionDetails: groovy.lang.Closure<VersionDetails> by extra
with(versionDetails()) {
if (!lastTag.matches("^(?:(?:\\d+\\.){2}\\d+)\$".toRegex())) {
throw GradleException("Tag '$lastTag' doesn't match 'MAJOR.MINOR.PATCH' format")
}
// If it detached state, get branch name from GitLab CI env var
val branch = branchName ?: System.getenv("CI_COMMIT_REF_NAME")
if (branch?.startsWith("release/") == true) {
val tokens = lastTag.split('.')
"${tokens[0]}.${tokens[1]}.${tokens[2].toInt() + commitDistance}"
} else "$lastTag-SNAPSHOT"
}
}
This works, but the code is duplicated across all the projects, which is difficult to maintain except for a very small number of projects.
This is just one example, the same applies for other Gradle tasks that assume certain conventions within the company/team, like creating a Dockerfile.
What is a good way to centralize such code so that all projects can use them? Note that code like this don't usually stand on their own, but rely on Gradle plugins.
What is a good way to centralize such code so that all projects can use them?
You'll want to create a custom Gradle plugin to hold your project's conventions.
If you have Gradle installed locally, you can use the Build Init Plugin to create a skeleton plugin project. With Gradle installed locally, simple run gradle init in a new project directory and follow the prompts to create the plugin project.
As a concrete example (assuming you generated a plugin project as mentioned earlier), to apply your versioning conventions, a plugin could be:
// Plugin's build.gradle.kts
dependencies {
// Add dependency for plugin, GAV can be found on the plugins page:
// https://plugins.gradle.org/plugin/com.palantir.git-version
implementation("com.palantir.gradle.gitversion:gradle-git-version:0.12.3")
}
Then a versioning conventions plugin could be:
import com.palantir.gradle.gitversion.VersionDetails
import groovy.lang.Closure
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
class VersioningConventionsPlugin : Plugin<Project> {
override fun apply(project: Project) {
// Apply plugin to project as you would in the main Gradle build file.
project.pluginManager.apply("com.palantir.git-version")
// Configure version conventions
val projectVersion: String by lazy {
// Gradle generates some Kotlin DSL code on the fly, in a plugin implementation we don't have that.
// So we must convert the DSL to the Gradle API.
val versionDetails: Closure<VersionDetails> = project.extensions.extraProperties.get("versionDetails") as Closure<VersionDetails>
with(versionDetails.call()) {
if (!lastTag.matches("^(?:(?:\\d+\\.){2}\\d+)\$".toRegex())) {
throw GradleException("Tag '$lastTag' doesn't match 'MAJOR.MINOR.PATCH' format")
}
val branch = branchName ?: System.getenv("CI_COMMIT_REF_NAME")
if (branch?.startsWith("release/") == true) {
val tokens = lastTag.split('.')
"${tokens[0]}.${tokens[1]}.${tokens[2].toInt() + commitDistance}"
} else "$lastTag-SNAPSHOT"
}
}
// Set the version as an extra property on the project
// Accessible via extra["projectVersion"]
project.extensions.extraProperties["projectVersion"] = projectVersion
}
}
I gave a Kotlin example since your sample used the Kotlin DSL. Once you've finished development work of your conventions plugin, then you would publish to a repository such as the Gradle Plugins repository. If it's an internal company plugin, then publish it to an internal Nexus Repository or similar.
Follow the docs for the maven-publish plugin for more details on publishing. Gradle plugins can be published like any other artifact/JAR.

Gradle warning: "The libsDir method has been deprecated."

I'm using Gradle 5.6.1 with a build.gradle file that publishes a distribution to Artifactory.
When I run the publish task, I receive a warning:
$ gradle publishMyPublicationToRemoteArtifactoryRepository
Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Using the suggested flag reveals The libsDir method has been deprecated.:
$ gradle publishMyPublicationToRemoteArtifactoryRepository --warning-mode all
> Configure project :
The libsDir method has been deprecated. This is scheduled to be removed in Gradle 6.0.
The relevant section of build.gradle is below:
distributions {
main {
baseName = archivesBaseName
contents {
from libsDir
}
}
}
How do I correct libsDir so that the warning is resolved?
Referencing the libsDir directly usually indicates bad design and often can be avoided with a different approach to the problem.
However, for those who are looking for a direct replacement and are using Gradle 6.0 or higher, it is libsDirectory.
The default value with java plugin is ${project.buildDir}/${project.libsDirName}, you may also use it as a replacement if that's what you want.
Please see https://docs.gradle.org/current/dsl/org.gradle.api.plugins.BasePluginConvention.html#org.gradle.api.plugins.BasePluginConvention:libsDir
There is a discussion on GitHub where the following alternative is suggested:
distributions {
main {
baseName = archivesBaseName
contents {
from "${buildDir}/${distsDirName}"
}
}
}

Gradle global plugin repository with Kotlin DSL

I am new to Gradle, but need to build an opensource project that uses it, from my machine on the corporate network. The project has recently moved to Kotlin DSL, so some plugins are required.
I need to use our corporate Nexus server to fetch the plugin dependencies, and I would like to set this globally, because I don't want to have to modify the settings.gradle.kts in all the projects (I've tried this and it works)
If I want to do this globally, I understand from https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_management that I need to have an init.gradle.kts file in my USER_HOME/.gradle directory. That's what I did, here's the content of the file :
settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
mavenLocal()
maven("https://my_corporate_nexus/")
}
}
}
But when I then trigger my build, here's what I get :
* What went wrong:
Script compilation errors:
Line 1: settingsEvaluated { settings ->
^ None of the following functions can be called with the arguments supplied:
public open fun settingsEvaluated(p0: Closure<(raw) Any!>): Unit defined in Init_gradle
public open fun settingsEvaluated(p0: Action<in Settings!>): Unit defined in Init_gradle
public final fun settingsEvaluated(p0: Settings!.() -> Unit): Unit defined in Init_gradle
Below are my version details, as provided by gradle -v :
Gradle 4.9
Kotlin DSL: 0.18.4
Kotlin: 1.2.41
Groovy: 2.4.12
So it looks likes there's something obvious I am missing.
Any idea what it could be ?
it seems to work with :
settingsEvaluated {
settings.pluginManagement {
repositories {
mavenLocal()
maven("https://my_corporate_nexus/")
}
}
}
no settings -> .
I am not sure whether documentation is wrong or if my setup is specific though...

is there any Gradle inbuilt feature equivalent to Maven's “copy-dependencies” without writing gradle task..?

looks like gradle still not mature when compared to maven.many handy features not available in gradle.
is there any Gradle inbuilt feature equivalent to Maven's “copy-dependencies” without writing gradle task..?
Please check installDist task of distribution plugin.
You have to write code like this:
distributions {
main {
baseName = 'someName'
contents {
from { 'src/readme' }
into { '../../' } // <----- change destination here
}
}
}
This plugin will create distribution installation, which will also copy all runtime dependencies.

Unable to resolve a plugin using the new plugin mechanism in Gradle

While trying to upgrade some of our scripts to Gradle 4.0.1 on of the plugins we are using is failing and I thought of fixing that plugin first. The plugin is a third party open source project.
So I have cloned the project and tried to compile it. However it fails with following message:
c:\source\gradle-xld-plugin>gradlew build
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\source\gradle-xld-plugin\build.gradle' line: 2
* What went wrong:
Plugin [id: 'com.gradle.plugin-publish', version: '0.9.7'] was not found in
any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- maven(https://artifactory/java-v) (Could not resolve plugin artifact 'com.gradle.plugin-publish:com.gradle.plugin-publish.gradle.plugin:0.9.7')
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --
debug option to get more log output.
BUILD FAILED in 0s
The build.gradle script for the plugin starts like this:
plugins {
id "com.gradle.plugin-publish" version "0.9.7"
id "com.github.hierynomus.license" version "0.11.0"
id 'nebula.nebula-release' version '4.0.1'
id "com.jfrog.bintray" version "1.7.3"
}
In addition to this the company policy dictates we have to go through an internal artifactory server, so following has been added to the settings.gradle file:
pluginManagement {
repositories {
maven {
url "https://artifactory/java-v"
}
}
}
The jar file exists at following location: https://artifactory/java-v/com/gradle/publish/plugin-publish-plugin/0.9.7/plugin-publish-plugin-0.9.7.jar
but when I look at the error message I am a little puzzled that it says that it cannot find com.gradle.plugin-publish:com.gradle.plugin-publish.gradle.plugin:0.9.7.
It seems to have suffixed the id with .gradle.plugin.
Does anyone know whether I am looking at the wrong location or how come it is suffixing the id with .gradle.plugin. And shouldn't it look at a location that has the GAV like this: com.gradle.plugin-publish:com.gradle.plugin-publish:0.9.7?
And does anyone know about how the resolution mechanism for the new plugin mechanism in Gradle works.
Thanks in advance
Edit
Thanks to Mateusz Chrzaszcz I was able to progress.
The only caveat I have with the solution is that it seems like a workaround rather than a solution. But it works!
In addition to his solution you had to resolve the plugins. I was able to hack my way to actually resolve the appropriate names.
In order to do so one has to do as follows:
In a webbrowser go for the plugin: id "com.github.hierynomus.license" version "0.11.0" go to following URL: https://plugins.gradle.org/api/gradle/4.0.1/plugin/use/com.github.hierynomus.license/0.11.0
The json returned contains the GAV needed in the useModule call. Use that
The following serves as an example:
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'com.gradle' && requested.id.name == 'plugin-publish') {
useModule('com.gradle.publish:plugin-publish-plugin:0.9.7')
} else if(requested.id.namespace == 'com.github.hierynomus' && requested.id.name == 'license') {
useModule('nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0')
}
}
}
Try to implement Plugin Resolution Rules.
According to gradle documentation:
Plugin resolution rules allow you to modify plugin requests made in plugins {} blocks, e.g. changing the requested version or explicitly specifying the implementation artifact coordinates.
To add resolution rules, use the resolutionStrategy {} inside the pluginManagement {} block
like that:
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'com.gradle.plugin-publish') {
useModule('com.gradle.plugin-publish:0.9.7') //try a few combinations
}
}
}
repositories {
maven {
url 'https://artifactory/java-v'
}
}
}
Keep in mind this is incubating feature though.

Resources