Gradle + Kotlin: publishing to maven after researchgate release - gradle

Using Gradle 7.5.1 and Kotlin DSL scripts.
I have a multi-project that publishes individual libraries to Maven - this is working. I'm also using the researchgate release plugin to tag and bump the version number - this is also working.
What I would like to do is to run the release plugin before publishing the artifacts, and I can't find any examples of how to accomplish this. For reference, this is my main build.gradle.kt file (publishing to Maven local only while testing):
plugins {
id("net.researchgate.release") version "3.0.2"
}
allprojects {
apply(plugin = "java")
apply(plugin = "java-library")
apply(plugin = "maven-publish")
repositories {
mavenLocal()
mavenCentral()
}
}
// also tried with PublishToMavenRepository and AbstractPublishToMaven
tasks.withType<PublishToMavenLocal> {
dependsOn("release")
}
subprojects {
configure<PublishingExtension> {
publications {
create<MavenPublication>("maven-java") {
from(components["java"])
}
}
}
}
When I run gradle publish, this is what I get:
> Task :publishToMavenLocal UP-TO-DATE
> Task :auth:compileJava UP-TO-DATE
> Task :auth:processResources NO-SOURCE
> Task :auth:classes UP-TO-DATE
> Task :auth:jar UP-TO-DATE
> Task :auth:generateMetadataFileForMaven-javaPublication
> Task :auth:generatePomFileForMaven-javaPublication
> Task :auth:publishMaven-javaPublicationToMavenLocal
> Task :auth:publishToMavenLocal
> Task :config:compileJava UP-TO-DATE
> Task :config:processResources NO-SOURCE
> Task :config:classes UP-TO-DATE
> Task :config:jar UP-TO-DATE
> Task :config:generateMetadataFileForMaven-javaPublication
> Task :config:generatePomFileForMaven-javaPublication
> Task :config:publishMaven-javaPublicationToMavenLocal
> Task :config:publishToMavenLocal
> Task :logging:compileJava UP-TO-DATE
> Task :logging:processResources NO-SOURCE
> Task :logging:classes UP-TO-DATE
> Task :logging:jar UP-TO-DATE
> Task :logging:generateMetadataFileForMaven-javaPublication
> Task :logging:generatePomFileForMaven-javaPublication
> Task :logging:publishMaven-javaPublicationToMavenLocal
> Task :logging:publishToMavenLocal
BUILD SUCCESSFUL in 319ms
No mention of the release task.

Related

How does IntelliJ gradle resolve task name from build.gradle

I am a bit puzzle about how gradle in IntelliJ resolve the task name
For example, build.gradle has following content:
plugins {
id 'java'
id 'org.gauge' version '1.8.1'
}
group 'com.example'
version '0.0.1-SNAPSHOT'
sourceCompatibility = 1.11
targetCompatibility = 1.11
repositories {...}
dependencies {...}
task gaugeTestLocal(type: GaugeTask) {
doFirst {
gauge {
specsDir = 'specs'
inParallel = false
nodes = 3
env = 'stg'
additionalFlags = '--verbose'
}
}
}
task downloadDependencies {...}
Using IntelliJ Gradle with command gradle gaugeTe, it somehow knows to run gaugeTestLocal instead.
How is this made possible behind the scene?
Run output
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestJava UP-TO-DATE
> Task :processTestResources UP-TO-DATE
> Task :testClasses UP-TO-DATE
> Task :gaugeTestLocal

Gradle Error when using maven publishing task

I am using Gradle version 6.7.1, Currently, in my application I facing an issue with the maven publishing task.
We have kept the publishing task in the central location Gradle file named ( nexusgradle-1.0.5.gradle) and importing it via apply from
the content of the central location Gradle (nexusgradle-1.0.5.gradle) is the below which contain the information of nexus repo for snapshot and release along with user credentials for pushing artefacts to nexus.
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
from components.web
}
}
repositories {
maven {
credentials {
username 'uploader'
password 'uploaderpassword'
}
println 'A message which is logged at QUIET level'
name 'Nexus_Repo'
def releasesRepoUrl = 'http://<hostname>/repository/<maven-releases>/'
def snapshotsRepoUrl = 'http://<hostname>/repository/<maven-snapshots>/'
url = project.version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
The application Gradle ( child Gradle file) looks like the one below
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id 'war'
// Add git release plugin for versioning snaphots and release builds
id 'pl.allegro.tech.build.axion-release' version '1.10.1'
id 'org.springframework.boot' version '2.1.4.RELEASE'
// Add Git properties plugin.
id 'com.gorylenko.gradle-git-properties' version '2.2.0'
id 'jacoco'
}
// apply from center location
apply from :'http://<hostaname>/repository/thirdparty/com/mf/nexusgradle/1.0.5/nexusgradle-1.0.5.gradle'
repositories {
maven {
url = 'http://<hostname>/repository/groupRepo/'
}
jcenter()
}
test {
testLogging.showStandardStreams = true
maxParallelForks = 3
ignoreFailures = true // to skip test Failures
testLogging { //logging the test
exceptionFormat = 'full'
events "passed", "skipped", "failed"
}
}
jacoco {
toolVersion = '0.8.3'
}
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
reports {
xml.enabled true //enabling for generate xml for to capture data in sonarqube server
}
}
// Customize Git properties plugin.
gitProperties {
// Change date format in git.properties file.
dateFormat = "yyyy-MM-dd HH:mm:ssZ"
dateFormatTimeZone = 'GMT'
}
dependencies {
implementation 'org.springframework.boot:spring-boot:2.1.4.RELEASE'
// mutliple import below
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
scmVersion {
repository {
directory = project.rootProject.file('.')
}
}
group = 'com.package'
description = 'appname'
project.version = scmVersion.version
project.ext.timestamp = new Date().format("dd/MM/yyyy HH:mm:ss")
processResources {
filter ReplaceTokens, tokens:[BUILD_VERSION: project.version, BUILD_TIMESTAMP: project.ext.timestamp]
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
war {
enabled = true
}
springBoot {
buildInfo()
}
bootWar {
archiveClassifier = 'boot'
mainClassName = 'com.package.appname.SpringBootRunner'
}
when I run the Gradle command for publishing
gradlew clean build publish
The task will fail as the publishing task will try to push artefacts of the snapshot to the release repo instead of the snapshot repo.
> Configure project :
A message which is logged at QUIET level
> Task :clean UP-TO-DATE
> Task :bootBuildInfo
> Task :compileJava
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
> Task :generateGitProperties
> Task :processResources
> Task :classes
> Task :bootWar
> Task :war
> Task :assemble
> Task :check
> Task :build
> Task :generateMetadataFileForMavenJavaPublication
> Task :generatePomFileForMavenJavaPublication
> Task :publishMavenJavaPublicationToNexus_RepoRepository FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':publishMavenJavaPublicationToNexus_RepoRepository'.
> Failed to publish publication 'mavenJava' to repository 'Nexus_Repo'
> Could not PUT 'http://<hostname>/repository/maven-releases/com/package/appname/1.0.9-SNAPSHOT/maven-metadata.xml'. Received status code 400 from server: Repository version policy: RELEASE does not allow metadata in path: com/package/appname/1.0.9-SNAPSHOT/maven-metadata.xml
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
But if I remove the apply from: item and bring the Publishing task to the application Gradle ( child Gradle file) file it will work fine, the build artefact is pushed to snapshot repo without any issue.
> Configure project :
A message which is logged at the QUIET level
> Task :clean UP-TO-DATE
> Task :bootBuildInfo
> Task :compileJava
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
> Task :generateGitProperties
> Task :processResources
> Task :classes
> Task :bootWar
> Task :war
> Task :assemble
> Task :check
> Task :build
> Task :generateMetadataFileForMavenJavaPublication
> Task :generatePomFileForMavenJavaPublication
> Task :publishMavenJavaPublicationToNexus_RepoRepository
> Task :publish
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.7.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 29s
10 actionable tasks: 9 executed, 1 up-to-date
Can someone guide me, what mistake I am making when putting the maven publishing task in a parent Gradle file? why child Gradle cant resolve values from parent properly
I found a way to fix it by updating the content of the central Gradle /parent file (nexusgradle-1.0.5.gradle) by adding
afterEvaluate
with the modification, it worked fine.
Is it the correct approach? or is there any better way to do it?
apply plugin: 'maven-publish'
afterEvaluate {project ->
publishing {
publications {
mavenJava(MavenPublication) {
from components.web
}
}
repositories {
maven {
credentials {
username 'uploader'
password 'uploaderpassword!'
}
name 'Nexus_Repo'
def releasesRepoUrl = 'http://<hostname>/repository/<maven-releases>/'
def snapshotsRepoUrl = 'http://<hostname>/repository/<maven-snapshots>/'
url = project.version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
}

Run Task in Gradle Plugin after check

I've written a Gradle Plugin in Groovy under buildSrc as:
package test
import org.gradle.api.Plugin
import org.gradle.api.Project
class SamplePlugin implements Plugin<Project> {
#Override
void apply(Project project) {
println "This line prints" //Just for Configuration. This prints
def sample = project.tasks.create("sample") {
doLast {
println "This line does not print"
}
}
project.configure(project) {
sample.mustRunAfter('check')
}
}
}
Here, I'm trying to run the sample task at the end of my build, so I have it run after check
I now try to call it in my projects build.gradle file that looks like:
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
}
apply plugin: 'java'
apply plugin:'application'
apply plugin: test.SamplePlugin
repositories {
mavenLocal()
mavenCentral()
}
mainClassName = "test.Widget"
Unfortunately, I don't see that it runs i.e. the code in the doLast does not appear in the output, but the configuration code does:
:buildSrc:compileJava NO-SOURCE
:buildSrc:compileGroovy
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes
:buildSrc:jar
:buildSrc:assemble
:buildSrc:compileTestJava NO-SOURCE
:buildSrc:compileTestGroovy NO-SOURCE
:buildSrc:processTestResources NO-SOURCE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test NO-SOURCE
:buildSrc:check UP-TO-DATE
:buildSrc:build
This line prints
:compileJava UP-TO-DATE
:processResources NO-SOURCE
:classes UP-TO-DATE
:jar UP-TO-DATE
:startScripts UP-TO-DATE
:distTar UP-TO-DATE
:distZip UP-TO-DATE
:assemble UP-TO-DATE
:compileTestJava NO-SOURCE
:processTestResources NO-SOURCE
:testClasses UP-TO-DATE
:test NO-SOURCE
:check UP-TO-DATE
:build UP-TO-DATE
BUILD SUCCESSFUL in 1s
5 actionable tasks: 5 up-to-date
I'd be grateful for any help or pointers
Edit: As M.Ricciuti commented below order matters, so I have moved the test.SamplePlugin after the plugin java. Otherwise, please follow lu.koerfers solution of using the pluginManager.
In your plugin you are creating a new task 'sample' and set a constraint "sample must run after check": but this does not include the sample task in the task graph . It just says: "if sample and check tasks are both executed , then check task must be executed first". So if you just execute 'gradle build', this will not trigger execution of task "sample".
Try to execute directly "gradle sample" : you will see it will trigger its execution, and make the execution of "check" task first in respect of the contraint you have defined in plugin.
If you want to make "sample" task execute each time you execute "build" task, then just set a "dependsOn" constraint between "build" and "sample" tasks, in your plugin:
class SamplePlugin implements Plugin<Project> {
#Override
void apply(Project project) {
println "This line prints" //Just for Configuration. This prints
def sample = project.tasks.create("sample") {
doLast {
println "This line does not print"
}
}
project.configure(project) {
sample.mustRunAfter('check')
project.getTasks().findByName('build').dependsOn(sample) // <== set this contraint
}
}
}
EDIT : to avoid having to rely on plugin apply order, the task dependency declaration could be wrapped in a "afterEvaluate" block:
void apply(Project project) {
// task 'sample' def ...
// ...
project.configure(project) {
project.afterEvaluate {
sample.mustRunAfter('check')
project.getTasks().findByName('build').dependsOn(sample)
}
}
The methods mustRunAfter and shouldRunAfter only define execution order, not causality. That means that they won't cause a task to be executed. But if both tasks are executed, the specified order will be taken into account.
To specify a task dependency, use dependsOn or finalizedBy:
project.pluginManager.withPlugin('java') {
project.tasks.getByName('check').finalizedBy('sample');
}
This would cause sample to run everytime check runs and it ensures that it runs after check.

Error pushing docker image to dockerhub using gradle

I am trying this Spring boot with docket example using Gradle, but getting the following error on running the task gradle build buildDocker
C:\Users\zeeshan\Workspace\MyWorkspace\SpringBootDocker>gradle build buildDocker
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
:buildDocker FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':buildDocker'.
> java.io.IOException: Cannot run program "docker": CreateProcess error=2, The system cannot find the file specified
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 10.092 secs
The Docketfile exists in src\main\docker in my windows machine.
My build.gradle file:
buildscript {
repositories {
maven { url "${nexusUrl}/content/groups/public" }
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
classpath('se.transmode.gradle:gradle-docker:1.2')
}
}
group = 'mydockergroup'
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'docker'
jar {
baseName = 'gs-spring-boot-docker'
version = '0.1.0'
}
repositories {
maven { url "${nexusUrl}/content/groups/public" }
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
task buildDocker(type: Docker, dependsOn: build) {
push = true
applicationName = jar.baseName
dockerfile = file('src/main/docker/Dockerfile')
doFirst {
copy {
from jar
into stageDir
}
}
}
Note: I copied my workspace in a Ubuntu system and it worked fine. Is there a problem setting the file path for dockerfile in my build.gradle for Windows system?
We are specifying dockerDirectory in docker-maven-plugin. I think you may required to setup similar in gradle.
<dockerDirectory>${basedir}/docker</dockerDirectory>

Gradle: Executing task in subproject programmatically

My WAR file should contain Java source files from components.
In my root project build.gradle I am executing tasks in subprojects programmatically:
apply plugin: 'war'
jar.enabled = false
war {
// - Copy Java source files to the folder corresponding to the component;
into("/") { from { collectFilesFromCopyTask('copySourceFiles') } }
}
// Collects files from destinationDirs of copy tasks with matching taskName
def collectFilesFromCopyTask(taskName) {
FileCollection collectedFiles = files{}
// for each task in subprojects
subprojects.each {project ->
project.tasks.withType(Copy).matching { task -> task.name.equals( taskName ) }.each { copyFilesTask ->
println 'copyFilesTask.destinationDir=' + copyFilesTask.destinationDir
// execute task
copyFilesTask.execute()
// add destinationDir of the task to the collected files
collectedFiles += files(copyFilesTask.destinationDir)
}
}
return collectedFiles
}
In subproject I have task:
task copySourceFiles(type: Copy) {
destinationDir = file(project.buildDir.name + '/sourceFiles')
into('componentName') {
from(project.projectDir)
exclude('build')
exclude('bin')
exclude('src/main/webapp')
exclude('.gradle')
}
}
Console output:
[sts] -----------------------------------------------------
[sts] Starting Gradle build for the following tasks:
[sts] clean
[sts] build
[sts] -----------------------------------------------------
copyFilesTask.destinationDir=<...>application1\build\sourceFiles
:clean
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:war
copyFilesTask.destinationDir=<...>application1\build\sourceFiles
copyFilesTask.destinationDir=<...>application1\build\sourceFiles
copyFilesTask.destinationDir=<...>application1\build\sourceFiles
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
, which means that collectFilesFromCopyTask() is executed 4 times.
It should be executed only once, from WAR task.
Never ever use the .execute() method of a task in Gradle.
Except of when ...... no, never ever do that.
It is not a supported thing to do and does probably not work as expected.
Always use task dependencies or task ordering dependencies to make sure dependent tasks are run or tasks are run in a specific order if they both run but otherwise do not depend on each other directly.
Make your war task depend on your copy tasks and make your war task use the outputs of those tasks (not a manual files(...) call).
EDIT:
war {
into("/") { from { subprojects.tasks*.findByName('copySourceFiles').findAll { it instanceof Copy } } }
}

Resources