griddynamics / mpl

[IT-36925] Jenkins Shared Modular Pipeline Library
https://blog.griddynamics.com/developing-a-modular-pipeline-library-to-improve-devops-collaboration/
Apache License 2.0
158 stars 97 forks source link

Fix problem with import env from Jenkinsfile #43

Closed emelianrus closed 5 years ago

emelianrus commented 5 years ago

Hi, There is a problem with wrong passing variables from Jenkinsfile for example i have Jenkinsfile and i want to use different CFG for each module

MPLPipeline {

  modules = [ 
    "Test-step-one": [
      ENV_VARS:[
        "test_one_var_from_jenkinsfile3=var3", 
        "test_one_var_from_jenkinsfile4=var4",
        "test_one_var_from_jenkinsfile5=var5"
      ]
    ],
    "Test-step-two": [
      ENV_VARS:[
        "test_two_var_from_jenkinsfile3=var3", 
        "test_two_var_from_jenkinsfile4=var4",
        "test_two_var_from_jenkinsfile5=var5"
      ]
    ]

and module Test-step/Test-step.groovy

withEnv(CFG.'ENV_VARS') {
  container("proteus") {
    sh "env | grep test"
  }
}

and MPLPipeline with 2 stages with use the same module 'Test-step' but should pass different CFG settings

stage('Test-step-one') {
   when { expression { MPLModuleEnabled() } }
  steps {
    MPLModule('Test-step')
  }
}
stage('Test-step-two') {
  when { expression { MPLModuleEnabled() } }
  steps {
    MPLModule('Test-step')
  }
}

My expectation env vars in Test-step-one stage will be

"test_one_var_from_jenkinsfile3=var3", 
"test_one_var_from_jenkinsfile4=var4",
"test_one_var_from_jenkinsfile5=var5"

and in Test-step-two will be

"test_two_var_from_jenkinsfile3=var3", 
"test_two_var_from_jenkinsfile4=var4",
"test_two_var_from_jenkinsfile5=var5"

But it will be error, because it will try to search variables by Test-step name in CFG Map not by name of stage Test-step-one or Test-step-two https://github.com/griddynamics/mpl/blob/master/vars/MPLModule.groovy#L45 https://github.com/griddynamics/mpl/blob/master/src/com/griddynamics/devops/mpl/MPLManager.groovy#L86 Or i miss something and exist the way how to pass env vars from Jenkinsfile to container using same module without modifying files in MPL?

sparshev commented 5 years ago

Hi @emelianrus

Looks like you trying to use stages of MPL in a tricky way: use the same module for different stages - depends on the purpose it could be fine or not, so I will try to explain both ways.

As you can see - the purpose of "modules" in the pipeline configuration is to provide some stage-specific configs. If module name is found in modules - it will override the basic configuration stored in the pipeline just for the module. In your case the module name is not the stage name, because you specify it during call of MPLModule.

The easiest way for you is to manually get the required module configuration using MPL object in the pipeline - this logic will ensure module "Test-step" will use configuration for the current stage:

...
stage('Test-step-one') {
  when { expression { MPLModuleEnabled() } }
  steps {
    MPLModule('Test-step', MPL.moduleConfig(env.STAGE_NAME))
  }
}
...

But, MPL stage purpose - is to separate different stages of the pipeline (build/deploy/test for example). If you try to separate different tests and just use different configs - I could suggest to put this logic into your pipeline config/modules and execute as a part of one stage (do not use MPL "module" pipeline logic). So all your custom logic will be stored in the Test module, that will run ExecuteTest common module with the required configs.

So my general advice - put the custom logic into module and process the configuration as you wish - use "modules" pipeline config just to put some different configurations for different stages (for example different credential ids for Build and Deploy stages).

emelianrus commented 5 years ago

got it, thanks