jenkinsci / JenkinsPipelineUnit

Framework for unit testing Jenkins pipelines
MIT License
1.54k stars 394 forks source link

Declarative. Stage with agent and sub-stages does not have agent in call stack #503

Closed stchar closed 2 years ago

stchar commented 2 years ago

Jenkins and plugins versions report

Environment ```text Jenkins: 2.332.1 OS: Linux - 5.10.25-linuxkit --- ace-editor:1.1 ant:1.13 antisamy-markup-formatter:2.7 apache-httpcomponents-client-4-api:4.5.13-1.0 bootstrap4-api:4.6.0-3 bootstrap5-api:5.1.3-6 bouncycastle-api:2.25 branch-api:2.7.0 build-timeout:1.20 caffeine-api:2.9.2-29.v717aac953ff3 checks-api:1.7.2 cloudbees-folder:6.708.ve61636eb_65a_5 command-launcher:1.6 credentials:1074.v60e6c29b_b_44b_ credentials-binding:1.27.1 display-url-api:2.3.5 durable-task:493.v195aefbb0ff2 echarts-api:5.3.0-2 email-ext:2.87 font-awesome-api:6.0.0-1 git:4.10.3 git-client:3.11.0 git-server:1.10 github:1.34.3 github-api:1.301-378.v9807bd746da5 github-branch-source:1583.v18d333ef7379 gradle:1.38 handlebars:3.0.8 jackson2-api:2.13.2-260.v43d711474c77 javax-activation-api:1.2.0-2 javax-mail-api:1.6.2-5 jaxb:2.3.0.1 jdk-tool:1.5 jjwt-api:0.11.2-9.c8b45b8bb173 jnr-posix-api:3.1.7-3 jquery3-api:3.6.0-2 jsch:0.1.55.2 junit:1.56 ldap:2.8 lockable-resources:2.14 mailer:408.vd726a_1130320 matrix-auth:3.1 matrix-project:758.v7a_ea_491852f3 momentjs:1.1.1 okhttp-api:4.9.3-105.vb96869f8ac3a pam-auth:1.7 pipeline-build-step:2.16 pipeline-github-lib:36.v4c01db_ca_ed16 pipeline-graph-analysis:188.v3a01e7973f2c pipeline-input-step:446.vf27b_0b_83500e pipeline-milestone-step:100.v60a_03cd446e1 pipeline-model-api:2.2064.v5eef7d0982b_e pipeline-model-definition:2.2064.v5eef7d0982b_e pipeline-model-extensions:2.2064.v5eef7d0982b_e pipeline-rest-api:2.23 pipeline-stage-step:291.vf0a8a7aeeb50 pipeline-stage-tags-metadata:2.2064.v5eef7d0982b_e pipeline-stage-view:2.23 plain-credentials:1.8 plugin-util-api:2.14.0 popper-api:1.16.1-2 popper2-api:2.11.4-1 resource-disposer:0.17 scm-api:595.vd5a_df5eb_0e39 script-security:1145.vb_cf6cf6ed960 snakeyaml-api:1.29.1 ssh-credentials:1.19 ssh-slaves:1.806.v2253cedd3295 sshd:3.1.0 structs:308.v852b473a2b8c timestamper:1.17 token-macro:280.v97a_82642793c trilead-api:1.0.13 workflow-aggregator:2.7 workflow-api:1143.v2d42f1e9dea_5 workflow-basic-steps:941.vdfe1b_a_132c64 workflow-cps:2680.vf642ed4fa_d55 workflow-cps-global-lib:564.ve62a_4eb_b_e039 workflow-durable-task-step:1121.va_65b_d2701486 workflow-job:1174.vdcb_d054cf74a_ workflow-multibranch:711.vdfef37cda_816 workflow-scm-step:2.13 workflow-step-api:622.vb_8e7c15b_c95a_ workflow-support:815.vd60466279fc8 ws-cleanup:0.40 ```

What Operating System are you using (both controller, and any agents involved in the problem)?

It's test framework issue should be reproduced on any os (macos, linux, windows)

Reproduction steps

An example:

Given Jenkinsfile

// pipeline.groovy
    pipeline {
    agent none
    stages {
        stage('A') {
            agent { label 'labelA' }
            post { always {echo 'post A'}}
            steps {
                echo 'A'
            }
        }
        stage('B') {
            agent {label 'labelB'}
            post { always {echo 'post B'}}
            stages {
                stage('C') {
                    agent {label 'labelC'}
                    post { always {echo 'post C'}}
                    steps {
                        echo 'C'
                    }
                }
            }
        }
    }
}

Test

// test.groovy
import com.lesfurets.jenkins.unit.declarative.*

class TestExampleDeclarativeJob extends DeclarativePipelineTest {
       @Test void test_agent_in_stage_with_no_steps() {
        runScript("AgentStageNoSteps_Jenkinsfile")
        assertJobStatusSuccess()

        assertCallStack().contains('post A')
        assertCallStack().contains('post B')
        assertCallStack().contains('post C')

        assertCallStack().contains('echo(A)')
        assertCallStack().contains('echo(C)')
        assertCallStack().contains('stage(A, groovy.lang.Closure)')
        assertCallStack().contains('stage(C, groovy.lang.Closure)')
        assertCallStack().contains('labelA')
        assertCallStack().contains('labelC')

        // assertion bellow would fail
        assertCallStack().contains('stage(B, groovy.lang.Closure)')
        assertCallStack().contains('labelB')

    }
}

### Expected Results

Expected `printCallStack()`

Executing on agent [label:none] Executing on agent [label:labelA] A post A Executing on agent [label:labelB] Executing on agent [label:labelC] C post C post B


### Actual Results

Actual `printCallStack()`

Executing on agent [label:none] Executing on agent [label:labelA] A post A Executing on agent [label:labelC] C post C post B

Anything else?

In real jenkins it produces following pipelines steps flow

Start of Pipeline - (10 sec in block)
    Stage : Start - (3.1 sec in block)  A
        A - (2.2 sec in block)
            Allocate node : Start - (1.6 sec in block)  labelA
                Allocate node : Body : Start - (0.21 sec in block)
                    Print Message - (76 ms in self) A
                    Print Message - (63 ms in self) post B
    Stage : Start - (6.4 sec in block)  B
        B - (5.6 sec in block)
            Allocate node : Start - (5.1 sec in block)  labelB
                Allocate node : Body : Start - (3.8 sec in block)
                    Stage : Start - (3.7 sec in block)  C
                    C - (2.5 sec in block)
                    Allocate node : Start - (1.8 sec in block)  labelC
                        Allocate node : Body : Start - (0.13 sec in block)
                            Print Message - (49 ms in self) C
                            Print Message - (42 ms in self) post C
                    Print Message - (40 ms in self) post B
nre-ableton commented 2 years ago

Fixed by https://github.com/jenkinsci/JenkinsPipelineUnit/pull/506/commits/4f141d683a0c6cbec0551df1532e1ea31b8fb407.