Jenkins Artifactory Plugin - docker

Can Jenkins Artifactory plugin run docker-in-docker? I would like to use this plugin in tandem with Jenkins Kubernetes plugin in a pipeline build provided below.
The example pipeline creates a Pod which firstly uses a git container to clone the given project-examples repository and then uses a maven container to build the project.
I suspect I am hitting this issue and just wanted to double check if it is still the case.
When executed, the Artifactory plugin searches for resources, e.g. MAVEN_HOME, in the Pod instead of the maven container. Not being able to find the resources the plugin fails.
def label = "worker-${UUID.randomUUID().toString()}"
podTemplate(label: label, containers: [
containerTemplate(name: 'maven', image: 'maven:3.3.9-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
containerTemplate(name: 'git', image: 'alpine/git', command: 'cat', ttyEnabled: true)
]) {
node(label) {
container('maven') {
def server
def buildInfo
def rtMaven
stage ('Clone') {
git url: 'https://github.com/jfrogdev/project-examples.git'
}
stage ('Test a Maven project') {
server = Artifactory.server 'private-artifactory'
rtMaven = Artifactory.newMavenBuild()
rtMaven.tool = 'maven'
rtMaven.run pom: 'maven-example/pom.xml', goals: 'clean build', buildInfo: buildInfo
buildInfo = Artifactory.newBuildInfo()
}
}

I've had the same problem and been trying various variations on configuring the connection to the maven installation.
The final configuration that seems to be working in picking up the maven installation that I have in my docker image is as follows:
stage("build") {
def server=Artifactory.server('My art')
def rtMaven=Artifactory.newMavenBuild()
rtMaven.resolver server: server, releaseRepo: 'libs-release', snapshotRepo: 'libs-snapshot'
rtMaven.deployer server: server, releaseRepo: 'libs-release-local', snapshotRepo: 'libs-snapshot-local'
env.MAVEN_HOME="/usr/share/maven"
def buildInfo = rtMaven.run pom: 'sub-dir/pom.xml', goals: 'clean install'
server.publishBuildInfo buildInfo
}
Using env.MAVEN_HOME instead of relying on a tool configuration seems to work. Rembember to place it before rtMave.run.

Related

Jenkins pipeline script to publish into Jfrogartifactory

I am trying to write a pipeline script to publish *.war/*.jar file to JFrogArtifactory. I don't find any syntax for the same.
Anyone can help me out on the same.
please help me with a sample script.
JFrog has a dedicated GitHub repository with many examples for such cases.
There are Jenkins Pipelines examples there.
First, you must install Artifactory Plugin and config it in Jenkins server.
Refer: https://www.jfrog.com/confluence/display/JFROG/Configuring+Jenkins+Artifactory+Plug-in
And then try add below script to Jenkinsfile:
script {
def server = Artifactory.server '<artifactory id>'
def uploadSpec = '''{
"files": [{
"pattern": "<name of war or jar file>",
"target": "<artifactory repo>/path-to/war-or-jar/file/in-Artifactory"
}]
}'''
server.upload(uploadSpec)
}
Don't forget replace <artifactory id> <name of war or jar file> and <artifactory repo>/path-to/war-or-jar/file/in-Artifactory
More information: https://www.jfrog.com/confluence/display/JFROG/Declarative+Pipeline+Syntax
The scripted pipeline syntax for deploying war files to JFrog artifactory is :
env.ARTIFACTORY = 'True'
if(env.ARTIFACTORY == 'True')
{
stage('Deploying to Artifactory')
{
FAILED_STAGE = env.STAGE_NAME
bat 'mvn deploy'
}
}
Note :
1.) 'bat' command is for Windows batch file. If you're using Linux, replace 'bat' with 'sh'
2.) env.ARTIFACTORY is used to give you control over whether or not you want to execute this particular stage in your pipeline job. if you don't want this stage to execute, simply set env.ARTIFACTORY = 'False'
3.) Also note, you've to configure JFrog in : Manage Jenkins -> Configure system -> JFrog Platform Instances
4.) Include JFrog in your pom.xml file under distributionManagement tag.

Jenkins pipeline for JFrog Artifactory fails to publish BuildInfo

I have Jenkinsfile written in groovy as follows:
env.MVN_Goals = MVN_Goals
node {
// Get Artifactory server instance, defined in the Artifactory Plugin administration page.
def server = Artifactory.newServer url: 'http://localhost:8085/artifactory', username: 'admin', password: 'password'
// Create an Artifactory Maven instance.
def rtMaven = Artifactory.newMavenBuild()
stage ('Clone sources'){
git url: 'D:/Sample GIT_Maven Repo'
}
stage 'Artifactory configuration'
rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server
rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server
def buildInfo = Artifactory.newBuildInfo()
stage('Maven_Build'){
if (isUnix()) {
sh "D:/apache-maven-3.3.9/bin/mvn -B -Dmaven ${MVN_Goals}"
}
else{
bat "D:/apache-maven-3.3.9/bin/mvn -B -Dmaven ${MVN_Goals}"
}
step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true])
}
stage ('Publish build info'){
server.publishBuildInfo buildInfo
}
}
I tried configuring the Artifactory in Jenkins by adding the Artifactory plugin for Jenkins. When I tried to test the connection, I am getting an error as There is either an incompatible or no instance of Artifactory at the provided URL. The same error is occurring when i tried to build my job in Jenkins. Is there a way to resolve it?
Artifactory plugin version - 2.9.1
Artifactory Version - 4.15.0
def buildInfo = Artifactory.newBuildInfo() is within that particular stage.
Modify that as
env.MVN_Goals = MVN_Goals
node {
// Get Artifactory server instance,
// defined in the Artifactory Plugin administration page.
def server = Artifactory.newServer url: 'http://localhost:8085/artifactory', username: 'admin', password: 'password'
// Create an Artifactory Maven instance.
def rtMaven = Artifactory.newMavenBuild()
def buildInfo = Artifactory.newBuildInfo()
stage ('Clone sources'){
git url: 'D:/Sample GIT_Maven Repo'
}

Don't 'artifactoryPublish' when running Artifactory Jenkins Plugin

Is it possible to do a gradle.run (see below), without running the artifactoryPublish task? I thought I could accomplish this by specifying the tasks parameter, but the plugin appears to add the task back in. For example, the following:
def server = Artifactory.server('artifactory-primary')
def gradle = Artifactory.newGradleBuild()
gradle.resolver server: server, repo: 'gradle-all-virtual'
gradle.deployer server: server, repo: 'gradle-libs-snapshot-local'
gradle.deployer.mavenCompatible = true
gradle.useWrapper = true
gradle.usesPlugin = true
def buildInfo = gradle.run(
rootDir: ".",
buildFile: 'build.gradle',
tasks: 'build',
switches: '--no-daemon -x check')
server.publishBuildInfo buildInfo
Results in:
...
gradlew -x check build artifactoryPublish -b build.gradle
...
When what I really want is:
...
gradlew -x check build -b build.gradle
...
Ultimately I want to build in one stage and deploy in another.
The same snippet but with references to artifactory removed from my Gradle file and with Tamir's addition added in:
def server = Artifactory.server('artifactory-primary')
def gradle = Artifactory.newGradleBuild()
gradle.resolver server: server, repo: 'gradle-all-virtual'
gradle.deployer server: server, repo: 'gradle-libs-snapshot-local'
gradle.deployer.mavenCompatible = true
gradle.deployer.deployArtifacts = false
gradle.useWrapper = true
gradle.usesPlugin = false
def buildInfo = gradle.run(
rootDir: ".",
buildFile: 'build.gradle',
tasks: 'build',
switches: '--no-daemon -x check')
server.publishBuildInfo buildInfo
Produces the same result.
The artifactoryPublish task is added by default, you can see that in the Jenkins Artifactory plugin code.
If you prefere not to deploy artifacts to artifactory you can do so by configuring deployer.deployArtifacts = false.
In your case:
gradle.deployer.deployArtifacts = false
If you want to build you project in two phases you can once build it with deployArtifacts=false and in the second time to build it with deployArtifacts=true

Jenkins + Gradle + Artifactory: Couldn't read generated build info

I'm trying to push my artifacts to Artifactory with Jenkins Pipeline, which call Gradle tool.
I am following the examples published on GitHub:
Example1
Example2
My Jenkins Pipeline script:
stage('Perform Gradle Release') {
//ssh-agent required to perform GIT push (when tagging the branch on release)
sshagent([git_credential]) {
sh "./gradlew clean release unSnapshotVersion -Prelease.useAutomaticVersion=true -Prelease.releaseVersion=${release_version} -Prelease.newVersion=${development_version}"
}
// Create an Artifactory server instance
def server = Artifactory.server('my-artifactory')
// Create and set an Artifactory Gradle Build instance:
def rtGradle = Artifactory.newGradleBuild()
rtGradle.resolver server: server, repo: 'libs-release'
rtGradle.deployer server: server, repo: 'libs-release-local'
//Use Gradle Wrapper
rtGradle.useWrapper = true
//Creates buildinfo
def buildInfo = Artifactory.newBuildInfo()
buildInfo.env.capture = true
buildInfo.env.filter.addInclude("*")
// Run Gradle:
rtGradle.run rootDir: "./", buildFile: 'build.gradle', tasks: 'clean artifactoryPublish', buildInfo: buildInfo
// Publish the build-info to Artifactory:
server.publishBuildInfo buildInfo
}
My Gradle file is very light, I'm just using the plugin Gradle Release Plugin to perform gradle release.
When executing the pipeline, it fails with this message:
:artifactoryPublish
BUILD SUCCESSFUL
Total time: 17.451 secs
ERROR: Couldn't read generated build info at : /tmp/generated.build.info4898776990575217114.json
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
hudson.model.Run$RunnerAbortedException
at org.jfrog.hudson.pipeline.Utils.getGeneratedBuildInfo(Utils.java:188)
at org.jfrog.hudson.pipeline.steps.ArtifactoryGradleBuild$Execution.run(ArtifactoryGradleBuild.java:127)
at org.jfrog.hudson.pipeline.steps.ArtifactoryGradleBuild$Execution.run(ArtifactoryGradleBuild.java:96)
at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution.start(AbstractSynchronousStepExecution.java:40)
...
Finished: FAILURE
When I check on the server, there is no such file /tmp/generated.build.info4898776990575217114.json (the user has of course permission to write to /tmp).
Thanks for your help.
[EDIT] It is weird, but I found some files named "buildInfo2408849984051060030.properties", containing the informations. The name is not the same, neither the format, and these files are stores on my Jenkins machine, not my slave executing the pipeline.
Thanks #tamir-hadad, it has indeed been fixed on 2.8.2.

Get gradle variables in jenkins pipeline script

I'm trying to migrate my build pipelines to the "Pipeline plugin" using the groovy build scripts.
My pipelines are usually:
Test (gradle)
IntegrationTest (gradle)
Build (gradle)
Publish (artifactory)
I would like to use the gradle variables like version/group etc. in my jenkins build script to publish to the correct folders in artifactory. Something the artifactory plugin would take care of for me in the past. How can this be achieved?
For a single gradle project I use something like this:
node('master')
{
def version = 1.0
def gitUrl = 'some.git'
def projectRoot = ""
def group = "dashboard/frontend/"
def artifactName = "dashboard_ui"
def artifactRepo = "ext-release-local"
stage "git"
git branch: 'develop', poll: true, url: "${gitUrl}"
dir(projectRoot)
{
sh 'chmod +x gradlew'
stage "test"
sh './gradlew clean test'
stage "build"
sh './gradlew build createPom'
stage "artifact"
def server = Artifactory.server('artifactory_dev01')
def uploadSpec = """{
"files": [
{
"pattern": "build/**.jar",
"target": "${artifactRepo}/$group/${artifactName}/${version}/${artifactName}-${version}.jar"
},
{
"pattern": "pom.xml",
"target": "${artifactRepo}/$group/${artifactName}/${version}/${artifactName}.pom"
}
]
}"""
def buildInfo1 = server.upload spec: uploadSpec
server.publishBuildInfo buildInfo1
}
}
For future reference here an example with the more modern declarative pipeline:
pipeline {
agent any
stages {
stage('somestage') {
steps {
script {
def version = sh (
script: "./gradlew properties -q | grep \"version:\" | awk '{print \$2}'",
returnStdout: true
).trim()
sh "echo Building project in version: $version"
}
}
}
}
}
see also:
Gradle plugin project version number
How to do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?
I think you actually have two different approaches to tackle this problem :
1. Get version/group from sh script
Find a way to get Gradle version from gradle build tool (e.g. gradle getVersion(), but I'm not familiar with Gradle) and then use shell script to get this version. If Gradle command to get the version is gradle getVersion(), you would do in your pipeline :
def projectVersion = sh script: "gradle getVersion()", returnStdout: true
def projectGroup= sh script: "gradle getGroup()", returnStdout: true
and then just inject your $projectVersion and $projectGroup variables in your current pipeline.
2. Configure your Gradle build script to publish to Artifactory
This is the reverse approach, which I personnaly prefer : instead of giving Artifactory all your Gradle project information, juste give Gradle your Artifactory settings and use Gradle goal to easily publish to Artifactory.
JFrog has a good documentation for this solution in their Working with Gradle section. Basically, you will follow the following steps :
Generate a compliant Gradle build script from Artifactory using Gradle Build Script Generator and include it to your project build script
Use Gradle goal gradle artifactoryPublish to simply publish your current artifact to Artifactory
For others who Google'd their way here, if you have the Pipeline Utility Steps plugin and store what you need in your gradle.properties file, you can do something like this in the environment block:
MY_PROPS = readProperties file:"${WORKSPACE}/gradle.properties"
MY_VERSION = MY_PROPS['version']

Resources