I'm trying to publish my first Gradle plugin to maven central (sonatype), but I'm receiving the following error:
Execution failed for task ':publishBom-pluginPluginMarkerMavenPublicationToMavenRepository'.
> Failed to publish publication 'bom-pluginPluginMarkerMaven' to repository 'maven'
> Could not PUT 'https://oss.sonatype.org/service/local/staging/deploy/maven2/bom-plugin/bom-plugin.gradle.plugin/0.3/bom-plugin.gradle.plugin-0.3.pom'.
Received status code 400 from server: Bad Request
It seems that for some reason, the publishing task is trying to publish my plugin at the root of the sonatype repository, it works when I do execute the task publishToMavenLocal, however, published this strange file in my m2 local: /.m2/repository/bom-plugin/bom-plugin.gradle.plugin and also publish the plugin here /.m2/repository/dev/thiagosouto/bom-plugin/0.3/
I think this is causing the issue but I don't have any clue to solve this problem.
My build.gradle.kts file
plugins {
java
`java-gradle-plugin`
`kotlin-dsl`
`maven-publish`
signing
kotlin("jvm") version "1.4.31"
id("com.gradle.plugin-publish") version "0.13.0"
}
group "dev.thiagosouto"
version "0.3"
buildscript {
repositories {
mavenCentral()
maven {
url = uri("https://plugins.gradle.org/m2/")
}
}
}
gradlePlugin {
plugins {
create("bom-plugin") {
id = "bom-plugin"
implementationClass = "dev.thiagosouto.plugins.bom.BomPlugin"
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.squareup:kotlinpoet:1.7.2")
testImplementation("com.google.truth:truth:1.1.2")
testImplementation("junit:junit:4.13.2")
testImplementation("dev.thiagosouto:file-butler:0.3.0")
}
sourceSets.main {
java.srcDirs("src/main/kotlin")
}
sourceSets.test {
java.srcDirs("src/test/kotlin")
}
tasks.withType<GenerateModuleMetadata> {
enabled = false
}
publishing {
val ossrhUsername: String by project
val ossrhPassword: String by project
repositories {
maven(url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
credentials {
username = ossrhUsername
password = ossrhPassword
}
}
}
publications {
group = "dev.thiagosouto"
version = "0.3"
create<MavenPublication>("mavenJava") {
pom {
name.set("bom-plugin")
description.set("A library to help apply tdd through help functions");
url.set("https://thiagosouto.dev")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
scm {
connection.set("scm:git:git://github.com/othiagosouto/bom-plugin.git/")
developerConnection.set("scm:git:ssh://github.com:othiagosouto/bom-plugin.git")
url.set("https://github.com/othiagosouto/bom-plugin")
}
developers {
developer {
id.set("othiagosouto")
name.set("Thiago Souto silva de barros Santos")
email.set("soutosss#gmail.com")
}
}
}
}
}
}
afterEvaluate {
signing {
sign(publishing.publications["mavenJava"])
}
}
I want to build a jar out of my Gradle project and push it to the nexus repository. As part of this, I created a Jenkins file and added a task "publishing" task in build.gradle.
My Jenkins file:
pipeline {
agent any
environment {
NEXUS = credentials('nexus-user')
}
options {
ansiColor('xterm')
buildDiscarder logRotator(daysToKeepStr: '30', numToKeepStr: '100')
}
triggers { pollSCM('H/5 * * * *') }
stages {
stage('Checkout'){
steps { checkout scm }
}
stage('Build') {
steps { sh "./gradlew assemble" }
}
stage('deploy') {
steps {
sh "gradle -Duser.home=\"$WORKSPACE\" --gradle-user-home=\"$WORKSPACE/.gradle\" -PnexusUsername=$NEXUS_USR -PnexusPassword=$NEXUS_PSW publish"
}
}
}
}
And build.gradle
publishing {
publications{
maven(MavenPublication){
artifactId = "testApp"
from components.java
}
}
repositories {
maven {
url = "http://localhost:8081/nexus/content/repositories/${version.endsWith('-SNAPSHOT') ? "snapshots" : "releases"}"
credentials {
username = "Dont know how to pass the username here"
password = "Dont know how to pass the password here"
}
}
}
}
Could anyone tell me how to get the username and password from Gradle and set here for publishing the jar to nexus.
Answer is:
publishing {
publications{
maven(MavenPublication){
artifactId = "testApp"
from components.java
}
}
repositories {
maven {
url = "http://localhost:8081/nexus/content/repositories/${version.endsWith('-SNAPSHOT') ? "snapshots" : "releases"}"
credentials {
username = "nexusUsername"
password = "nexusPassword"
}
}
}
}
Given the following three projects (foo, bar, and app), where app depends on bar depends on foo, I'd like to be able to simply install bar in project app and have library foo automatically installed as well. This does work correctly with the following scripts:
Project 'foo' build.gradle
plugins {
id "maven-publish"
}
repositories {
mavenLocal()
}
group = "com.test2.foo"
version = "0.0.1"
def distZip = file("${buildDir}/dist.zip")
def distFile = file("${buildDir}/Foo.txt")
tasks.register("createDistFile") {
outputs.file(distFile)
doLast {
distFile.delete()
distFile.parentFile.mkdirs()
distFile.text = "foo output 1"
}
}
tasks.register("assembleZip", Zip) {
dependsOn "createDistFile"
from distFile
archiveName = distZip.name
destinationDir distZip.parentFile
}
publishing {
publications {
main(MavenPublication) {
artifact(distZip) {
builtBy tasks.named("assembleZip")
}
}
}
repositories {
mavenLocal()
}
}
Project 'bar' build.gradle
plugins {
id "maven-publish"
id "base"
}
repositories {
mavenLocal()
}
group = "com.test2.bar"
version = "0.0.1"
def distZip = file("${buildDir}/dist.zip")
def distFile = file("${buildDir}/Bar.txt")
tasks.register("createDistFile") {
outputs.file(distFile)
doLast {
distFile.delete()
distFile.parentFile.mkdirs()
distFile.text = "bar output 2"
}
}
tasks.register("assembleZip", Zip) {
dependsOn "createDistFile"
from distFile
archiveName = distZip.name
destinationDir distZip.parentFile
}
artifacts {
"default" distZip, {
builtBy tasks.named("assembleZip")
}
}
publishing {
publications {
main(MavenPublication) {
artifact(distZip) {
builtBy tasks.named("assembleZip")
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', "com.test2.foo")
dependencyNode.appendNode('artifactId', "foo")
dependencyNode.appendNode('version', "0.0.1")
}
}
}
}
repositories {
mavenLocal()
}
}
Project 'app' build.gradle
repositories {
mavenLocal()
}
configurations {
api
}
dependencies {
api "com.test2.bar:bar:0.0.1"
// This should be automatically installed when bar is installed
// api "com.test2.foo:foo:0.0.1"
}
tasks.register("installLibs", Copy) {
dependsOn configurations.api
destinationDir = file("${buildDir}/libs")
configurations.api.each { config ->
from zipTree(config)
}
doFirst {
destinationDir.deleteDir()
}
}
The Problem
When using the above scripts, this can be verified by running installLibs in project app and verifying that both Bar.txt and Foo.txt are installed into the build/libs directory.
However, if I change the settings.gradle file in project 'app' to be this:
rootProject.name = 'app'
includeBuild '[PATH TO BAR PROJECT]'
Then if I run ./gradle installLibs again for the app project, I find that Foo.txt is no longer installed. Is there a way to manually specify this build metadata for project bar, so then when it is used with includeBuild that its transtive dependencies get included?
I want to download the dependency artifacts manually in the future after Gradle has all the dependency artifacts available, hence I would like to get the URLs which Gradle used to download those artifacts.
Is there a way to get the URL of dependencies which artifacts have been downloaded by Gradle?
use gson for a example:
dependencies {
// https://mvnrepository.com/artifact/com.google.code.gson/gson
compile 'com.google.code.gson:gson:2.8.6'
}
create a task to print url:
task getURLofDependencyArtifact() {
doFirst {
project.configurations.compile.dependencies.each { dependency ->
for (ArtifactRepository repository : project.repositories.asList()) {
def url = repository.properties.get('url')
//https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar
def jarUrl = String.format("%s%s/%s/%s/%s-%s.jar", url.toString(),
dependency.group.replace('.', '/'), dependency.name, dependency.version,
dependency.name, dependency.version)
try {
def jarfile = new URL(jarUrl)
def inStream = jarfile.openStream();
if (inStream != null) {
println(String.format("%s:%s:%s", dependency.group, dependency.name, dependency.version)
+ " -> " + jarUrl)
return
}
} catch (Exception ignored) {
}
}
}
}
}
run ./gradlew getURLofDependencyArtifact
Task :getURLofDependencyArtifact
com.google.code.gson:gson:2.8.6 -> https://jcenter.bintray.com/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar
PS:the result dependency your project's
repositories {
jcenter()
mavenCentral()
}
so, the result maybe:
Task :getURLofDependencyArtifact
com.google.code.gson:gson:2.8.6 -> https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar
using Gradle version 6.0 or above, another way of outputting the URLs is to mix --refresh-dependencies with --info
// bash/terminal
./gradlew --info --refresh-dependencies
// cmd
gradlew --info --refresh-dependencies
or output to file
// bash/terminal
./gradlew --info --refresh-dependencies > urls.txt
// cmd
gradlew --info --refresh-dependencies > urls.txt
note on --refresh-dependencies
It’s a common misconception to think that using --refresh-dependencies
will force download of dependencies. This is not the case: Gradle will
only perform what is strictly required to refresh the dynamic
dependencies. This may involve downloading new listing or metadata
files, or even artifacts, but if nothing changed, the impact is
minimal.
source: https://docs.gradle.org/current/userguide/dependency_management.html
see also: How can I force gradle to redownload dependencies?
Wanted something similar but on Android and Kotlin DSL so based on #andforce's answer developed this which hopefully will be useful for others also,
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.net.URL
val dependenciesURLs: Sequence<Pair<String, URL?>>
get() = project.configurations.getByName(
"implementation"
).dependencies.asSequence().mapNotNull {
it.run { "$group:$name:$version" } to project.repositories.mapNotNull { repo ->
(repo as? UrlArtifactRepository)?.url
}.flatMap { repoUrl ->
"%s/%s/%s/%s/%s-%s".format(
repoUrl.toString().trimEnd('/'),
it.group?.replace('.', '/') ?: "", it.name, it.version,
it.name, it.version
).let { x -> listOf("$x.jar", "$x.aar") }
}.firstNotNullResult { url ->
runCatching {
val connection = URL(url).openConnection()
connection.getInputStream() ?: throw Exception()
connection.url
}.getOrNull()
}
}
tasks.register("printDependenciesURLs") {
doLast {
dependenciesURLs.forEach { (dependency: String, url: URL?) -> println("$dependency => $url") }
}
}
Update: It might not able to find indirect dependencies however.
We need to take care about aar also.
project.configurations.getByName(
"implementation"
).dependencies.each { dependency ->
for (ArtifactRepository repository : rootProject.repositories.asList()) {
def url = repository.properties.get('url')
def urlString = url.toString()
if (url.toString().endsWith("/")) {
urlString = url.toString()
} else {
urlString = url.toString() + "/"
}
def jarUrl = String.format("%s%s/%s/%s/%s-%s.jar", urlString,
dependency.group.replace('.', '/'), dependency.name, dependency.version,
dependency.name, dependency.version)
def aarUrl = String.format("%s%s/%s/%s/%s-%s.aar", urlString,
dependency.group.replace('.', '/'), dependency.name, dependency.version,
dependency.name, dependency.version)
try {
def jarfile = new URL(jarUrl)
def inStreamJar = jarfile.openStream();
if (inStreamJar != null) {
println(String.format("%s:%s:%s", dependency.group, dependency.name, dependency.version)
+ " -> " + jarUrl)
return
}
} catch (Exception ignored) {
}
try {
def aarfile = new URL(aarUrl).setURLStreamHandlerFactory()
def inStreamAar = aarfile.openStream();
if (inStreamAar != null) {
println(String.format("%s:%s:%s", dependency.group, dependency.name, dependency.version)
+ " -> " + aarUrl)
return
}
} catch (Exception ignored) {
}
}
}
I am facing an issue in my build.gradle script My script is bascially generatiing the POM file and then copy the artifact to other location as well under build/lib with different name.The issue which I am facing How to call the below build task beacuse it is generating the error.I am using gradle 2.3
Error:"Defining custom ‘build’ task is deprecated when using standard lifecycle plugin has been deprecated and is scheduled to be removed in Gradle 3.0"
My task build will build the artifact and then generate the POM and move the artifact to different location but I am getting below error.
My full script is
apply plugin: 'cpp'
apply plugin: 'java'
//-- set the group for publishing
group = 'com.tr.anal'
/**
* Initializing GAVC settings
*/
def buildProperties = new Properties()
file("version.properties").withInputStream {
stream -> buildProperties.load(stream)
}
//add the jenkins build version to the version
def env = System.getenv()
if (env["BUILD_NUMBER"]) buildProperties.analBuildVersion += "_${env["BUILD_NUMBER"]}"
version = buildProperties.analBuildVersion
println "${version}"
//name is set in the settings.gradle file
group = "com.t.anal"
version = buildProperties.analBuildVersion
println "Building ${project.group}:${project.name}:${project.version}"
repositories {
maven {
url "http://cm.thon.com:900000/artifactory/libs-snapshot-local"
}
maven {
url "http://cm.thon.com:9000000/artifactory/libs-release"
}
}
dependencies {
compile ([
"com.tr.anal:analytics-engine-common:4.+"
])
}
model {
repositories {
libs(PrebuiltLibraries) {
jdk {
headers.srcDirs "${System.properties['java.home']}/../include",
"${System.properties['java.home']}/../include/win32",
"${System.properties['java.home']}/../include/darwin",
"${System.properties['java.home']}/../include/linux"
}
}
}
}
model {
platforms {
x64 { architecture "x86_64" }
x86 { architecture "x86" }
}
}
model {
components {
main(NativeLibrarySpec) {
sources {
cpp {
source {
lib library: 'main', linkage: 'static'
lib library: 'jdk', linkage: 'api'
srcDir "src/main/c++/native"
include "**/JniSupport.cpp"
include "**/DiseaseStagingJni.cpp"
}
}
}
}
}
}
def nativeHeadersDir = file("$buildDir/nativeHeaders")
//def compilePath = configurations.compile.resolve().collect {it.absolutePath}.join(";")
binaries.all {
// Define toolchain-specific compiler and linker options
if (toolChain in Gcc) {
cppCompiler.args "-I${nativeHeadersDir}"
cppCompiler.args "-g"
linker.args '-Xlinker', '-shared -LNativeJNI/src/main/resources/DSresources/DSLib -lds64 -Wl'
}
}
//def nativeHeadersDir = file("$buildDir/nativeHeaders")
task nativeHeaders {
// def nativeHeadersDir = file("$buildDir/nativeHeaders")
def outputFile = file("$nativeHeadersDir/DiseaseStagingJniWrapper.h")
def classes = [
'com.truvenhealth.analyticsengine.common.diseasestaging.DiseaseStagingJniWrapper'
]
inputs.files sourceSets.main.output
inputs.property('classes', classes)
outputs.file outputFile
doLast {
outputFile.parentFile.mkdirs()
def compilePath = configurations.compile.resolve().collect {it.absolutePath}.join(":")
println "Using Compile Path: ${compilePath}"
exec {
executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
args '-o', outputFile
args '-classpath', compilePath
args classes
}
}
}
tasks.withType(CppCompile) { task ->
task.dependsOn nativeHeaders
}
/*****************************
* Packaging
*****************************/
apply plugin: "maven"
// Workaround for Jenkins-Artifactory plugin not picking up the POM file
def pomFile = file("${buildDir}/libs/${archivesBaseName.toLowerCase()}-${version}.pom")
task newPom << {
pom {
project {
groupId project.group
artifactId project.name
version project.version
description = "Configuration Management Gradle Plugin"
}
}.writeTo(pomFile)
}
//disabling the install task since we're not using maven for real
install.enabled = false
//for publishing to artifactory via jenkins
if(project.hasProperty('artifactoryPublish')) {
artifactoryPublish {
mavenDescriptor pomFile
}
}
def filechange = file("build/libs/NativeJNI-${project.version}.so")
task copyfile(type: Copy) {
from 'build/binaries/mainSharedLibrary'
into 'build/libs'
include('libmain.so')
rename ('libmain.so', "$filechange")
}
//build.dependsOn copyfile
task build (dependsOn: ["newPom","copyfile"]) << {
println "build in progress"
}
def someFile = file("build/libs/NativeJNI-${project.version}.so")
artifacts {
archives someFile
}
Looks like this was a bug in 3.0,
https://github.com/GradleFx/GradleFx/issues/235