Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save arehmandev/736daba40a3e1ef1fbe939c6674d7da8 to your computer and use it in GitHub Desktop.
Save arehmandev/736daba40a3e1ef1fbe939c6674d7da8 to your computer and use it in GitHub Desktop.
1. Setup a project
2. Add groovy SDK support:
https://www.bonusbits.com/wiki/HowTo:Add_Groovy_SDK_to_IntelliJ_IDEA
3. Download http://(yourjenkinsurl)/job/(yourpipelinejob)/pipeline-syntax/gdsl
- this will give you the .gdsl file - download this to the src folder of your project.
4. Finally follow this step - right click on the src folder -> Mark directory as -> Sources Root
5. Now create a .groovy file and begin writing, the autocompletion will work.
references:
http://stackoverflow.com/questions/41062514/use-gdsl-file-in-a-java-project-in-intellij
@rmpestano
Copy link

Hi, thank you for the tips.

One missing step, at least needed here (idea 2017.2), is to associate Jenkinsfile with groovy in Settings > Editor > File types:

filetype

@pathob
Copy link

pathob commented Nov 10, 2017

@arehmandev It is not working for declarative pipelines for me. The generated GDSL file does not contain methods like 'pipeline'. Am I missing anything?

@rmpestano
Copy link

Hi @pathob,
Same problem here, I've made auto completion work but declarative dsl is missing. Looking at this issue looks like Jenkins isn't generating a declarative pipeline GDSL yet.

@forresthopkinsa
Copy link

Keep voting on that Jira task

@ggarcia24
Copy link

Just as an FYI for the folks that are coming from Google like myself I've created a GDSL that supports the declarative pipeline, Hope this can help someone 😄

https://gist.github.com/ggarcia24/fc5acec3288812b34c64a4f2b8f9bca9

@ranma2913
Copy link

Just as an FYI for the folks that are coming from Google like myself I've created a GDSL that supports the declarative pipeline, Hope this can help someone

https://gist.github.com/ggarcia24/fc5acec3288812b34c64a4f2b8f9bca9

This worked wonderfully. I added some more to it here: https://gist.github.com/ranma2913/6c2424a5bda07d12d034502fb4b0b7c2 I forked it, so how do I open a pull request? Is that not possible with gist?

@amitrintzler
Copy link

thanks!
do you have more updated file?

@leemeador
Copy link

The GDSL file from Jenkins 2.164 does not contain everything needed for scripted pipelines either. "parallel" is missing and "usernamePassword" is missing. You can add these lines.

    method(name: 'parallel', type: 'Object', params: [stages:Map], doc: 'Parallel')
    method(name: 'usernamePassword', type: 'Object', params: [stages: Map], doc: 'username plus password credential type')
    method(name: 'usernamePassword', type: 'Object', namedParams: [parameter(name: 'credentialsId', type: 'java.lang.String'), parameter(name: 'passwordVariable', type: 'java.lang.String'), parameter(name: 'usernameVariable', type: 'java.lang.String'),], doc: 'username plus password credential type')

@flitzie
Copy link

flitzie commented Aug 23, 2019

Hi, thanks a lot.

I added this to the last file version

// TODO: How to define annotations in GDSL?
method(name: '@Library', type: 'Object', params: [name: 'java.lang.String'], doc: 'Load a shared library')
method(name: '@Library', type: 'Object', params: [names: 'Map'], doc: 'Load a shared library')

to support shared libraries but I don't know how to define Annotations.
IntelliJ still marks it red and says "Cannot resolve symbol 'Library'". Do you have an idea how to fix it?

and also added

//Steps that require a node context
def closures = context(scope: closureScope())
contributor(closures) {
// What things can be inside a node or pipeline
if (enclosingCall('node') || enclosingCall("pipeline")) {
method(name: 'environment', type: 'Object', params: [body: 'Closure'])

for environment.

@daniilyar-incountry
Copy link

In my case, I just added a dummy annotation to the Intellij project with Jenkins pipelines:

// This is a dummy Library annotation for the IntellijIDEA to compile the pipelines code locally
// It is not used in runtime, in the runtime (on the real Jenkins) the Jenkins built-in 'Library' annotation is used
@interface Library {
  String value()
}

Jenkins doesn't pick it in runtime in my case because it lives one folder above from the pipeline scripts folder :)

Ugly hack but now my pipeline scripts are at least comparable

@ranma2913
Copy link

Hi, thanks a lot.

I added this to the last file version

// TODO: How to define annotations in GDSL?
method(name: '@Library', type: 'Object', params: [name: 'java.lang.String'], doc: 'Load a shared library')
method(name: '@Library', type: 'Object', params: [names: 'Map'], doc: 'Load a shared library')

to support shared libraries but I don't know how to define Annotations.
IntelliJ still marks it red and says "Cannot resolve symbol 'Library'". Do you have an idea how to fix it?

and also added

//Steps that require a node context
def closures = context(scope: closureScope())
contributor(closures) {
// What things can be inside a node or pipeline
if (enclosingCall('node') || enclosingCall("pipeline")) {
method(name: 'environment', type: 'Object', params: [body: 'Closure'])

for environment.

Hi, I found that updating the build.gradle in my pipeline library with this dependency works. Basically it force downloads the jar files which contain the actual Annotation code.
implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-cps-global-lib', version: '2.9', ext: 'jar'`
This prompts IntelliJ to add an import to the top of my pipeline file:
image

Below is an example of my complete build.gradle which allows you to run gradle clean built test running any unit tests you've built.

/**
 * gradle-versions-plugin Documentation: https://github.com/ben-manes/gradle-versions-plugin
 * gradle-upgrade-interactive Documentation: https://github.com/kevcodez/gradle-upgrade-interactive
 */
plugins {
    id "com.jfrog.artifactory" version "4.15.1"
    id 'war'
    id 'eclipse'
    id 'idea'
    id 'groovy'
    id "org.sonarqube" version "2.8"
    id "jacoco"
    id 'application'
    id 'com.github.ben-manes.versions' version "0.28.0"
    id "com.github.johnrengelman.shadow" version "5.2.0"
    id 'org.jenkins-ci.jpi' version '0.38.0'
}

// Pull in version information from version.properties
Properties props = new Properties()
props.load(new FileInputStream("$project.rootDir/gradle/version.properties"))
props.each { prop -> if (!project.hasProperty(prop.key)) project.ext.set(prop.key, prop.value) }

// The pipeline can override these values by e.g. `gradle build -Prevision_version=3`
version = new Version(major: project.property('version.major'),
        minor: project.property('version.minor'),
        revision: project.property('version.revision'))

defaultTasks 'clean', 'compileTestGroovy'

project.group = 'jenkins.pipeline.library'
project.version = '1.0.0-SNAPSHOT'

artifactory {
    contextUrl = "${artifactory_contextUrl}"   //The base Artifactory URL if not overridden by the publisher/resolver
    resolve {
        repository {
            repoKey = 'repo'
            maven = true
        }
    }
}

jacoco {
    toolVersion = "0.8.5"
}

shadowJar {
    zip64 true
}

sonarqube {
    properties {
        property "sonar.java.coveragePlugin", "jacoco"
        property "sonar.jacoco.reportPaths", "$buildDir/target/jacoco.exec"
        property "sonar.vorbose", "true"
    }
}

configurations {
    bom
    upToDate
    exceedLatest
    platform
    upgradesFound
    upgradesFound2
    unresolvable
    unresolvable2
}

repositories {
    maven {
        url "https://repo.jenkins-ci.org/public/"
    }
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    compileGroovy {
        groovyOptions.configurationScript = file("gradle/config.groovy")
    }
//    implementation fileTree(include: ['*.jar'], dir: 'libs')
//    implementation files('libs/global-pipeline-library-method-classes-0.3.0.jar')
    implementation group: 'com.cloudbees', name: 'groovy-cps', version: '1.32'
    implementation group: 'com.contrastsecurity', name: 'contrast-sdk-java', version: '2.12'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.3'
    implementation group: 'com.github.ben-manes', name: 'gradle-versions-plugin', version: '0.+'
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
    implementation group: 'com.lesfurets', name: 'jenkins-pipeline-unit', version: '1.3'
    implementation group: 'com.optum.jenkins.plugins', name: 'optum-plugin', version: '1.3.1'
    implementation group: 'com.optum.psas', name: 'securitymetrics-client', version: '0.1.16'
    implementation group: 'com.optum.riptide.http', name: 'rest-clients', version: '1.1.0'
    implementation group: 'com.rallydev.rest', name: 'rally-rest-api', version: '2.2.1'
    implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.4.0'
    implementation group: 'io.fabric8', name: 'openshift-client', version: '4.8.0'
    implementation group: 'javax.inject', name: 'javax.inject', version: '1'
    implementation group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
    implementation group: 'maven-plugins', name: 'maven-cobertura-plugin', version: '1.4'
    implementation group: 'org.apache.ivy', name: 'ivy', version: '2.5.0'
    implementation group: 'org.apache.maven', name: 'maven-model', version: '3.6.3'
    implementation group: 'org.apache.poi', name: 'poi', version: '4.1.2'
    implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '3.0.1'
    implementation group: 'org.codehaus.groovy', name: 'groovy-jaxb', version: '3.0.1'
    implementation group: 'org.eclipse.hudson', name: 'hudson-cli', version: '3.1.2'
    implementation group: 'org.eclipse.hudson', name: 'hudson-core', version: '3.1.2'
    implementation group: 'org.freemarker', name: 'freemarker', version: '2.3.29'
    implementation group: 'org.jenkins-ci.main', name: 'jenkins-core', version: '2.223', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'buildrotator', version: '1.2', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'credentials', version: '2.1.16', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'credentials-binding', version: '1.4', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'junit', version:'1.6', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'mask-passwords', version:'2.7', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins', name: 'plain-credentials', version:'1.5', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-api', version: '2.23.1', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-cps', version: '2.41', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-cps-global-lib', version: '2.9', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-job', version: '2.15', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-multibranch', version: '2.21', ext: 'jar'
    implementation group: 'org.jenkins-ci.plugins.workflow', name: 'workflow-step-api', version: '2.13', ext: 'jar'
    implementation group: 'org.jsoup', name: 'jsoup', version: '1.13.1'
    implementation group: 'org.kohsuke', name: 'github-api', version: '1.108'
    implementation group: 'org.kohsuke.stapler', name: 'stapler', version: '1.259'
    implementation group: 'org.projectlombok', name: 'lombok', version: '1.18.12'
    implementation group: 'org.sonarsource.scanner.gradle', name: 'sonarqube-gradle-plugin', version: '2.8.0.1969'
    implementation group: 'org.springframework', name: 'spring-web', version: '5.2.2.RELEASE'
    implementation group: 'org.yaml', name: 'snakeyaml', version: '1.26'
    testImplementation group: 'junit', name: 'junit', version: '4.13'
    testImplementation group: 'cglib', name: 'cglib-nodep', version: '3.3.0'
    testImplementation group: 'com.lesfurets', name: 'jenkins-pipeline-unit', version: '1.1'
    testImplementation group: 'commons-io', name: 'commons-io', version: '2.6.0.redhat-00001'
    testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.6.0'
    testImplementation group: 'org.junit.vintage', name: 'junit-vintage-engine', version: '5.6.0'
    testImplementation group: 'org.objenesis', name: 'objenesis', version: '3.1'
    testImplementation group: 'org.spockframework', name: 'spock-core', version: '2.0-M2-groovy-3.0'
    testImplementation group: 'org.yaml', name: 'snakeyaml', version: '1.26'  //read test optumfile yaml
    testRuntime group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.6.0'
}

configurations {
    integrationCompile.extendsFrom testCompile
    integrationRuntime.extendsFrom testRuntime
}

sourceSets {
    main {
        groovy {
            srcDirs = ['src', 'vars']
        }
        resources {
            srcDirs = ['resources']
        }
    }
    test {
        groovy.srcDirs = ['test/groovy']
        resources.srcDirs = ['test/resources']
    }
//    integration {
//        // Note:  https://www.petrikainulainen.net/programming/gradle/getting-started-with-gradle-integration-testing/
//        groovy {
//            compileClasspath += main.output + test.output
//            runtimeClasspath += main.output + test.output
//            srcDir file('test/integration/groovy')
//        }
//        resources.srcDir file('src/integration/resources')
//    }
}


test {
    dependsOn 'cleanTest'
    testLogging {
        events "PASSED", "FAILED", "SKIPPED"
    }
    useJUnitPlatform()
}

//task integration(type: Test) {
//    // dependsOn 'cleanTest'
//    testClassesDirs = sourceSets.integration.output.classesDirs
//    classpath = sourceSets.integration.runtimeClasspath
//    outputs.upToDateWhen { false }
//
//    testLogging {
//        events "PASSED", "FAILED", "SKIPPED"
//    }
//}

// After the build, delete the "vars" classes which are output to build/classes/main.
task deleteVarsClasses(type: Delete) {
    delete fileTree(dir: "$buildDir/classes/main", include: '*.class')
}

class Version {
    String major, minor, revision

    String toString() {
        "$major.$minor.$revision"
    }
}

@ranma2913
Copy link

Hi, thank you for the tips.

One missing step, at least needed here (idea 2017.2), is to associate Jenkinsfile with groovy in Settings > Editor > File types:

filetype

I like giving all my pipeline files a .groovy file extension because then any IDE can at least do basic syntax highlighting. You just have to update your Jenkins Script File to match. Also feel free to Name the files anything you like. there's nothing special about the word Jenkinsfile other than it's default. Here's an example repo I built. Each of the .groovy files is a different pipeline file.
image

@flitzie
Copy link

flitzie commented May 14, 2020

@ranma2913
Thanks for sharing. I came to the same solution by adding "import org.jenkinsci.plugins.workflow.libs.Library" too.
Using implementation makes sense but only if the repository/project itself contains or is the shared library groovy code (in your case it does).

I am using this notation in Gradle because I noticed that hpi files are still resolved unnecessarily:

implementation('org.jenkins-ci.plugins.workflow:workflow-cps-global-lib:2.16') {
   // explicitly adding the jar artifact for the IDE and exclude hpi file ...
   artifact {
      name = 'workflow-cps-global-lib'
      type = 'jar'
   }
}

try it out :-)

But when it comes to a consumer project using the shared library code then my suggestion is to separate the sourceSet by defining it for example like this:

configurations {
   ideJenkinsfileSupport
}

Otherwise you "poison" your actual project code with shared library code, which you don't want to have in your productive environment :-)

@salimfadhleyhtp
Copy link

The instructions say to download the gdsl, but where and to which filename?

@smangels
Copy link

smangels commented May 20, 2021

The instructions say to download the gdsl, but where and to which filename?

Download them from a pipeline in Jenkins (link on the left pane), filename doesn't matter. What matters is that IntelliJ recognizes the file as GDSL (thus the "gdsl" file extension. :-)

@Mr-LiuDC
Copy link

Thanks for the ideas here, I have added some other pipeline syntax.

https://gist.github.com/Mr-LiuDC/8a1fbe27e8fbd42361185b06085ef4c3

@karfau
Copy link

karfau commented Feb 3, 2022

What groovy version is used by people that get this working?
I tried 4.0.0-rc2, 3.0.9, 2.5.15 without success.

I only ever get the following:
image

image

@gsusI
Copy link

gsusI commented Jul 30, 2022

For the issue 'pipeline' cannot be applied to '(groovy.lang.Closure)'

Add: method(name: 'pipeline', type: 'Object', params: [body:'Closure'], doc: 'Pipeline root element')

@jaydubb12
Copy link

@karfau I did get it working...see this project I was able to setup - https://github.com/jaydubb12/jenkins-dsl-pipelines

@NicoStrecker
Copy link

@gsusI i had to set the project sdk set to java 17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment