# Jenkins

### Environment variables

[video](https://www.youtube.com/watch?v=KwQDxwZRZiE) [blog](https://e.printstacktrace.blog/jenkins-pipeline-environment-variables-the-definitive-guide/)

[GitHub repo](https://github.com/bhuvanchandmaddi/Jenkins-tutorials/blob/main/Jenkinsfile-environment-vars-demo)

* In echo variables can be accessed using either ${env.variable\_name} or ${variable\_name}
    
* In sh variables can only be accessed using ${variable\_name}
    
* stage-level environment block variables can override pipeline-level (global) environment block variables
    
* But env variables inside script block cannot override global-env or stage-env variables
    
* variables inside withEnv block can override all levels of env vars.
    
* If we assign a true or false value to a variable. It will be treated as a string. You need to typecast explicitly using toBoolean()
    
* Generally sh won\`t return any output, so if you want to get any output out of sh use it with a script like this  
    **COUNT\_FILES= sh(script: "ls -la /tmp | tail -n +4 | wc -l", returnStdout: true)**
    
* Take care when using a null value, because if a function returns null and you capture it in a variable. It is most likely to store a string with the value null. Use Elvis operator as shown below
    
* If you want to access variable inside a script of particular stage outside its scope(i.e. any where in the pipeline including post block then create a variable using env and assign it to that)  
    EG: In Jenkins pipelines, variables defined within a `script` block using `def` are scoped to that block. This means that you won't be able to access them outside of that `script` block directly. However, if you want to access a variable in the `post` block, you can set it as an environment variable or use other mechanisms to make it globally accessible.
    
    Here are a couple of methods to achieve this:
    
    1. **Using** `env` **to Set Environment Variables**:
        
        Inside your `script` block, you can set the variable as an environment variable using the `env` global variable. This way, the value becomes accessible throughout the Jenkins pipeline, including in the `post` block.
        
        ```c
        groovyCopy codestage('Some Stage') {
            steps {
                script {
                    def myLocalVar = "someValue"
                    env.MY_GLOBAL_VAR = myLocalVar
                }
            }
        }
        
        post {
            always {
                script {
                    echo "Value of MY_GLOBAL_VAR: ${env.MY_GLOBAL_VAR}"
                }
            }
        }
        ```
        
        * In Jenkins, parameters declared for a pipeline are automatically made available as environment variables. This means if you have a parameter named `MY_PARAM`, you can access its value anywhere in the pipeline script using [`env.MY`](http://env.MY)`_PARAM`.
            
            Here's an example of how you can use pipeline parameters:
            
            ```c
            groovyCopy codepipeline {
                agent any
            
                parameters {
                    string(name: 'MY_PARAM', defaultValue: 'Default Value', description: 'A description of my parameter')
                }
            
                stages {
                    stage('Print Parameter') {
                        steps {
                            echo "Parameter value is: ${env.MY_PARAM}"
                        }
                    }
            
                    stage('Another Stage') {
                        steps {
                            script {
                                if (env.MY_PARAM == 'SomeValue') {
                                    echo "Parameter is set to SomeValue"
                                } else {
                                    echo "Parameter is set to something else"
                                }
                            }
                        }
                    }
                }
            
                post {
                    always {
                        echo "Post block: Parameter value is: ${env.MY_PARAM}"
                    }
                }
            }
            ```
            
            **Very very Imp:**
            
            <mark>In a Jenkins pipeline, you can access environment variables inside a </mark> `script` <mark> block as well as inside an </mark> `sh` <mark> step. Environment variables can be accessed using the </mark> `env` <mark> prefix.</mark>
            
            Here are some examples to illustrate this:
            
            ### **1\. Accessing** `env` variable inside a `script` block:
            
            ```c
            groovyCopy codepipeline {
                agent any
                environment {
                    MY_ENV_VAR = 'Hello from env'
                }
                stages {
                    stage('Demo Stage') {
                        steps {
                            script {
                                echo "Accessing env variable in script block: ${env.MY_ENV_VAR}"
                            }
                        }
                    }
                }
            }
            ```
            
            ### **2\. Accessing** `env` variable inside an `sh` step within a `script` block:
            
            ```c
            groovyCopy codepipeline {
                agent any
                environment {
                    MY_ENV_VAR = 'Hello from env'
                }
                stages {
                    stage('Demo Stage') {
                        steps {
                            script {
                                echo "Accessing env variable in script block: ${env.MY_ENV_VAR}"
            
                                // Accessing inside sh step
                                sh """
                                echo "Accessing env variable in sh block: $MY_ENV_VAR"
                                """
                            }
                        }
                    }
                }
            }
            ```
            
            Note that when you access the environment variable inside the `sh` step, you don't need to use the `env` prefix. You can simply reference the variable by its name.
            
            However, remember that this works because Groovy is interpolating the variable inside the double-quoted string (`"""..."""`). If you used single quotes (`'''...'''`), the variable would not be interpolated.
            
            ## **The code snippet used in the video**
            
    
    ```c
    pipeline{
    
        agent { label 'slave' }
        environment{
            // Available to all stages
            NAME = "Bhuvan"
            ID = 90
        }
        stages{
            stage("Print default vars"){
                steps{
                    sh 'printenv | sort'
                }
            }
            
             stage("Use Env vars"){
                environment{
                    // Available to this particular stage only
                    NAME ="Chand"
                    ID = 30
                }
                steps{
                    // Here env is optional we can use ${BUILD_NUMBER} directly but it is best practice to use env.
                    echo "Build Number = ${env.BUILD_NUMBER}"
                    echo "Build Number(without env.) = ${BUILD_NUMBER}"
                    
                    // It overrides global username
                    echo "NAME = ${env.NAME}" // chand
                    // For shell we don`t use env. If we use we ill get error
                    sh 'echo ${NAME}' // chand
                    
                    // Even number will be treated as string, as you can see here
                    echo "ID = ${env.ID} and its type is ${env.ID.class}" //ID = 30 and its type is class java.lang.String
                    
                    script{
                        env.GROUP_NAME = "test-group"
                        env.TRIGGER_NEXT=true
                        env.NAME = "dummy-name"
                    }
                    echo "Group name =${env.GROUP_NAME}" // test-group
                    sh 'echo group name is ${GROUP_NAME}' // test-group
                    // script block cannot overide name
                    echo "NAME is: ${env.NAME}" // chand
                    
                    withEnv(["USER_PWD=secret","USER_IS_ADMIN=false","NAME=Maddi"]){
                    echo "user password is: ${env.USER_PWD}" // secret
                    sh 'echo user is admin?: ${USER_IS_ADMIN}' // false
                    echo "Name is: ${env.NAME}" // Maddi
                    }
                }
            }
            
            stage("Using boolean env vars"){
                when{
                    expression{
                       // env.TRIGGER_NEXT == true --> This will result in error because env.TRIGGER_NEXT will be treated as a string
                        env.TRIGGER_NEXT.toBoolean() == true
                    }
                }
                // other way is to use when {environmanet name: "TRIGGER_NEXT", value = "true" and set value in script block to string by double quoating "true"}
                steps {
                    echo "Type of trigger next is: ${env.TRIGGER_NEXT.class}"
                    echo "Type of trigger next is: ${env.TRIGGER_NEXT.toBoolean().class}"
                }
                
            }
            stage("capturing output from other step"){
                environment{
                    // By default sh doesn`t return anything so sh 'ls -la /tmp | tail -n +4 | wc -l' output will be null.
                    COUNT_FILES= sh(script: "ls -la /tmp | tail -n +4 | wc -l", returnStdout: true)
                }
                steps{
                    echo "No of files in /tmp folder are: ${env.COUNT_FILES}"
                }
            }
            stage("Handling null values"){
                environment{
                    // SOME_VAL = someVal() //It captures string(null value string with 4 characters) not null 
                    // This is elvis opetaror. Refere blog: https://blog.mrhaki.com/2009/08/groovy-goodness-elvis-operator.html  
                    SOME_VAL = "${someVal() ?: ''}"
                }
                steps{
                    echo "The value of someval is ${env.SOME_VAL} and its type is ${env.SOME_VAL?.class}"
                }
            }
            
        }
    }
    def someVal(){
        return null
    }
    ```
    
    ### Script and steps blocks:
    
    Use steps block inside the stage wherever possible. If something cannot be achieved using the steps block then use the script block. You can even use scripts bloc within steps.
    
    1. **Using Only** `steps` **Block:** This is the most common and recommended way to define steps in a Declarative pipeline. You can define individual steps directly within the `steps` block without using a separate `script` block.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        echo "Hello from the steps block!"
                        sh 'ls -la'
                    }
                }
            }
        }
        ```
        
    2. **Using Only** `script` **Block:** If you need to execute complex scripted Groovy code or use scripted pipeline steps that are not available as Declarative steps, you can use only a `script` block. In this case, the `steps` block is not required.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    script {
                        echo "Hello from the script block!"
                        sh 'ls -la'
                    }
                }
            }
        }
        ```
        
    3. **Using** `script` **Inside** `steps` Block: You can use a `script` block within a `steps` block when you need to perform complex or custom logic for a specific step.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        script {
                            echo "Running complex logic here..."
                            def result = sh(returnStdout: true, script: 'echo "Hello from the script!"').trim()
                            echo "Script Result: ${result}"
                        }
                        echo "Continuing with regular steps..."
                    }
                }
            }
        }
        ```
        
    4. **Using Multiple** `script` **Blocks Inside** `steps` Block: You can use multiple `script` blocks within a `steps` block when you have separate steps that require custom scripted logic.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        script {
                            echo "Step 1: Performing a custom action..."
                        }
                        script {
                            echo "Step 2: Running a custom script..."
                            sh 'ls -la'
                        }
                    }
                }
            }
        }
        ```
        
    
    Remember that while the `script` block allows you to perform advanced and custom logic, it's best to use Declarative pipeline steps whenever possible. Declarative steps provide better readability and maintainability, and using them follows the spirit of the Declarative pipeline approach. Reserve the `script` block for situations where you genuinely need scripted Groovy code or require specific scripted pipeline steps that are not available in Declarative steps.
    
    ### Capturing the output or return code of a command
    
    **Capturing the exit status**: If you want to capture the exit status of the shell command (0 for success, non-zero for failure), you can use the returnStatus option. When returnStatus is true, the sh step will return the exit status of the command instead of its output. Here's an example:
    
    ```c
    pipeline {
        agent any
        stages {
            stage('Example') {
                steps {
                    script {
                        def exitStatus = sh(returnStatus: true, script: 'ls some_nonexistent_directory')
                        if (exitStatus == 0) {
                            echo "Command succeeded!"
                        } else {
                            echo "Command failed with exit code: ${exitStatus}"
                        }
                    }
                }
            }
        }
    }
    ```
    
    **Capturing the command output:** If you want to capture the output (standard output) of the shell command, you can assign the `sh` step to a variable. The `sh` step will return the output as a string. Here's an example:
    
    ```c
    groovyCopy codepipeline {
        agent any
        stages {
            stage('Example') {
                steps {
                    script {
                        def commandOutput = sh(script: 'echo "Hello, Jenkins!"', returnStdout: true).trim()
                        echo "Command output: ${commandOutput}"
                    }
                }
            }
        }
    }
    ```
    
    ### Script Block
    
    In Jenkins, the `script` block is a section in a Jenkins pipeline where you can write and execute arbitrary Groovy code. The `script` block is used when you need to perform more complex logic or need access to the underlying Jenkins API that is not available directly in declarative pipeline steps.
    
    1. **Within a** `steps` **block:** Although most steps in Declarative pipelines are designed to work without needing a `script` block, there may be situations where you want to include one within the `steps` block. This can be useful if you need to perform more complex logic. Here's an example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        script {
                            // Your scripted Groovy code here
                            def message = "Hello, Jenkins!"
                            echo message
                        }
                    }
                }
            }
        }
        ```
        
    2. **Within a** `post` **block:** The `post` block allows you to define actions that should be executed after the entire pipeline or specific stages have completed. If you need to include scripted Groovy logic in a post-action, you can use a `script` block within the `post` block. Here's an example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        // Your regular steps here
                    }
                }
            }
            post {
                always {
                    script {
                        // Your scripted Groovy code here
                        echo "This will always run, regardless of the pipeline result."
                    }
                }
                success {
                    script {
                        // Your success-specific scripted Groovy code here
                        echo "This will run only if the pipeline is successful."
                    }
                }
                failure {
                    script {
                        // Your failure-specific scripted Groovy code here
                        echo "This will run only if the pipeline fails."
                    }
                }
            }
        }
        ```
        
    
    Please note that while the `script` block can be powerful, it's best to use Declarative pipeline steps whenever possible, as they provide a higher level of abstraction and better readability. Only use the `script` block when you need to perform advanced or custom logic that cannot be achieved using regular Declarative pipeline steps.
    
    ### Functions & Conditional statements
    
    Functions blog: [here](https://naiveskill.com/jenkins-pipeline-functions/)  
    Conditional statements(if/else and when) blog: [here](https://naiveskill.com/jenkins-pipeline-if-statement/)
    
    Note: If you want to capture the return type of any function. There are 2 ways.
    
    1. If you are using steps{} block(declarative syntax with simple logic). use def in front of a variable name as shown.
        
        ```c
        def myFunction() {
            return "Hello from the function!"
        }
        
        pipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        // Calling the function directly in the steps block
                        def result = myFunction()
                        echo "Function Return Value: ${result}"
                    }
                }
            }
        }
        ```
        
    2. If you are using script block then no worries. You can directlyc capture it
        
        ```c
        def mul()
        {
           def a=2
           def b=3
           def mul=a*b
           return mul
        }
        
        pipeline {
            agent any
            stages {
                stage('Hello') {
                    steps{
                        script{
                          output= mul()
                          echo "The mul is ${output}"
                    }
                    }
                }
            }
            }
        ```
        
    
    ### Scope of variables in Jenkins Declarative pipeline
    
    1. **Variables in a Stage:** Variables defined within a stage using the `environment` directive are only available within that stage. They are not accessible in other stages or post blocks. This is because each stage in a Declarative pipeline runs in a separate workspace and has its own environment.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Stage 1') {
                    environment {
                        MY_VARIABLE = "Value 1"
                    }
                    steps {
                        echo "Variable in Stage 1: ${MY_VARIABLE}"
                    }
                }
                stage('Stage 2') {
                    steps {
                        echo "Variable in Stage 2: ${MY_VARIABLE}"  // This will not work
                    }
                }
            }
        }
        ```
        
    2. **Variables in a Script Block:** Variables defined(using def) inside a `script` block within a stage or post block have local scope and are limited to that specific block. They are not accessible outside of the block.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Example') {
                    steps {
                        script {
                            def localVariable = "Local Value"
                            echo "Local Variable: ${localVariable}"
                        }
                    }
                }
            }
            post {
                always {
                    script {
                        echo "Post Block Variable: ${localVariable}"  // This will not work
                    }
                }
            }
        }
        ```
        
        **Note**: However if you want to use a variable defined in stage 1 in stage 2, then you need to use env variable in stage 1 instead of local def.  
        Example:  
        Here's an example using environment variables to share data between stages:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Stage 1') {
                    steps {
                        script {
                            // Define a variable in Stage 1
                            env.MY_VARIABLE = 'Data from Stage 1'
                        }
                    }
                }
                stage('Stage 2') {
                    steps {
                        script {
                            // Access the variable defined in Stage 1
                            def dataFromStage1 = env.MY_VARIABLE
                            echo "Data from Stage 1: ${dataFromStage1}"
                        }
                    }
                }
            }
        }
        ```
        
        In this example, `MY_VARIABLE` is defined in "Stage 1" and then accessed in "Stage 2" using the `env` object. This allows you to pass data between stages through environment variables.
        
    3. **Variables in Nested Stages and Post Blocks:** Variables defined within nested stages or post blocks have the same scope rules as described above. Nested stages or post blocks do not have access to variables defined in their parent stages or vice versa.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                stage('Parent Stage') {
                    steps {
                        script {
                            def parentVariable = "Parent Value"
                            echo "Parent Variable: ${parentVariable}"
                        }
                    }
                    stage('Nested Stage') {
                        steps {
                            script {
                                def nestedVariable = "Nested Value"
                                echo "Nested Variable: ${nestedVariable}"
                                echo "Parent Variable in Nested Stage: ${parentVariable}"  // This will not work
                            }
                        }
                    }
                }
            }
        }
        ```
        
    4. you can access variables defined in the parent stage using the `environment` block within a nested stage. The `environment` block defined at the parent stage level will be available to all child stages within that stage's workspace.
        
    
    Here's the updated example to demonstrate this:
    
    ```c
    groovyCopy codepipeline {
        agent any
        stages {
            stage('Parent Stage') {
                environment {
                    PARENT_VARIABLE = "Parent Value"
                }
                steps {
                    echo "Parent Variable: ${PARENT_VARIABLE}"
                }
                stage('Nested Stage') {
                    steps {
                        script {
                            echo "Nested Variable: ${PARENT_VARIABLE}"  // This will work
                        }
                    }
                }
            }
        }
    }
    ```
    
    In conclusion, variables defined in one stage or context (e.g., script block) are not directly accessible in other stages, nested stages, or post blocks. If you need to share data between different stages, you can use external means like writing to files, using Jenkins workspace, or using shared libraries. Alternatively, you can also pass parameters between stages using the `input` step or using the `stash` and `unstash` steps to move files between stages.
    
    **Note**: If we declare a variable using def then only that variable can be accessed within script block. But if we define a variable without def just like other variable then it can be accessed outside of the script block as well. See in below example
    
    ```c
    pipeline {
        agent any
        stages {
            stage('Example') {
                steps {
                    script {
                        // Local variable declaration within the script block
                        def localVariable = "Local Value"
                        NORMAL_VAR = "Normal var"
                        echo "Local Variable: ${localVariable}" // Local Value
                        // Since NORMAL_VAR is in script block don1t use env. before variable name which resolves to null
                        echo "Normal variable: ${NORMAL_VAR}" // Normal var
                        echo "Normal variable with env: ${env.NORMAL_VAR}" //null
                    }
                    // Since NORMAL_VAR is in script block don1t use env. before variable name which resolves to null
                    echo "Normal Variable outside script block: ${NORMAL_VAR}" // Normal var
    
                }
            }
        }
    }
    ```
    
    ### Post block
    
    In Jenkins Declarative pipeline, the `post` block is used to define actions that should be executed after the main stages of the pipeline have been completed. It allows you to specify different behaviours based on the outcome of the pipeline or specific stages within the pipeline. The `post` block contains one or more postconditions, which can be associated with a specific result (e.g., success, failure) or run unconditionally.
    
    The syntax of the `post` block is as follows:
    
    ```c
    groovyCopy codepipeline {
        // Pipeline configuration
    
        post {
            // Post conditions go here
        }
    }
    ```
    
    Within the `post` block, you can define different sections, each associated with a specific outcome of the pipeline run. The available sections are:
    
    1. `always`**:** The `always` section specifies actions that should be executed regardless of the pipeline result. This section is always executed, regardless of whether the pipeline is successful or not.
        
        ```c
        groovyCopy codepost {
            always {
                // Actions to run always
            }
        }
        ```
        
    2. `success`**:** The `success` section specifies actions that should be executed only if the pipeline is successful (i.e., all stages are completed without any failure).
        
        ```c
        groovyCopy codepost {
            success {
                // Actions to run on successful pipeline
            }
        }
        ```
        
    3. `failure`**:** The `failure` section specifies actions that should be executed only if the pipeline fails (i.e., at least one stage fails).
        
        ```c
        groovyCopy codepost {
            failure {
                // Actions to run on failed pipeline
            }
        }
        ```
        
    4. `unstable`**:** The `unstable` section specifies actions that should be executed if the pipeline result is unstable (e.g., some tests failed, but the build itself succeeded).
        
        ```c
        groovyCopy codepost {
            unstable {
                // Actions to run on unstable pipeline
            }
        }
        ```
        
    5. `changed`**:** The `changed` section specifies actions that should be executed only if the state of the pipeline has changed from the previous run. This can be useful when triggering actions based on code changes or other external factors.
        
        ```c
        groovyCopy codepost {
            changed {
                // Actions to run if the pipeline state has changed
            }
        }
        ```
        
    6. **Combining Post Conditions:** You can combine multiple post conditions within the `post` block to specify different actions based on different pipeline outcomes.
        
        ```c
        groovyCopy codepost {
            always {
                // Actions to run always
            }
            success {
                // Actions to run on successful pipeline
            }
            failure {
                // Actions to run on failed pipeline
            }
        }
        ```
        
    
    Remember that each section of the `post` block is optional, and you can include only the sections that are relevant to your pipeline. The sections are executed in the order they are defined.
    
    The `post` block is a powerful feature in Declarative pipelines that allows you to handle post-build actions efficiently and cleanly. It can be used to perform tasks such as sending notifications, cleaning up resources, publishing reports, and more based on the pipeline's results.
    
    ### Commonly used pre-defined function
    
    In Jenkins Declarative pipeline, there are indeed some commonly used predefined functions and steps that are specifically designed to be used within the `post` block. Here are a few of them:
    
    1. `cleanWs`**:** The `cleanWs` function is used to clean up the workspace at the end of a pipeline run. It helps to free up disk space by deleting the workspace of the current build.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                // Define stages
            }
            post {
                always {
                    cleanWs()
                }
            }
        }
        ```
        
    2. `archiveArtifacts`**:** The `archiveArtifacts` step is used to archive artifacts (e.g., build outputs) after a successful build. The artifacts can be accessed later or used for deployments.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                // Define stages
            }
            post {
                success {
                    archiveArtifacts artifacts: '**/*.jar', allowEmptyArchive: true
                }
            }
        }
        ```
        
    3. `mail`**:** The `mail` step is used to send an email notification after the pipeline run. It is useful for notifying team members or stakeholders about the build result.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                // Define stages
            }
            post {
                failure {
                    mail to: 'team@example.com', subject: 'Pipeline Failed', body: 'The pipeline has failed.'
                }
            }
        }
        ```
        
    4. `slackSend`**:** The `slackSend` step is used to send messages to Slack channels. It is helpful for integrating Jenkins with Slack for build notifications.
        
        Example:
        
        ```c
        groovyCopy codepipeline {
            agent any
            stages {
                // Define stages
            }
            post {
                always {
                    slackSend message: 'Pipeline completed.', channel: '#build-notifications'
                }
            }
        }
        ```
        
    
    These are just a few examples of commonly used predefined functions and steps in the `post` block of Jenkins Declarative pipeline. There are many more available, and you can find additional functions provided by plugins or write your own custom functions as needed. The `post` block is a powerful mechanism to execute specific actions based on the outcome of the pipeline, and it enables you to perform various post-build tasks like cleanup, notifications, archiving, etc.
    

### Multi Branch pipeline

[Article](https://valaxytech.medium.com/multibranch-pipeline-on-jenkins-with-webhook-a65decede4f8) [Video](https://www.youtube.com/watch?v=fo36b23cpIU)

### Environment variables available throughout the pipeline:

* Environment variables defined in the below 3 ways can be accessed anywhere in the pipeline.  
    1\. global environment block  
    2\. external files
    
    3\. pipeline parameters
    
    **Eg: Supply environment variables using external file using load**  
    In a Jenkins Declarative Pipeline, you can use the `load` step to read and evaluate Groovy scripts from external files. This can be useful for modularizing your pipeline code or for reading configuration or shared code from external files. Here's how you can use the `load` step:
    
    1. Create an external Groovy script file. This file can contain any Groovy code you want to use in your pipeline. For example, you can create a file named `myScript.groovy` with the following content:
        
    
    ```c
    // App vars
    env.APP_NAME = 'dummy-app'
    ```
    
    1. In your Jenkins Declarative Pipeline script, use the `load` step to load and evaluate the external script file. You can then call functions or use variables defined in the loaded script:
        
    
    ```c
    pipeline {
        agent any
        stages {
            stage('Load Script') {
                steps {
                    script {
                       load("myScript.groovy")   
                       echo "App name: ${env.APP_NAME}"
                    }
                }
            }
        }
    }
    ```
    
    In this example, we load the `myScript.groovy` file using `load`, and then we call the env.APP\_NAME variable defined in that external script.
    
    Make sure the external script file is located in the same directory as your Jenkinsfile or provide the full path to the script file if it's located elsewhere. Additionally, ensure that the script file is secure and trusted, as loading external scripts can introduce security risks.
    
* So when the same variable is declared in all 3 places. Then the precedence order will be like this.  
    **Global env &gt;&gt; external file &gt;&gt; pipeline parameters**
    
* **Example:** Extend the above example by providing the same APP\_NAME env in other 2 locations i.e. global environment block and pipeline parameter.
    
* ```c
        pipeline {
            agent any
            environemnt {
            APP_NAME = "dummy value from global env block"
            } 
            stages {
                stage('Load Script') {
                    steps {
                        script {
                           load("myScript.groovy")   
                           echo "App name: ${env.APP_NAME}"
                        }
                    }
                }
            }
        }
    ```
    
    Defined a string parameter to the pipeline with the same value
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696429567413/a0727a7b-11e2-489e-b4be-246dfd1e9a9c.png align="center")
    
    **case 1:** If I trigger the pipeline now then I will get "dummy value from global env block" as ouput(since it has highest precedence)
    
    **case 2:** comment envi block var and the trigger pipeline again, then you will get "dummy app" from the external file as output
    
    **case3:** Now comment the external file value also and trigger pipeline finally you will get "dummy app from params"
