Jenkins pipeline script to copy artifacts of current build to server location - jenkins

I want to create a Jenkins job which does following:
Git>Mvn build> copy jar to some location of server.
So this can be done using a single job or 2 jobs?
Or which is preferred way of doing this , is pipeline preferred over creating a maven job?
I have created this pipeline script, but this does not copy the current build jar to the server location, it copies the previous build artifact jar.
node {
def mvnHome
stage('Preparation') { // for display purposes
// Get some code from a GitHub repository
git 'git#github.pie.ABC.com:abcdef/BoltRepo.git'
mvnHome = tool 'M2'
}
stage('Build') {
// Run the maven build
if (isUnix()) {
sh "'${mvnHome}/bin/mvn' -Dmaven.test.failure.ignore clean package"
} else {
bat(/"${mvnHome}binmvn" -Dmaven.test.failure.ignore clean package/)
}
}
stage('Results') {
archiveArtifacts 'target/*/BoltRepo*.jar'
}
stage('Deploy Artifact') {
copyArtifacts(
projectName: currentBuild.projectName,
filter: 'target/*/BoltRepo*.jar',
fingerprintArtifacts: true,
target: '/ngs/app/boltd/bolt/bolt_components/bolt_provision/test',
flatten: true )
}
}
What is the best way of achieving this.

I haven't used the pipeline before, but I have done what you want using "ArtifactDeployer" from the "Post-build Actions" in the job's configurations
Note: you will need to install "Artifact Deployer Plug-in"

Related

Jenkins: unable to access the artifacts on the initial run

My setup: main node runs on Linux and an agent on Windows. I want to compile a library on an agent, archive those artifacts and copy them on the main node to create a release togather with the Linux compiled binaries.
This is my Jenkinsfile:
pipeline {
agent none
stages {
stage('Build-Windows') {
agent {
dockerfile {
filename 'docker/Dockerfile-Windows'
label 'windows'
}
}
steps {
bat "tools/ci/build.bat"
archiveArtifacts artifacts: 'build_32/bin/mylib.dll'
}
}
}
post {
success {
node('linux') {
copyArtifacts filter: 'build_32/bin/mylib.dll', flatten: true, projectName: '${JOB_NAME}', target: 'Win32'
}
}
}
}
My problem is, when I run this project for the first time, I get the following error
Unable to find project for artifact copy: mylib
But when I comment the copyArtifacts block and rerun the project, it is successful and I have artifacts vivible in the project overview. After this I can reenable the copyArtifacts and then the artifacts will be copied as expected.
How to configure the pipeline so it can access the artifacts on the initial run?
The copyArtifacts capability is usually used to copy artifacts between different builds and not between agents on the same build. Instead, to achieve what you want you can use the stash and unstash keywords which are designed exactly for passing artifacts from different agents in the same pipeline execution:
stash: Stash some files to be used later in the build.
Saves a set of files for later use on any node/workspace in the same Pipeline run. By default, stashed files are discarded at the end of a pipeline run
unstash: Restore files previously stashed.
Restores a set of files previously stashed into the current workspace.
In your case it can look like:
pipeline {
agent none
stages {
stage('Build-Windows') {
agent {
dockerfile {
filename 'docker/Dockerfile-Windows'
label 'windows'
}
}
steps {
bat "tools/ci/build.bat"
// dir is used to control the path structure of the stashed artifact
dir('build_32/bin'){
stash name: "build_artifact" ,includes: 'mylib.dll'
}
}
}
}
post {
success {
node('linux') {
// dir is used to control the output location of the unstash keyword
dir('Win32'){
unstash "build_artifact"
}
}
}
}

Sharing files between Jenkins pipelines

A lot of the examples I see like How can I use the Jenkins Copy Artifacts Plugin from within the pipelines (jenkinsfile)? share a file within the SAME pipeline. I want to share a file between two different pipelines.
I tried to use the Copy Artifacts plugin like so
Pipeline1:
node {'linux-0') {
stage("Create file") {
sh "echo \"hello world\" > hello.txt"
archiveArtifacts artifact: 'hello.txt', fingerprint: true
}
}
Pipeline2:
node('linux-1') {
stage("copy") {
copyArtifacts projectName: 'Pipeline1',
fingerprintArtifacts: true,
filter: 'hello.txt'
}
}
and I get the following error for Pipeline2
ERROR: Unable to find project for artifact copy: Pipeline1
This may be due to incorrect project name or permission settings; see help for project name in job configuration.
Finished: FAILURE
What am I missing?
NOTE: My real scripted, i.e., not declarative, pipelines are more complicated than these so I can't readily convert them to declarative pipelines.
I just tested this and it worked fine for me. Here is my code, pipeline1:
pipeline {
agent any
stages {
stage('Hello') {
steps {
sh "echo \"hello world\" > hello.txt"
archiveArtifacts artifacts: 'hello.txt', fingerprint: true
}
}
}
}
pipeline2
pipeline {
agent any
stages {
stage('Hello') {
steps {
copyArtifacts projectName: 'pipeline1',
fingerprintArtifacts: true,
filter: 'hello.txt'
}
}
}
}
copyArtifacts projectName: 'pipeline1'
Ensure that the project name is exactly same as the first pipleline's name (
and there are no conflicts on that name). If you have conflicts or use folder plugin ensure to look at this link to refer the project accordingly:
https://wiki.jenkins.io/display/JENKINS/How+to+reference+another+project+by+name

Use workspace location in the post build script in jenkins

I am trying to use the artifacts created in the workspace post jenkins build in a postbuild shell script.
I am not able to use them as workspace artifacts are automatically getting deleted before it comes postbuild script.
Could anyone help me to address this?
When the post-build stage is running, your workspace is already removed. When you think of it, your regular stage and post-build stage may even be running on different nodes, so there can't be any expectation that the files are in your workspace.
To access your artifacts in the post-build stage, you need to fetch them manually, e.g. by using Copy Artifact plugin:
post {
always {
// fetch artifacts of this job and this number to $WORKSPACE
step([
$class: 'CopyArtifact',
filter: '*',
fingerprintArtifacts: true,
optional: true,
projectName: "${JOB_NAME}",
selector: [$class: 'SpecificBuildSelector',
buildNumber: "${BUILD_NUMBER}"]
])
script {
try {
for(file in findFiles(glob: "*")) {
println "Found file ${file}"
}
} catch(error) {
println "Failed to find files"
}
}
}
}

Prevent Archiving In a Jenkins Pipeline

I have asked this question on the Jenkins mailing list.
I have an upstream component, libraryA, I build, archive, and deploy via a Maven job, jobA. This works great. I have a downstream Maven job, jobB, that has a dependency on libraryA. This also works great, except…
I have a completely separate pipeline job, pipelineA specified by Jenkinsfile. Within that Jenkinsfile, I build a specific branch of libraryA I don’t want archived or deployed. In my Jenkinsfile I have “withMaven(mavenLocalRepo: ‘libraryA/.repository’, publisherStrategy: ‘EXPLICIT’)”, and inside that, “sh “””[…]mvn clean package sonar:sonar[…]””” (Any typos here are probably the fault of my typing here as I did not copy-paste. There are no errors from Jenkins when executing these steps.) I have also tried “options: [artifactsPublisher(disabled: true)]” in place of “publisherStrategy: ‘EXPLICIT’” and had the same results. I have verified when pipelineA builds libraryA, it does NOT get deployed to my remote Maven repository, and I expect it not to get deployed there. Good.
So, what happens?
Well, if I build pipelineA followed by jobB, jobB gets its copy of libraryA from pipelineA, causing the build to fail. If I then run jobA, jobB succeeds as expected.
I could change the version of libraryA in the branch pipelineA builds, but I’d rather not do that as it’s not correct for my particular use case. What else could I do? What did I miss? (I do not admin this Jenkins instance, so my access is limited in that respect.)
For clarity here is an approximation of the pipeline's Jenkinsfile:
#!groovy
pipeline {
environment {
GIT_CREDENTIAL_ID = 'git_credential_name'
}
agent any
tools {
maven 'internal_maven'
jdk 'openjdk'
git 'internal_git'
}
stages {
stage('Build Parent') {
steps {
checkoutRepos([[checkoutDir: 'parent', branch: 'gold', url: 'ssh://git#fake-git-url/parent.git']], env.GIT_CREDENTIAL_ID)
withMaven(publisherStrategy: 'EXPLICIT') {
sh """
cd parent
mvn -U clean verify
"""
}
stash name: 'parent', includes: 'pom.xml'
}
}
stage('Build libraryParent') {
steps {
unstash 'parent'
checkoutRepos([[checkoutDir: 'libraryParent', branch: 'gold', url: 'ssh://git#fake-git-url/libraryParent.git']], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: 'libraryParent/.repository', publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
cd libraryParent
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
dir('libraryParent/libraryA/target/') {
stash name: 'libraryA', includes: 'libraryA-1000-SNAPSHOT.jar'
}
}
}
stage('Build appA') {
steps {
sonarAnApp 'appA'
}
}
stage('Build appB') {
steps {
sonarAnApp 'appB'
}
}
stage('Build appC') {
steps {
sonarAnApp 'appC'
}
}
}
}
def sonarAnApp(final String appName) {
unstash 'parent'
unstash 'libraryA'
checkoutRepos([[checkoutDir: appName, branch: 'gold', url: "ssh://git#fake-git-url/${appName}.git"]], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: "$appName/.repository", publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
mvn install:install-file -Dfile=libraryA-1000-SNAPSHOT.jar
cd $appName
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
}

Reuse artifacts at a later stage in the same Jenkins project

I have a Jenkins pipeline whose Build step has an archiveArtifacts command.
After the Build step there is Unit test, Integration test and Deploy.
In Deploy step, I want to use one of the artifacts. I thought I could find it in the same place the Build step generated it, but apparently the archiveArtifacts has deleted them.
As a workaround I can copy the artifact before it is archived, but it doesn't look elegant to me. Is there any better way?
As I understand it, archiveArtifacts is more for saving artifacts for use by something (or someone) after the build has finished. I would recommend looking at using "stash" and "unstash" for transferring files between stages or nodes.
You just go...
stash include: 'globdescribingfiles', name: 'stashnameusedlatertounstash'
and when you want to later retrieve that artifact...
unstash 'stashnameusedlatertounstash'
and the stashed files will be put into the current working directory.
Here's the example of that given in the Jenkinsfile docs (https://jenkins.io/doc/book/pipeline/jenkinsfile/#using-multiple-agents):
pipeline {
agent none
stages {
stage('Build') {
agent any
steps {
checkout scm
sh 'make'
stash includes: '**/target/*.jar', name: 'app'
}
}
stage('Test on Linux') {
agent {
label 'linux'
}
steps {
unstash 'app'
sh 'make check'
}
post {
always {
junit '**/target/*.xml'
}
}
}
stage('Test on Windows') {
agent {
label 'windows'
}
steps {
unstash 'app'
bat 'make check'
}
post {
always {
junit '**/target/*.xml'
}
}
}
}
}

Resources