jenkins convert to pipeline plugin

I needed to convert a freestyle job to a pipeline job for “Automating your Ci/CD Stack with Java and Groovy” Hands On Lab at Oracle Code One. It’s a really simple project, but it is still a pain to convert by hand.

I had read about the Convert to Pipeline plugin so decide to give it a shot. It’s easy enough to install a plugin.

Generated Pipeline

Below is what got generated. While I’d like to assume that credentials binding isn’t in wide use, that one didn’t surprise me. In hindsight, it makes sense because the credentials binding would need to wrap the Gradle block. I was surprised that Gradle wasn’t supported.

I am glad that the tool leaves comments for what you need to do by hand.

// Powered by Infostretch 

timestamps {

node () {

	stage ('osprey - Checkout') {
 	 checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '', url: 'https://github.com/boyarsky/OracleCodeOne2018-HOL-Automating-Stack-Groovy.git']]]) 
	}
	stage ('osprey - Build') {
 	
// Unable to convert a build step referring to "org.jenkinsci.plugins.credentialsbinding.impl.SecretBuildWrapper". Please verify and convert manually if required.
// Unable to convert a build step referring to "hudson.plugins.gradle.Gradle". Please verify and convert manually if required.
		// JUnit Results
		junit 'osprey-project/build/test-results/test/*.xml' 
	}
}
}

Using the pipeline generator

On the pipeline job, you can click the “pipeline syntax” link. It opens a new browser tab with a pull down for common pipeline operations.

Credentials

I choose “withCredentials”, entered the variable names and selected the credential from the pull down. Then I clicked “Generate Pipeline Script” and got:


withCredentials([usernamePassword(credentialsId: 'nexus', passwordVariable: 'nexusPassword', usernameVariable: 'nexusUserName')]) {
// some block
}


Gradle

That brings us to Gradle. As far as I can tell, there are only objects for Gradle if you are using Artifactory. I am using the gradle wrapper though, so I followed the advice of this Stack Overflow post and just called gradlew.


withCredentials([usernamePassword(credentialsId: 'nexus', passwordVariable: 'nexusPassword', usernameVariable: 'nexusUserName')]) {
  sh "./osprey-project/gradlew clean build -b osprey-project/build.gradle -PnexusBaseUrl=http://nexus:8081 -PnexusUserName=${nexusUserName} -PnexusPassword=${nexusPassword}"
}

I decided to separate the publish step into a different stage and rename the stages as well.  Resulting in:


// Powered by Infostretch 

timestamps {

node () {

	stage ('Checkout') {
 	 checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '', url: 'https://github.com/boyarsky/OracleCodeOne2018-HOL-Automating-Stack-Groovy.git']]]) 
	}
	stage ('Build') {
	    
	   withCredentials([usernamePassword(credentialsId: 'nexus', passwordVariable: 'nexusPassword', usernameVariable: 'nexusUserName')]) {
          sh "./osprey-project/gradlew clean build -b osprey-project/build.gradle -PnexusBaseUrl=http://nexus:8081 -PnexusUserName=${nexusUserName} -PnexusPassword=${nexusPassword}"
       }

		// JUnit Results
		junit 'osprey-project/build/test-results/test/*.xml' 
	}
	
	stage ('Publish') {
	    
	   withCredentials([usernamePassword(credentialsId: 'nexus', passwordVariable: 'nexusPassword', usernameVariable: 'nexusUserName')]) {
          sh "./osprey-project/gradlew publish -b osprey-project/build.gradle -PnexusBaseUrl=http://nexus:8081 -PnexusUserName=${nexusUserName} -PnexusPassword=${nexusPassword}"
       }
	}
}
}

Note: My actual build file was bigger. The parts outside the pipeline (ex: project security settings) got preserved.

creating a new VS code gradle project

I need to create a really simple Gradle project from scratch for my Oracle Code One hands on lab. I also need need to gain more experience with Visual Studio Code since we are using it soon for FIRST robotics. Seems like a good opportunity to combine my tasks here!

First, I re-read my first impressions of VS Code blog post. That reminded me of the keyboard shortcut to get context sensitive options. Ok. now I’m ready to get started.

(I intentionally didn’t use an archetype to get more experience using the editor)

Installing Gradle extension

I installed the Gradle Language Support plugin. Not sure if I needed it, but the syntax highlighting is nice. I don’t see a wizard option to create a Gradle project. This means I have to create an empty project

Creating a new project

I created an empty folder on my filesystem. Then I added that folder to VS Code. This created an empty project with the name I wanted.

Create the build file

I tried click “New File” on the editor. That created an untitled file that I couldn’t figure out how to rename. I could figure out how to delete it so I did that.

Then I used the keyboard shortcut to open help and choose “File: New”. Great that prompts me for a name. (I then realized that I could have just right clicked to have the new file option.)

I then typed a small gradle build file

apply plugin: 'java'</div>
repositories {
<div>  mavenCentral()</div>
<div>}</div>
<div>dependencies {</div>
<div>  compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8'</div>
<div>}
Create directory structure
I then created the src/main/java and src/test/java folders. I was able to right click to create the folders so this was easy enough.
Create Java packages
I couldn’t find an easy way to create packages/classes, so I created a bunch of folders and a file with the extension .java. This did work and the IDE let me type in my class.
However, when i did the same for my unit test, I was not able to open the empty file. At this point, I gave up and went back to Eclipse. I need to poke at this when I have more time.
Also, it appears the FIRST robotics plugin overrides the behavior of the default gradle run.
Editing a project
I created my first project in Eclipse. The second was a copy of the first with some renames and minor behavior changes. I copied the first project on disk. Then I opened that folder and made all the edits in VS Code. That was easy; even autocomplete worked as expected. My only problem with the second project was running the gradle build and I think that’s the FIRST robotics plugin.
Other observations
  • Since I created my folder/project inside a git repo on my machine, VS Code was smart enough to detect this. It was also helpful for seeing what I forgot to add to the .gitignore fil.
  • I feel like I got dropped into someone else’s home. I was able to do everything I needed. But not in an efficient way.

 

 

a rant about jenkins script security

I’m working on the lab for my Automating Your CI/CD Stack with Java and Groovy Oracle Code One session. And of course I tripped over Jenkins Script Security plugin.

I don’t need script security. I’m running a lab. But you can’t turn off that feature. Sigh.

I can run this code from the scripting console as an admin. I can also run it from within a job using the embedded Groovy console option. If I try to pull the same code from GitHub and run it from the same job as a Groovy script, I can’t. Script security views the SAME script to be more dangerous because I put it in source control.

import jenkins.model.Jenkins

def instance = Jenkins.getInstance()
def realm = Jenkins.getInstance().securityRealm

I can think of three ways to “solve” the problem that Cloudbees created.

Option 1: Deal with script security

I can configure script security to allow these signatures. However, this does not make things more secure. I want these to be available to admins not for general use. So approving them or whitelisting them is the wrong decision. (Ok. It doesn’t matter here since this is just a lab. But in this hypothetical use case…)

Option 2: Authorized Build plugin

There’s an authorize project plugin that lets you run the build as an admin. I didn’t try it, but it appears to provide a decent workaround to this problem. (I’m trying to minimize setup)

Option 3: Just run the code through the Groovy console

I’m going with this. Up to 50 people are going to be doing this manually in a lab. Copy/paste is the easiest solution.