Jenkins build via SSH, artifacts on host but not in workspace? - jenkins

I've started with a new company and a very convoluted build methodology. The best way I've found to build projects is to command Jenkins to SSH into the build server and execute a string of commands there.
Building by executing shell commands using SSH works well, but the build artifacts don't show up in the Jenkins workspace. Therefore, I can't seem to archive the artifacts directly to Jenkins.
Is there a way to correct this or work around it? Can Jenkins be set up to archive files from outside the workspace?

Assuming that you've added your build node as a node (slave), here's a stash / unstash example
Stash on the build node
stage ('Stash file on node 1') {
node ('some_build_node') {
dir ('/tmp') {
stash name: 'TestTransfer', includes: 'foo.jar'
}
}
}
Unstash on the master
stage ('Unstash file on node 2') {
node ('master') {
// If you don't use a 'dir' block, it'll unstash in the workspace
// which is handy if you then want to archive the artifacts
dir ('/tmp') {
unstash 'TestTransfer'
}
}
}

Related

Is it Possible to Run Jenkinsfile from Jenkinsfile

Currently we are developing centralized control system for our CI/CD projects. There are many projects with many branches so we are using multibranch pipeline ( This forces us to use Jenkinsfile from project branches so we can't provide custom Jenkinsfile like Pipeline projects ). We want to control everything under 1 git repo where for every project there should be kubernetes YAMLS's, Dockerfile and Jenkinsfile. When developer presses build button, Jenkinsfile from their project repo suppose to run our jenkinsfile. Is it possible to do this?
E.g. :
pipeline {
agent any
stages {
stage('Retrieve Jenkinsfile From Repo') { // RETRIEVE JENKINSFILE FROM REPO
steps {
git branch: "master",
credentialsId: 'gitlab_credentials',
url: "jenkinsfile_repo"
scripts {
// RUN JENKINSFILE FROM THE REPO
}
}
}
}
}
Main reason we are doing this, there are sensetive context in jenkinsfile like production database connections. We don't want to store jenkinsfile under developers' repo. Also you can suggest correct way to achieve that beside using only 1 repo.
EDIT: https://plugins.jenkins.io/remote-file/
This plugin solved all my problems. I could'not try comments below
As an option you can use pipeline build step.
pipeline {
agent any
stages {
stage ('build another job') {
steps {
build 'second_job_name_here'
}
}
}
}
Try load step
scripts {
// rename Jenkinsfile to .groovy
sh 'mv Jenkinsfile Jenkins.groovy'
// RUN JENKINSFILE FROM THE REPO
load 'Jenkinsfile.groovy'
}

How to make subsequent checkout scm stages use local repo in a Jenkins pipeline?

We use Jenkins ECS plugin to spawn Docker containers for "each" job we build. So our pipelines look like
node ('linux') {
stage('comp-0') {
checkout scm
}
parallel(
"comp-1": {
node('linux') {
checkout scm
...
}
}
"comp-2": {
node('linux') {
checkout scm
...
}
}
)
}
The above pipeline will spawn 3 containers, one for each node('linux') call.
We set up a 'linux' node in our Jenkins configuration page to tell Jenkins the Docker repo/image we want to spawn. Its setup has a notion of 'Container mount points' which I assume are mounts on the host that the container can access.
So in above pipeline, I want the "first" checkout scm to clone the our repo onto a host path mounted by our containers, say /tmp/git. I then want the succeeding 'checkout scm' lines to clone the repo in my host's /tmp/git path.
I'm looking at How to mount Jenkins workspace in docker container using Jenkins pipeline to see how to mount a local path onto my docker
Is this possible?
You can stash the code from your checkout scm step and then unstash it in subsequent steps. Here's an example from the Jenkins pipeline documentation.
// First we'll generate a text file in a subdirectory on one node and stash it.
stage "first step on first node"
// Run on a node with the "first-node" label.
node('first-node') {
// Make the output directory.
sh "mkdir -p output"
// Write a text file there.
writeFile file: "output/somefile", text: "Hey look, some text."
// Stash that directory and file.
// Note that the includes could be "output/", "output/*" as below, or even
// "output/**/*" - it all works out basically the same.
stash name: "first-stash", includes: "output/*"
}
// Next, we'll make a new directory on a second node, and unstash the original
// into that new directory, rather than into the root of the build.
stage "second step on second node"
// Run on a node with the "second-node" label.
node('second-node') {
// Run the unstash from within that directory!
dir("first-stash") {
unstash "first-stash"
}
// Look, no output directory under the root!
// pwd() outputs the current directory Pipeline is running in.
sh "ls -la ${pwd()}"
// And look, output directory is there under first-stash!
sh "ls -la ${pwd()}/first-stash"
}
Jenkins Documentation on Stash/Unstash

Jenkins Pipeline Build Trigger with git pull, how?

I've got a maven, java project and I'm using git.
I want to use jenkins for build + test + deploy (.war file) on tomcat server (on same device)
My current question is about triggering the build with pushing changes into the git repository master. However it did work with jenkins freestyle project. There I could setup my git repository, so it detected any changes and run the build.
But as far as I could make my research using a "pipeline" should be better to run the process with build + test + deploy. So I created a pipeline and also wrote a jenkinsfile.
pipeline {
agent any
stages {
stage('Compile Stage') {
steps {
withMaven(maven: 'maven_3_5_1'){
bat 'mvn clean compile'
}
}
}
stage('Testing Stage') {
steps {
withMaven(maven: 'maven_3_5_1'){
bat 'mvn test'
}
}
}
stage('Deployment Stage (WAR)') {
steps {
withMaven(maven: 'maven_3_5_1'){
bat 'mvn deploy'
}
}
}
}
}
The current problem is, that inside a pipeline project I could not find an option for setting up the git repository. Currently jenkins does not track any changes in git, when I push a change.
What I've to do, so jenkins runs build when changes are detected in git (like in the freestyle project)?
I thank you very much in advance.
Definition Inside the Repository (Jenkinsfile)
You should place the pipeline definition into a file called Jenkinsfile inside your repository.
This has the great advantage that your pipeline is also versioned. Using the Multibranch Project, you can point Jenkins to your Git repo and it will automatically discover all branches containing such Jenkinsfile (and create a job for each of them). You can find more information in the documentation.
In case you don't want jobs for different branches, you can also configure the job to take the pipeline definition from SCM:
With that specified, you can configure the job to poll SCM changes regularly:
Definition in the Job
In case you really don't want to put your pipeline into the repository (I don't recommend this), then you can use the checkout step to get your code:
pipeline {
agent any
stages {
stage('Compile Stage') {
steps {
checkout('https://git.example.com/repo.git')
withMaven(maven: 'maven_3_5_1') {
bat 'mvn clean compile'
}
}
}
// ...
More options for the checkout (e.g. other branches) can be found in the step documentation.
Finally, change the job to be built in regular intervals:
And now comes the point where I'm struggling (while editing the post): This probably builds the project every time (5min in the example). I am not sure, if currentBuild.changeSets contains the changes that are explicitly checked out with checkout. If it does, then you can check, if it contains changes and in such cases abort the build. All not very nice...

How to set specific workspace folder for jenkins multibranch pipeline projects

I have an external tool that should be called as build-step in one of my jenkins jobs. Unfortunately, this tool has some issues with quoting commands to avoid problems with whitespaces in the path that is called from.
Jenkins is installed in C:\Program Files (x86)\Jenkins. Hence I'm having trouble with jenkins calling the external tool.
What I tried is to set "Workspace Root Directory" in Jenkins->configuration to C:\jenkins_workspace in order to avoid any whitespaces. This works for Freestyle Projects but my Multibranch Pipeline Project is still checked out and built under C:\Program Files (x86)\Jenkins\workspace.
One solution would be to move the whole jenkins installation to e.g. C:\jenkins. This I would like to avoid. Is there a proper way to just tell Jenkins Pipeline jobs to use the "Workspace Root Directory" as well?
Thanks for any help
the ws instruction sets the workspace for the commands inside it. for declarative pipelines, it's like this:
ws("C:\jenkins") {
echo "awesome commands here instead of echo"
}
You can also call a script to build the customWorkspace to use:
# if the current branch is master, this helpfully sets your workspace to /tmp/ma
partOfBranch = sh(returnStdout: true, script: 'echo $BRANCH_NAME | sed -e "s/ster//g"')
path = "/tmp/${partOfBranch}"
sh "mkdir ${path}"
ws(path) {
sh "pwd"
}
you can also set it globally by using the agent block (generally at the top of the pipeline block), by applying it to a node at that level:
pipeline {
agent {
node {
label 'my-defined-label'
customWorkspace '/some/other/path'
}
}
stages {
stage('Example Build') {
steps {
sh 'mvn -B clean verify'
}
}
}
}
Another node instruction later on might override it. Search for customWorkspace at https://jenkins.io/doc/book/pipeline/syntax/. You can also it use it with the docker and dockerfile instructions.
Try this syntax instead:
pipeline {
agent {
label {
label 'EB_TEST_SEL'
customWorkspace "/home/jenkins/workspace/ReleaseBuild/${BUILD_NUMBER}/"
}
}
}

Auto generate build pipeline for gradle build using Jenkinsfile

I am trying to create a build pipeline based upon the Gradle tasks. I have viewed JenkinsFile configuration Pipeline-as-code-demo but I am unable to create a pipeline for gradle tasks. Please suggest me a possible way so that I can use the Jenkinsfile to automatically show the build pipeline just by reading the configurations from the Jenkinsfile.
Thankyou
In case your project uses Gradle Wrapper you can use the following snippet in your Jenkinsfile:
stage('Gradle Build') {
if (isUnix()) {
sh './gradlew clean build'
} else {
bat 'gradlew.bat clean build'
}
}
If you checkout to subdirectory sub-dir you might want to use
stage('Gradle Build') {
if (isUnix()) {
dir('sub-dir') {sh './gradlew clean build'}
} else {
dir('sub-dir') {bat 'gradlew.bat clean build'}
}
}
In case you're using Artifactory to resolve your build dependencies or to deploy your build artifacts, it is recommended to use the Pipeline DSL for Gradle build with Artifactory.
Here's an example taken from the Jenkins Pipeline Examples page:
node {
// Get Artifactory server instance, defined in the Artifactory Plugin administration page.
def server = Artifactory.server "SERVER_ID"
// Create an Artifactory Gradle instance.
def rtGradle = Artifactory.newGradleBuild()
stage 'Clone sources'
git url: 'https://github.com/jfrogdev/project-examples.git'
stage 'Artifactory configuration'
// Tool name from Jenkins configuration
rtGradle.tool = "Gradle-2.4"
// Set Artifactory repositories for dependencies resolution and artifacts deployment.
rtGradle.deployer repo:'ext-release-local', server: server
rtGradle.resolver repo:'remote-repos', server: server
stage 'Gradle build'
def buildInfo = rtGradle.run rootDir: "gradle-examples/4/gradle-example-ci-server/", buildFile: 'build.gradle', tasks: 'clean artifactoryPublish'
stage 'Publish build info'
server.publishBuildInfo buildInfo
}
Otherwise, you can simply run the gradle command with the sh or bat Pipeline steps.
In jenkins you can creates a jenkins pipeline using a script which is written in Jenkinsfile.
We write a script using 'stages' and 'node' as building block, these building blocks allow you to specify instructions that should be executed as part of jenkins pipeline.
To execute gradle build using JenkinsFile first check for Operating system and call appropriate shell that can execute that gradle task, as below:
Jenkinsfile
stage 'build_Project'
node{
if(isUnix()){
sh 'gradle build --info'
}
else{
bat 'gradle build --info'
}
}
Above code snippet create a stage with name build_project and execute gradle build script of the current project.

Resources