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

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.

Related

Jenkins, Gradle : How to publish Dependency report to Sonar Dashboard

Currently we're using Jenkins free style job for Gradle project and using following commands to run Sonar and Dependencycheck
./gradlew clean build sonarqube dependencyCheckAnalyze \
and I'm getting following message
Analyzing /opt/jenkins_slave_home/workspace/AA/package-lock.json - however, the node_modules directory does not exist. Please run npm install prior to running dependency-check
Generating report for project AA_ArbitraryBuild
Found 0 vulnerabilities in project AA
and we can able to see a file inside "ws/build/reports/" but it dint scanned anything.
Following are the "build.gardle" file
buildscript {
repositories {
maven { url artifactoryRepoUrl }
mavenCentral()
}
dependencies {
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7'
classpath 'org.owasp:dependency-check-gradle:6.0.3'
}
}
apply plugin: 'org.sonarqube'
apply plugin: 'org.owasp.dependencycheck'
sonarqube {
properties {
property 'sonar.projectName', sonarProjectName
property 'sonar.projectKey', sonarProjectKey
property 'sonar.host.url', sonarHostUrl
property 'sonar.login', sonarAuthToken
property 'sonar.dependencyCheck.reportPath', sonarDependencyCheckReport
property 'sonar.dependencyCheck.htmlReportPath', sonarDependencyCheckHTMLReport
}
}
Can you plz help on what are the additional steps that I need to add.
You've got all you need to push result to sonar. Make sure that you provide right path for your owasp vulnerabilities report for sonar plugin. It's sonar.dependencyCheck.reportPath and should point to build/reports directroy, and if you produce html report file you can point it with sonar.dependencyCheck.htmlReportPath.

Compile groovy project and run JUnit tests via Jenkins

I googled for ages now and I give up, the buzz word Groovy + Jenkins is bringing up so many false flags...
I have a Groovy project I developed in IntelliJ, it contains also a JUnit.groovy with unit tests. Now this is a script for SoapUI, no need for Maven, Ant nor Grails, but I would like to be able to compile those files on Jenkins and run the unit tests after. Is it possible to build and test those files on Jenkins? So far all solutions seem to be me manually running groovyc (commited with my repository) and then running JUnit on the JUnit.class.
So before I start to dig deeper and write a Maven, Grails or Ant file, is there another way that does not involve me pushing the GroovySDK on my git? Or is there may be a simple build script, not involving 20 libraries and steps that would build the groovy sources and run the JUnit tests :) ?
I'm new to Jenkins obviously ;), thanks for your input.
Update:
So for all as newbie as me, what was required? First I changed my local source code to a gradle project (remember to activate AutoImport in IntelliJ) and also activate the creation of the JUnit xml and since I do not use Maven and the system is "offline" we have the libs in git anyway so my build.gradle is:
version '2.5-SNAPSHOT'
apply plugin: 'groovy'
dependencies {
compile fileTree(dir: '../Library', include: ['*.jar'])
}
test {
reports {
junitXml.enabled = true
html.enabled = true
}
}
sourceCompatibility = 1.8
set up gradle wrapper for the project via gradle wrapper for the gradlew.bat
then I added a post-commit in my git-/.hooks/ so my Jenkins is triggered upon commit via curl http://jenkins:8080/git/notifyCommit?url=https://git.git&branches=dev
finally set up a pipeline on jenkins:
#!groovy
node {
stage('Checkout') {
git branch: 'dev', credentialsId: 'youwish', url: 'https://git.git'
}
stage('Build') {
dir('./Modules') {
gradle('clean')
gradle('compileTestGroovy')
}
}
stage('UnitTest') {
dir('./Modules') {
gradle('test')
junit '/build/test-results/**/TEST-*.xml'
}
}
stage('IntegrationTest') {
stage('CodeTableDownload') {
dir('./SoapUi') {
bat 'AutoRun.bat'
junit '/results/**/*-JUNIT.xml'
}
}
}
}
def gradle(command) {
bat "./gradlew.bat $command"
}
There's a Groovy plugin for Jenkins that will let you execute Groovy scripts on Jenkins.
But, why not let something like Gradle do the build and run the test for you? A minimal Gradle build file for Groovy that will do both is:
apply plugin: 'groovy'
repositories {
jcenter()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.12'
testCompile 'junit:junit:4.12'
}
You don't have to commit the GDK, just declare a dependency.

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.

Using waitForQualityGate in a Jenkins declarative pipeline

The following SonarQube (6.3) analysis stage in a declarative pipeline in Jenkins 2.50 is failing with this error in the console log: http://pastebin.com/t2ja23vC. More specifically:
SonarQube installation defined in this job (SonarGate) does not match any configured installation. Number of installations that can be configured: 1.
Update: after changing "SonarQube" to "SonarGate" in the Jenkins settings (under SonarQube servers, so it'll match the Jenkinsfile), I get a different error: http://pastebin.com/HZZ6fY6V
java.lang.IllegalStateException: Unable to get SonarQube task id and/or server name. Please use the 'withSonarQubeEnv' wrapper to run your analysis.
The stage is a modification of the example from the SonarQube docs: https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Jenkins#AnalyzingwithSonarQubeScannerforJenkins-AnalyzinginaJenkinspipeline
stage ("SonarQube analysis") {
steps {
script {
STAGE_NAME = "SonarQube analysis"
if (BRANCH_NAME == "develop") {
echo "In 'develop' branch, don't analyze."
}
else { // this is a PR build, run sonar analysis
withSonarQubeEnv("SonarGate") {
sh "../../../sonar-scanner-2.9.0.670/bin/sonar-scanner"
}
}
}
}
}
stage ("SonarQube Gatekeeper") {
steps {
script {
STAGE_NAME = "SonarQube Gatekeeper"
if (BRANCH_NAME == "develop") {
echo "In 'develop' branch, skip."
}
else { // this is a PR build, fail on threshold spill
def qualitygate = waitForQualityGate()
if (qualitygate.status != "OK") {
error "Pipeline aborted due to quality gate coverage failure: ${qualitygate.status}"
}
}
}
}
}
I also created a webhook, sonarqube-webhook, with the URL http://****/sonarqube-webhook/. Should it be like that, or http://****/sonarqube/sonarqube-webhook? To access the server dashboard I use http://****/sonarqube.
In SonarQube's Quality Gates section I created a new quality gate:
I am not sure if the setting in SonarGate is correct. I do use jenkins-mocha to generate an lcov.info file that is used in Sonar to generate the coverage data.
Perhaps the quality gate setting is the wrong setting to do? The end result is to fail the job in Jenkins if coverage % is not met.
Finally, I am not sure if the following configurations in the Jenkins system configuration are at all required:
And
(It's 9000 not 900... cut text in the screen shot)
The SonarQube Jenkins plugin scans the build output for two specific lines, which it uses to get the SonarQube report task properties and project URL. If your invocation of sonar-scanner does not output these lines, the waitForQualityGate() call won't have the task ID to look them up. So you will have to figure out the correct settings to make it more verbose.
See the extractSonarProjectURLFromLogs and extractReportTask methods in the SonarUtils class of the plugin to understand how they work:
ANALYSIS SUCCESSFUL, you can browse <project URL> is used to add a link to the badge (in the build history)
Working dir: <dir with report-task.txt> is used to pass the task ID to the waitForQualityGate step
This was discovered to be a bug in the SonarQube scanner for Jenkins, when using a Jenkins slave for jobs (if the job is run on the master, it'd work). You can read more here: https://jira.sonarsource.com/browse/SONARJNKNS-282
I have tested this using a test build of v2.61 of the scanner plug-in and found it working.
The solution is to upgrade to v2.61 when released.
This stage will then work:
stage ("SonarQube analysis") {
steps {
withSonarQubeEnv('SonarQube') {
sh "../../../sonar-scanner-2.9.0.670/bin/sonar-scanner"
}
def qualitygate = waitForQualityGate()
if (qualitygate.status != "OK") {
error "Pipeline aborted due to quality gate coverage failure: ${qualitygate.status}"
}
}
}
If you're running SonarCube in a docker container check that the memory isn't exhausted. We were maxing out. Which seemed to be the issue.

How does Jenkins Artifactory Plugin communicates resolver credentials to Gradle?

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.

Resources