I would like to use the "input step" of Jenkins to upload a binary file to the current workspace.
However, the code below seems to upload the file to the Jenkins master, not to the workspace of the current job on the slave where the job is running.
Is there any way to fix that?
Preferably without having to add an executor on the master or clutter the master disk with files.
def inFile = input id: 'file1', message: 'Upload a file', parameters: [file(name: 'data.tmp', description: 'Choose a file')]
Seems Jenkins officially doesn't support upload of binary file yet as you can see in JENKINS-27413. You can still make use of the input
step to get binary file in your workspace. We will be using a method to get this working but we will not use it inside the Jenkinsfile
otherwise we will encounter errors related to In-process Script Approval
. Instead, we will use Global Shared Libraries, which is considered one of Jenkins' best practices.
Please follow these steps:
1) Create a shared library
- Create a repository test-shared-library
- Create a directory named
vars
in above repository. Inside vars
directory, create a file copy_bin_to_wksp.groovy
with the following content:
def inputGetFile(String savedfile = null) {
def filedata = null
def filename = null
// Get file using input step, will put it in build directory
// the filename will not be included in the upload data, so optionally allow it to be specified
if (savedfile == null) {
def inputFile = input message: 'Upload file', parameters: [file(name: 'library_data_upload'), string(name: 'filename', defaultValue: 'demo-backend-1.0-SNAPSHOT.jar')]
filedata = inputFile['library_data_upload']
filename = inputFile['filename']
} else {
def inputFile = input message: 'Upload file', parameters: [file(name: 'library_data_upload')]
filedata = inputFile
filename = savedfile
}
// Read contents and write to workspace
writeFile(file: filename, encoding: 'Base64', text: filedata.read().getBytes().encodeBase64().toString())
// Remove the file from the master to avoid stuff like secret leakage
filedata.delete()
return filename
}
2) Configure Jenkins for accessing Shared Library in any pipeline job
- Go to Manage Jenkins » Configure System » Global Pipeline Libraries section
- Name the library whatever you want (in my case, my-shared-library as shown below)
- Keep the default to master (this is the branch where i pushed my code)
- No need to check/uncheck the check-boxes unless you know what you're doing
3) Access shared library in your job
- In
Jenkinsfile
, add the following code:
@Library('my-shared-library@master') _
node {
// Use any file name in place of *demo-backend-1.0-SNAPSHOT.jar* that i have used below
def file_in_workspace = copy_bin_to_wksp.inputGetFile('demo-backend-1.0-SNAPSHOT.jar')
sh "ls -ltR"
}
You're all set to run the job. :)
Note:
- Make sure Script Security plugin is always up-to-date
- How are Shared Libraries affected by Script Security?
- Global Shared Libraries always run outside the sandbox. These libraries are considered "trusted:" they can run any methods in Java, Groovy, Jenkins internal APIs, Jenkins plugins, or third-party libraries. This allows you to define libraries which encapsulate individually unsafe APIs in a higher-level wrapper safe for use from any Pipeline. Beware that anyone able to push commits to this SCM repository could obtain unlimited access to Jenkins.
- Folder-level Shared Libraries always run inside the sandbox. Folder-based libraries are not considered "trusted:" they run in the Groovy sandbox just like typical Pipelines.
Code Reference: James Hogarth's comment