How does Jenkins Artifactory Plugin communicates resolver credentials to Gradle? - jenkins

Using the Jenkins Artifactory Plugin and Gradle, I am able to deploy to my Artifactory instance successfully. However, I have not been able to use the credentials entered into Jenkins configuration to resolve the artifact from the same repository.
Here is the build.gradle, adopted right from Artifactory's "Generate Build Script" feature in Artifactory.
apply plugin: 'java'
sourceCompatibility = 1.5
version = '1.0'
buildscript {
repositories {
maven {
url 'http://artifactory.myorg.com:8081/artifactory/plugins-release'
credentials {
username = "${artifactory_user}"
password = "${artifactory_password}"
}
}
}
dependencies {
//Check for the latest version here: http://plugins.gradle.org/plugin/com.jfrog.artifactory
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.3"
}
}
allprojects {
apply plugin: "com.jfrog.artifactory"
}
artifactory {
contextUrl = "${artifactory_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'libs-release-local'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
resolve {
repository {
repoKey = 'libs-release'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
}
dependencies {
compile group: "com.myorg", name: "internal-library", version: '1.0'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
Job configuration on Jenkins:
Jenkins Artifactory plugin configuration:
Error:
FAILURE: Build failed with an exception.
* Where:
Build file '/var/lib/jenkins/jobs/deleteme/workspace/build.gradle' line: 10
* What went wrong:
A problem occurred evaluating root project 'untitled2'.
> Could not find property 'artifactory_user' on Credentials [username: null].
Locally, resolving artifacts works (artifactory_user etc are resolved, because I configured them in my local ~/.gradle/gradle.properties). However, builds fail, because artifactory_user is not defined. Of course, I can configure a gradle.properties for Jenkins to use (and this works), however how is this supposed to work? It appears the Jenkins Artifactory Plugin Gradle integration is supposed to somehow communicate resolver credentials. Is there a way to do this without replicating the credentials in two places on Jenkins?

tl;dr username = "${project.getProperty('artifactory.publish.username')}"
Note: I haven't tested this on a Jenkins machine yet
The Jenkins artifactory plugin's gradle integration appears to do two things
Inject the artifactory configuration using a [gradle init script]
Provide build and artifactory configuration information
Both involve writing files to a temporary folder (i.e. /tmp on linux). If you have access to your build server you will probably have a lot of buildInfo\d{19}.properties and init-artifactory\d{19}gradle files in your temp folder.
Looking inside one of these buildInfo files reveals the resolve and publish credentials are stored in artifactory.resolve.username and artifactory.publish.username, respectively.
Trying to setting and trying to use ${artifactory.publish.username} directly doesn't work on my local machine; I assume it has to do with gradle trying to access the property before it is set. But the project.getProperty method works.
buildscript {
repositories {
maven {
url 'http://artifactory.myorg.com:8081/artifactory/plugins-release'
credentials {
username = "${project.getProperty('artifactory.resolve.username')}"
password = "${project.getProperty('artifactory.resolve.password')}"
}
}
}
}
artifactory {
publish {
contextUrl = "${project.getProperty('artifactory.publish.contextUrl')}"
repository {
repoKey = 'libs-release-local'
username = "${project.getProperty('artifactory.publish.username')}"
password = "${project.getProperty('artifactory.publish.password')}"
maven = true
}
}
resolve {
repository {
contextUrl = "${project.getProperty('artifactory.resolve.contextUrl')}"
repoKey = 'libs-release'
username = "${project.getProperty('artifactory.resolve.username')}"
password = "${project.getProperty('artifactory.resolve.password')}"
maven = true
}
}
}
You will have to update your local ~/.gradle/gradle.properties accordingly
artifactory.publish.contextUrl=<artifactory-url>
artifactory.publish.username=<username>
artifactory.publish.password=<password>
artifactory.resolve.contextUrl=<artifactory-url>
artifactory.resolve.username=<username>
artifactory.resolve.password=<password>

I am also banging my head against the wall with this one...I tried all the combinations myself and the only one that seems to be working is adding the gradle.properties to the jenkins server.
Finally I ended up not using the artifactory gradle plugin from jenkins alltogether.R ather add it to the build.gradle and simply call artifactoryPublish from Jenkins Server gradle plugin.

Related

How to publish a WAR file to maven (Nexus) repository with Jenkins via Gradle task

I'm struggling with deploying the war file to Nexus repository using Jenkinsfile via Gradle task.
The war is being created successfully. I have also no problem with deploying JARs (since there are examples everywhere how to do it).
So I have this publishing section in my build.grade:
publishing {
repositories {
maven {
URI releasesUrl = new URI("${UploadURL}/repository/releases")
URI snapshotsUrl = new URI("${UploadURL}/repository/snapshots")
afterEvaluate {
url version.endsWith("SNAPSHOT") ? snapshotsUrl : releasesUrl
}
credentials {
username "${user}"
password "${password}"
}
}
}
publications {
mavenWeb(MavenPublication) {
from components.web
artifact war.archivePath
}
}
}
With pluggins:
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
The URL for repositories is also specified in the build script correctly (test publish with the jar works just fine)
And the Jenkinsfile:
stage ('Publish war') {
steps {
sh "sh gradlew publish"
}
}
Currently I'm getting this error from jenkins build:
Task :publishMavenWebPublicationToMavenRepository FAILED
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':publishMavenWebPublicationToMavenRepository'.
Failed to publish publication 'mavenWeb' to repository 'maven'
Invalid publication 'mavenWeb': multiple artifacts with the identical extension and classifier ('war', 'null').
I'm quite sure that the problem is within "publications" part of Gradle task.
For publishing the Jars I have been using it like this:
[...]
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar
}
}
[...]
task sourceJar(type: Jar) {
classifier 'sources'
from sourceSets.main.java
}
I do not know how to configure from, artifact and classifier for this task. I do not even know if all of these parameters should be configured... Could anyone help me with that?
It turned out, that the origin of the problem was this section:
afterEvaluate {
url version.endsWith("SNAPSHOT") ? snapshotsUrl : releasesUrl
}
This feature works with Gradle 5.X version however, I was using Gradle 4.8. That lead to null instead of propper url value...
Unfortunately, it took a while since the exception message does not suggest where the problem was.

Gradle - "override" behaviour/properties from build.gradle

I'm not a Gradle expert by any means so please be gentle...
I have a Gradle build which I'm trying to run on Jenkins. The build.gradle contains the following:
repositories {
maven {
url "http://some_internal_corporate_repo"
}
}
The Jenkins server that I am running the job on cannot access "some_internal_corporate_repo".
As I can't modify the build.gradle I would like to know if there's a way I can somehow extend or override the build.gradle, on the Jenkins server, to point to mavenCentral (or similar), maybe via an init file or setting a property etc?
Thanks in advance
EDIT: in the end, because I was using Jenkins, I used it's Groovy support (execute Groovy build step) to address my issue:
def file = new File('build.gradle')
def newConfig = file.text.replace('url "http://some_internal_corporate_repo"', 'url "http://repo.maven.apache.org/maven2/"')
file.text = newConfig
You can define multiple repositories.
The order of declaration determines how Gradle will check for dependencies at runtime
repositories {
maven {
url "http://some_internal_corporate_repo"
}
mavenCentral()
}
You can use a properties to define the maven repo url:
repositories {
maven {
url "${repositories_maven_url}"
}
}
In the gradle.properties file
repositories_maven_url=maven_url
According to the gradle documentation, gradle.properties files are applied in the following order:
gradle.properties in project root directory.
gradle.properties in GRADLE_USER_HOME directory.
system properties, e.g. when -Dgradle.user.home is set on the command line.
Or you can use something like this:
repositories {
maven {
url getMavenUrl()
}
}
/**
* Returns the url of the maven repo.
* Set this value in your ~/.gradle/gradle.properties with repositories_maven_url key
* If the property is not defined returns a default value
* #return
*/
def getMavenUrl() {
return hasProperty('repositories_maven_url') ? repositories_maven_url : "YOUR_DEFAULT_VALUE"
}

gradle artifactorypublish: jenkins pipeline does not publish properties

I'm trying to set up a jenkins pipeline for publishing a zip file to jfrog artifactory.
I am using com.jfrog.artifactory plugin to do so. This works great from command line gradle and I can run the artifactoryPublish task to publish the artifacts and tie them back to the module, which then has a tie back to the artifacts.
The artifacts show up with the properties:
build.name = `projectname`
build.number = `some large number`
And I can click from them to the build/module and back to the artifact.
However, when I run this from a jenkinsfile pipeline, the artifacts get published and get tied back to the module, but then the module does not successfully tie the module back to the artifacts.
The artifacts do not receives the build.name and build.number properties and i cannot click from the module back to the artifacts, as the module cannot find or resolve the paths back to the artifacts(a zip file and a generated pom).
I am passing the params from jenkins like:
ORG_GRADLE_PROJECT_buildInfo.build.number=${env.BUILD_NUMBER} which seems to work on other projects... but for whatever reason I cannot shake it.
I can include more jenkinsfile if that would help debug, but i'm really just checking out a repository and trying to publish it.
I have been reading heavily the documentation here:
https://www.jfrog.com/confluence/display/RTF/Gradle+Artifactory+Plugin
and haven't been able to make it work through -Pproject stuff.
Does anyone have any idea what else I can try? i don't really want to use the jenkins pipeline artifactory plugin directly because it's so nice to be able to deploy from the command line too.
build.gradle:
publishing {
publications {
ManualUpdaterPackage(MavenPublication){
artifact assembleManualUpdaterPackage
}
}
}
artifactory {
contextUrl = "${artifactoryUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
defaults {
publications('ManualUpdaterPackage')
}
repository {
repoKey = project.version.endsWith('-SNAPSHOT') ? snapshotRepo : releaseRepo
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
}
task assembleManualUpdaterPackage (type: Zip){
dependsOn anotherTask
from (packageDir + "/")
include '**'
// archiveName "manualUpdaterPackage-${version}.zip"
destinationDir(file(manualUpdaterZipDir))
}
jenkinsfile snip:
withCredentials(
[
[
$class : 'UsernamePasswordMultiBinding',
credentialsId : 'validcreds',
passwordVariable: 'ORG_GRADLE_PROJECT_artifactory_password',
usernameVariable: 'ORG_GRADLE_PROJECT_artifactory_user'
]
]
) {
withEnv(
[
"ORG_GRADLE_PROJECT_buildInfo.build.number=${env.BUILD_NUMBER}",
"ORG_GRADLE_PROJECT_buildInfo.build.name=${artifactName}",
"ORG_GRADLE_PROJECT_buildInfo.build.url=${env.JOB_URL}"
]
) {
sh 'chmod +x gradlew'
sh "./gradlew --no-daemon clean artifactoryPublish"
}
}
https://www.jfrog.com/confluence/display/RTF/Working+With+Pipeline+Jobs+in+Jenkins#WorkingWithPipelineJobsinJenkins-GradleBuildswithArtifactory
Eventually my coworker recommended looking into the Artifactory Pipeline Gradle plugin instead. It is very nice to work with and we've had much quicker success with it.

Getting full nexus archive name in Jenkins pipeline

I'm trying to set-up jenkins build pipeline. It should contains three steps:
Build project
Publish artifact to nexus
Deploy artifact to host
Step 2 should trigger step 3 with full nexus artifact name as a parameter. I don't know how to obtain that value.
Here is my gradle configuration:
uploadArchives {
repositories {
mavenDeployer{
repository(url: "hereMyNexusRepo") {
authentication(userName: "admin", password: "admin123")
}
pom.version = "1.0-SNAPSHOT"
pom.artifactId = "artifactId"
pom.groupId = "groupId"
pom.packaging='jar'
}
}
}
Artifact published by this task has a name that is concatenation of 3 known values:
groupId
artifactId
version
and unknown values
date
time
Sample artifact path looks as follow:
groupId/1.0-SNAPSHOT/artifactId-1.0-20170323.225852-2.jar
How can I get this path? Or can I override it from Jenkins?

Jenkins searches in wrong artifactory path and build fails but local build is successful

we do have a Jenkins server and an Artifactory repository. We have published several libraries to that artifactory repo and it works well. We have also published the anyline sdk as an aar-module. In our projects we reference the artifactory-repo and the aar-module as such:
dependencies { ... compile 'anyline:anyline:3.6.1#aar' ... }
repositories {
jcenter()
mavenLocal()
// External Third Party Libs lookup
maven {
url "https://MYURL/artifactory/libs-snapshot-local"
credentials {
username = bla
password = blubb
}
}
// External Third Party Libs lookup
maven {
url "https://MYURL/artifactory/libs-release-local"
credentials {
username = bla
password = blubb
}
}
// External Third Party Libs lookup
maven {
url "https://MYURL/artifactory/ext-release-local"
credentials {
username = bla
password = blubb
}
}
}
The url for the aar-package is this:
https://MYURL/artifactory/ext-release-local/anyline/anyline/3.6.1/anyline-3.6.1.aar
Locally the build just runs fine but on the jenkins it throws the following error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':BLABLUBB_app'.
> Could not find anyline.jar (anyline:anyline:3.6.1).
Searched in the following locations:
https://MYURL/artifactory/libs-release-local/anyline/anyline/3.6.1/anyline-3.6.1.jar
Now there are two weird things going on here:
1.) Why does the jenkins-build look up a jar-file? Isn't it supposed to look up an aar-file or am I missing something?
2.) The server seems to search in the wrong folder. It should also search in
ext-release-local
and not only in
libs-release-local where obviously no anyline-lib is located.
Does anyone have a hint on whats going wrong here?
The build script on the server is the same as the local one of course, the local repo and the server point to the same git.
Help appreciated,
Thanks
Daniel Sahm

Resources