jenkinsfile-runner icon indicating copy to clipboard operation
jenkinsfile-runner copied to clipboard

How do I run this from within a multibranch pipeline?

Open mezpahlan opened this issue 4 years ago • 3 comments

What I'm trying to do

Run the docker version of Jenkinsfile-runner from within a multibranch pipeline. I want to do something similar to this post https://www.jenkins.io/blog/2019/02/28/serverless-jenkins/ . However instead of using TravisCI as the blog author does I want to use our companies existing Jenkins mutlibranch pipeline infrastructure.

What I have done already

I have successfully managed to build a customised Jenkinsfile-runner Docker image and added it to my local registry. When I execute this from the command line using docker run it correctly picks up my Jenkinsfile and executes it.

Now I want to do this automatically from within a multibranch pipeline but I am getting a bit stuck. Do I need a small bootstrap Jenkinsfile that is configured in the mutlibranch configuration page that simply runs the Jenkinsfile-runner? I'd like to pass some environment values to the main Jenkinsfile such as branch name like the blog post does too.

I must admit I don't know enough about Docker and especially Docker inside of Jenkins so this may seem like an obvious question.

mezpahlan avatar Jun 16 '20 22:06 mezpahlan

To update this after some experimentation:

  1. I have started Jenkins using Docker and created a multibranch pipeline job. This is how I start the Jenkins Docker container.
docker run -p 8080:8080 -p 50000:50000 -v $(pwd)/jenkins_home:/var/jenkins_home -v $(pwd)/test-project:/testgitrepo:ro --group-add $(stat -c '%g' /var/run/docker.sock) -v /var/run/docker.sock:/var/run/docker.sock jenkins/jenkins:lts

I have modified this run command from the jenkinsci/docker README and this blog about some of the troubles trying to run Docker within an already running Jenkins Docker. I also mount my git repo into the running image to be able to quickly reference a Git project using the file:// git schema. This if for quick testing purposes.

  1. In the global tool configuration I have added a Docker installation and asked Jenkins to automatically install Docker.

    • In the future I could customise the Jenkins Docker image to bundle the Docker client as well, but this was easier to start with.
  2. I have added a Jenkinsfile.bootstrap file and told the pipeline configuration to use this instead of the main Jenkinsfile that Jenkinsfile-runner will use.

node {
    def dockerHome = tool 'docker'
    env.PATH = "${dockerHome}/bin:${env.PATH}"
    sh "ls -alt"
    sh "pwd"
    sh "docker run --rm -v \$(pwd):/workspace:ro -v /tmp -e BRANCH_NAME=\$BRANCH_NAME experiment/jenkinsfile-custom-experiment"
}

The run command is modified from the blog post I linked above.

  1. When I run the last line of that boostrap script outside of the Dockerised Jenkins it runs correctly as in the Jenkinsfile-runner Docker image runs, picks up the Jenkinsfile, and runs it.

  2. When I run the multibranch pipeline runs, however, it give me this error:

Started by user admin
Replayed #42
 > git rev-parse --is-inside-work-tree # timeout=10
Setting origin to file:///testgitrepo
 > git config remote.origin.url file:///testgitrepo # timeout=10
Fetching origin...
Fetching upstream changes from origin
 > git --version # timeout=10
 > git config --get remote.origin.url # timeout=10
 > git fetch --tags --progress -- origin +refs/heads/*:refs/remotes/origin/* # timeout=10
Seen branch in repository origin/add-jenkinsfile
Seen branch in repository origin/master
Seen 2 remote branches
Obtained Jenkinsfile.bootstrap from 24fcde91505ac324e46056a45735c55e597060fc
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/ibranch-pipeline_add-jenkinsfile
[Pipeline] {
[Pipeline] tool
[Pipeline] sh
+ ls -alt
total 24
drwxr-xr-x 8 jenkins jenkins 4096 Jun 16 21:52 .git
drwxr-xr-x 3 jenkins jenkins 4096 Jun 16 21:36 .
-rw-r--r-- 1 jenkins jenkins  477 Jun 16 21:36 Jenkinsfile.bootstrap
drwxr-xr-x 6 jenkins jenkins 4096 Jun 16 19:46 ..
-rw-r--r-- 1 jenkins jenkins  221 Jun 16 19:38 Jenkinsfile
-rw-r--r-- 1 jenkins jenkins   12 Jun 16 19:38 README
[Pipeline] sh
+ pwd
/var/jenkins_home/workspace/ibranch-pipeline_add-jenkinsfile
[Pipeline] sh
+ pwd
+ docker run --rm -v /var/jenkins_home/workspace/ibranch-pipeline_add-jenkinsfile:/workspace:ro -v /tmp -e BRANCH_NAME=add-jenkinsfile experiment/jenkinsfile-custom-experiment
2020-06-21 15:55:06.940+0000 [id=1]	WARNING	j.branch.WorkspaceLocatorImpl#getWorkspaceRoot: JENKINS-2111 path sanitization ineffective when using legacy Workspace Root Directory ‘/build’; switch to ‘${JENKINS_HOME}/workspace/${ITEM_FULL_NAME}’ as in JENKINS-8446 / JENKINS-21942
2020-06-21 15:55:07.138+0000 [id=46]	WARNING	o.j.p.w.flow.FlowExecutionList#unregister: Owner[job/1:job #1] was not in the list to begin with: []
Started
java.io.IOException: File '/workspace/Jenkinsfile' exists but is a directory
	at org.apache.commons.io.FileUtils.openInputStream(FileUtils.java:291)
	at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:1805)
	at org.apache.commons.io.FileUtils.readFileToString(FileUtils.java:1838)
	at io.jenkins.jenkinsfile.runner.SetJenkinsfileLocation.create(SetJenkinsfileLocation.java:31)
	at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:105)
	at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:69)
	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:309)
	at hudson.model.ResourceController.execute(ResourceController.java:97)
	at hudson.model.Executor.run(Executor.java:428)
Finished: FAILURE
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 2
Finished: FAILURE

I can see from the ls commands prior to the Docker command that Jenkinsfile is definitely not a directory.

Again, I'm fairly new to Docker and am trying to hack my way through this so I am very much open to being told that I am doing something wrong. Apologies if so.

mezpahlan avatar Jun 21 '20 16:06 mezpahlan

Seems my novice Docker skills are causing issues here. I did manage to get this to work by modifying my Jenkinsfile.bootstrap to this:

node {
    def dockerHome = tool 'docker'
    env.PATH = "${dockerHome}/bin:${env.PATH}"
    sh "docker run --rm -v /path/to/project/on/host/machine/test-project:/workspace:ro -v /tmp -e BRANCH_NAME=\$BRANCH_NAME experiment/jenkinsfile-custom-experiment"
}

The issue I had above was because I was trying to mount a volume that itself was a mounted volume (Docker in Docker) and that doesn't work. But explicitly pointing to location on the host machine did.

That's still not great. But it is a step further. I'll keep hacking.

mezpahlan avatar Jun 21 '20 20:06 mezpahlan

Yes, more patches are needed to make Multi-branch work natively. I am open to change the engine to make it more easy though my first objective is to emulate the folder structure

oleg-nenashev avatar Jul 19 '20 16:07 oleg-nenashev