Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
@arehmandev

This comment has been minimized.

Copy link
Owner Author

@arehmandev arehmandev commented Apr 12, 2017

Another link:

https://st-g.de/2016/08/jenkins-pipeline-autocompletion-in-intellij

and an example declarative pipeline to play around with:

pipeline {
    agent  {
        label "abdul-executor"
    }

    environment {
        DISABLE_AUTH = 'true'
        DB_ENGINE    = 'sqlite'
    }

    stages {
        stage('Build') {
            steps {
                sh 'echo $DB_ENGINE'
            }
        }
        stage('Test') {
            steps {
                sh 'echo $DISABLE_AUTH'
            }
        }
    }
@rmpestano

This comment has been minimized.

Copy link

@rmpestano rmpestano commented Nov 8, 2017

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

This comment has been minimized.

Copy link

@pathob 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

This comment has been minimized.

Copy link

@rmpestano rmpestano commented Nov 13, 2017

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

This comment has been minimized.

Copy link

@forresthopkinsa forresthopkinsa commented Nov 21, 2017

Keep voting on that Jira task

@ggarcia24

This comment has been minimized.

Copy link

@ggarcia24 ggarcia24 commented Feb 21, 2018

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

This comment has been minimized.

Copy link

@ranma2913 ranma2913 commented Jun 11, 2019

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

This comment has been minimized.

Copy link

@amitrintzler amitrintzler commented Jun 18, 2019

thanks!
do you have more updated file?

@leemeador

This comment has been minimized.

Copy link

@leemeador leemeador commented Jul 1, 2019

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

This comment has been minimized.

Copy link

@flitzie 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

This comment has been minimized.

Copy link

@daniilyar-incountry daniilyar-incountry commented Apr 26, 2020

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

This comment has been minimized.

Copy link

@ranma2913 ranma2913 commented May 13, 2020

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

This comment has been minimized.

Copy link

@ranma2913 ranma2913 commented May 13, 2020

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

This comment has been minimized.

Copy link

@flitzie 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 :-)

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