For some reason gradle is not downloading dependencies from Maven Central. We have a private Nexus repository set up as well and for some reason gradle is looking there for dependencies and not Maven Central.
I get a ton of errors similar to:
Failed to get resource: HEAD. [HTTP HTTP/1.1 400 Repository version policy: SNAPSHOT does not allow version: 1.5.0.RELEASE: http://*****/repository/******/io/pivotal/spring/cloud/spring-cloud-services-dependencies/1.5.0.RELEASE/spring-cloud-services-dependencies-1.5.0.RELEASE.pom]
I swear I have resolved this before when I first set it up, but cannot replicate. In order for me to hit Maven Central, I must have the proxy set up and have Nexus as an exclusion to the proxy.
This all works locally, but the issue comes in when dealing with Jenkins and the Sonarqube plugin. Locally I've tried various proxy settings (remove systemProps or even system env variables), but errors are not the same (ie cannot find host).
Any idea why it's not able to download from Maven Central?
Update:
So I was able to narrow it down a little further. When using Jenkins and Sonarqube withSonarQubeEnv block, something happens with how gradle resolves dependencies. See 3 examples:
// #1 This breaks when SNAPSHOT is declared first
repositories {
maven { // <------------------ SNAPSHOT
credentials {
username usr
password pass
}
url uri(snapshot)
}
maven { // <------------------ RELEASE
credentials {
username usr
password pass
}
url uri(release)
}
mavenCentral() // <---------- Maven Central
}
// #2 This works since mavenCentral() is first:
repositories {
mavenCentral() // <---------- Maven Central
maven { // <------------------ SNAPSHOT
credentials {
username usr
password pass
}
url uri(snapshot)
}
maven { // <------------------ RELEASE
credentials {
username usr
password pass
}
url uri(release)
}
}
// #3 This also works because no failing version policy:
repositories {
maven { // <------------------ RELEASE
credentials {
username usr
password pass
}
url uri(release)
}
mavenCentral() // <---------- Maven Central
}
This works fine when not using withSonarQubeEnv in Jenkins. Why would order matter when using withSonarQubeEnv?
Figured it out. It had nothing to do with withSonarQubeEnv block in Jenkins. The Sonarqube sample settings for gradle had the --info flag added, which I was using for testing. I added that to my build step and found same errors. I even cleaned the cache in the .gradle folder and everything still downloaded.
I suppose Gradle does something a little misleading when it tries to resolve dependencies. It spits out info messages when retrieving a RELEASE artifact from a SNAPSHOT repository, but it still continues to retrieve the artifact from the other listed repositories.
Related
My question is related to:
Jenkins Declarative Pipeline with custom settings.xml
I would like to use Maven with a custom settings.xml created via the Config File Provider plugin. This works fine when wrapping the Maven calls with withMaven(...) or configFileProvider(...), but as pointed out in this comment, it becomes cumbersome when using e.g. multiple stages.
I wonder if this can be avoided with a one-time setup. For instance:
pipeline {
tools {
maven: 'someMaven'
jdk: 'someJdk'
}
environment {
MVN_SETTINGS = 'somehow get path to settings.xml created via Config File Provider Plugin'
}
stages {
stage('someStage') {
sh "mvn --settings ${MVN_SETTINGS} ..."
}
}
}
Usually we bundle the settings.xml file with the source code.
This is especially helpful when sharing the project, or building it on different workspaces.
Any reason why you dont bundle the settings.xml inside your code repository?
We use Sonatype Nexus as artefact repository, configured with credentials in Jenkins and it works fine.
Now i'm trying to get get a gradle project running as jenkins multibranch pipeline job using gradlew including a sonarqube code scan.
Problem:
when using only the rootProjekt.name property in settings.gradle
i get this error:
What went wrong: Plugin [id: 'org.sonarqube', version: '2.6.2'] was not found in any of the following sources:
Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
Plugin Repositories (could not resolve plugin artifact 'org.sonarqube:org.sonarqube.gradle.plugin:2.6.2') Searched in the
following repositories:
Gradle Central Plugin Repository
The sonarqube gradle plugin is found when using the Nexus web UI, but not by gradle inside the pipeline, seems it searches only in Gradle Central Plugin Repository.
When using a Settings.gradle like that:
pluginManagement {
repositories {
maven {
url "http://nexushost/content/groups/public/"
}
}
}
rootProject.name = 'fooBar'
it works like a charm.
How to tell gradle it should always use the sonatype nexus host without having
to configure it in settings.gradle for every Job ?
You should use a Gradle init script.
For example, in every agent, create a file USER_HOME/.gradle/init.d/use-corporate-nexus.gradle, with content:
settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
maven {
url "http://nexushost/content/groups/public/"
}
}
}
}
I have a custom Nexus for project related utility jars. I have a Jenkins to build these jars.
I want to use gradle in the project and a Jenkinsfile to define the pipeline. As the last stage, I want the build job to deploy the artifact to my Nexus.
Since I don't want the credentials for the Nexus in my source repository (and therefor neither in the gradle script nor in the Jenkinsfile), I set up a credentials entry in the Jenkins Credentials plugin, containing user and password for the Nexus.
How do I refer to these credentials from within the Jenkinsfile such that I can use them to deploy to the Nexus?
Currently, my deploy stage looks like this:
stage('Publish') {
sh "gradle upload"
}
Can I use gradle for this purpose at all? I know I can use it locally, but it would be ok for me to use a different command from within the Jenkinsfile.
In gradle, I use this to define the task:
def nexusUser = "$System.env.NEXUS_USER"
def nexusPass = "$System.env.NEXUS_PASS"
uploadArchives {
repositories {
mavenDeployer {
repository(url: "http://nexus.example.com/repository/maven-releases/") {
authentication(userName: nexusUser, password: nexusPass)
}
}
}
}
(I set the user and password as environment variables locally. That's not an option on the Jenkins, of course.)
You can set external variables in ~/.gradle/gradle.properties
nexusUser=superuser
nexusPass=superpassword
You can use withCredentials(){} step to inject environment variables which will be visible only inside {} block.
For one of my projects that I have on GitHub, I wanted to build it as a docker image and push it to my docker hub. The project is a sbt one with a Scala codebase.
Here is how my JenkinsFile is defined:
#!groovy
node {
// set this in Jenkins server under Manage Jenkins > Credentials > System > Global Credentials
docker.withRegistry('https://hub.docker.com/', 'joesan-docker-hub-credentials') {
git credentialsId: '630bd271-01e7-48c3-bc5f-5df059c1abb8', url: 'https://github.com/joesan/monix-samples.git'
sh "git rev-parse HEAD > .git/commit-id"
def commit_id = readFile('.git/commit-id').trim()
println comit_id
stage "build" {
def app = docker.build "Monix-Sample"
}
stage "publish" {
app.push 'master'
app.push "${commit_id}"
}
}
}
When I tried to run this from my Jenkins server, I get the following error:
java.io.FileNotFoundException
at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:167)
at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:159)
at jenkins.plugins.git.GitSCMFileSystem$3.invoke(GitSCMFileSystem.java:161)
at org.jenkinsci.plugins.gitclient.AbstractGitAPIImpl.withRepository(AbstractGitAPIImpl.java:29)
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.withRepository(CliGitAPIImpl.java:65)
at jenkins.plugins.git.GitSCMFileSystem.invoke(GitSCMFileSystem.java:157)
at jenkins.plugins.git.GitSCMFile.content(GitSCMFile.java:159)
at jenkins.scm.api.SCMFile.contentAsString(SCMFile.java:338)
at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:101)
at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:59)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:232)
at hudson.model.ResourceController.execute(ResourceController.java:98)
at hudson.model.Executor.run(Executor.java:404)
Finished: FAILURE
Since this is running inside a VM on Azure, I thought the VM was not able to reach outside, but that seems not to be the case as I was able to ssh into the VM and git pull from the Git repo. So what is the problem here? How could I make this work?
for me unchecking "lightweight checkout" fixed the issue
I experienced the exact same error. My setting:
Pipeline build inside a dockerized Jenkins (version 2.32.3)
In the configuration of the job, I specified a check out into a subdirectory: Open the configuration, e.g. https://myJenkins/job/my-job/configure. At the bottom, see section Pipeline -> Additional Behaviours -> Check out into a sub-directory with Local subdirectory for repo set to, e.g., my-sub-dir.
Expectation: Upon check out, the Jenkinsfile ends up in my-sub-dir/Jenkinsfile.
Via the option Script path, you configure the location of the Jenkinsfile so that Jenkins can start the build. I put my-sub-dir/Jenkinsfile as value.
I then received the exception you pasted in your question. I fixed it by setting Script Path to Jenkinsfile. If you don't specify a sub-directory for check out, then still try double checking values for Script Path.
Note: I have another Jenkins instance at work. There I have to specify Script Path including the custom check out sub-directory (as mentioned in Expectation above).
GO TO Job-->Config-->Pipline and uncheck checkbox lightweight checkout"
lightweight checkout : selected, try to obtain the Pipeline script contents >directly from
the SCM without performing a full checkout. The advantage of this mode
is its efficiency; however, you will not get any changelogs or polling
based on the SCM. (If you use checkout scm during the build, this will
populate the changelog and initialize polling.) Also build parameters
will not be substituted into SCM configuration in this mode. Only
selected SCM plugins support this mode.
I have an incredibly basic Gradle build file:
plugins {
id "base"
id "com.jfrog.artifactory" version "4.3.0"
}
configurations {
batchConfig
}
artifacts{
file("dist").eachFile{ zipFile ->
batchConfig zipFile
}
}
println "BatchConfig Artifacts: " + configurations.batchConfig.allArtifacts
This is executed via Jenkins and appears to work fine:
Archives Artifacts: [DefaultPublishArtifact_Decorated
module-0.0.post0.dev6+n4c62094-py2.7:egg:egg:null]
[buildinfo] Properties file found at
'/tmp/buildInfo65481565498521.properties'
:artifactoryPublish
Deploying build descriptor to:
https://ourArtifactoryServer/artifactory/api/build
Build successfully deployed.
Browse it in Artifactory under
https://ourArtifactoryServer/artifactory/webapp/builds/testGradleBuild/34
BUILD SUCCESSFUL
However the artifact is not actually uploaded to Artifactory at all.
SSL cert configuration appears to be working fine, as I had to address that first. Any suggestions as to what I'm missing here?
Looks like you do still need to utilise the artifactory closure outlined in the Gradle Artifactory Plugin. Switching back to using "archives" instead of a custom Config and then adding this to my build sorted it:
artifactory {
publish {
defaults {
publishConfigs('archives')
}
}
}