access environment variables in jenkins shared library code
Asked Answered
W

6

10

When I use my new shared library I cannot access environment variables for any src class which is executed either directly by the Jenkinsfile or via a var/*.groovy script. This problem persists even when I add withEnv to the var/*groovy script.

What is the trick to get environment variables to propagate to jenkins shared library src class execution?

Jenkinsfile

withEnv(["FOO=BAR2"]) {
  println "Jenkinsfile FOO=${FOO}"
  library 'my-shared-jenkins-library'
  lib.displayEnv()

Shared Library var/lib.groovy

def displayEnv() {
  println "Shared lib var/lib FOO=${FOO}"
  MyClass c = new MyClass()
}

Shared Library src/MyClass.groovy

class MyClass() {
  MyClass() {
    throw new Exception("Shared lib src/MyClass  FOO=${System.getenv('FOO')")
  }
}

** Run Result **

Jenkinsfile FOO=BAR
Shared lib var/lib FOO=BAR
java.lang.Exception: Shared lib src/MyClass FOO=null
...
Wingard answered 12/1, 2018 at 22:3 Comment(0)
W
11

It sure looks like the only way to handle this is to pass the this from Jenkins file down to the var/lib.groovy and harvest from that object

Jenkinsfile

withEnv(["FOO=BAR2"]) {
  library 'my-shared-jenkins-library'
  lib.displayEnv(this)

var/lib.groovy

def displayEnv(script) {
 println "Shared lib var/lib FOO=${FOO}"
 MyClass c = new MyClass(script)

}

src class

MyClass(def script) {
  throw new Exception("FOO=${script.env.FOO}")
}
Wingard answered 12/1, 2018 at 22:12 Comment(0)
F
5

I believe you can populate the environment variable as below, where shared library can access.

Jenkisfile

env.FOO="BAR2"
library 'my-shared-jenkins-library'
lib()

vars/lib.groovy

def call(){
    echo ("FOO: ${FOO}")
    echo ("FOO:"+env.FOO)
}
Flamboyant answered 17/4, 2018 at 12:1 Comment(0)
O
3

For me this just works.

Jenkinsfile:

@Library('jenkins-library') _
pipeline {
    agent any
    environment {
        FOO = 'bar'
    }
    stages {
        stage('Build') {
            steps {
                script {
                    buildImage()
...

The library vars/buildImage.groovy:


def call() {
    println(this.env.FOO)
    println(env.FOO)
}

So to pass the environment to a class in the library, just use this in the vars/yourfunc.groovy.

Ochlophobia answered 4/4, 2019 at 12:21 Comment(0)
D
2

Another method is use the "steps" variable:

In Jenkinsfile

mypackages.myclass.mymethod(steps)

In src

class myclass implements Serializable {
  void mymethod(steps) {
    String myEnvVar = steps.sh(returnStdout: true, script: "env | grep 'myVar' | cut -f 2- -d '='")
  }
}
Dialectical answered 23/4, 2018 at 22:35 Comment(0)
U
2

Not sure what the experts will say about the solution but I was able to access the variables defined in my Jenkinsfile from the shared library using evaluate.

Jenkinsfile

myVar = "abc"

vars/test.groovy

String myVar = evaluate("myVar")
Unfreeze answered 19/9, 2018 at 1:30 Comment(0)
C
2

I stumbled upon this problem lately, so I'm gonna add my $0.02.

The basic template I use for var/*.groovy is:

// var/myMethod.groovy
import cool.package.Clazz

def call(Map m) {
    m.put('env', env)
    m.put('steps', steps)
    new Clazz(m).call()
}

And the template for src/**/*.groovy

// src/cool/package/Clazz.groovy
class Clazz {
    private String cool_field_1 = "default-value-1"
    private int cool_value = 42

    def env
    def steps

    def call() {
        steps.echo("env.BUILD_TAG: ${env.BUILD_TAG}")
        //...
    }
}

In Jenkinsfile it is used standard way:

@Library('mylib@mybranch')

pipeline {
    stages {
       stage('St 1') {
           steps { myMethod('cool_value': 43) }
       }
    }
}

Disclaimer: I don't do Groovy but since it looks similar to Java I can use it a little. Also using Map seems to give the advantage of quite flexible interface.

Cribriform answered 6/10, 2019 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.