• Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • workflow-cps-plugin
    • None

      As with JENKINS-26481 the eachLine-method on String only works for the first iteration.

      Using version 3.39

      We use a cleanup-pipeline to find all running docker-containers without a corresponding feature-branch (deleted after merge).

      stage('clean') {
       def branches = []
       // extract available branches from git
       sh (returnStdout: true, script: "ssh-agent bash -c 'ssh-add /var/lib/jenkins/.ssh/id_rsa &>/dev/null; git ls-remote --heads --refs ssh://git@myrepo/project.git' | cut -f 2")
        .eachLine { branches << it }
       // extract all containers (including stopped)
       def containers = []
       sh (returnStdout: true, script: "docker ps -a --format '{{.Names}}' --filter name=project")
        .trim()
        .eachLine { containers << it }
       println(containers) // <---- only prints first container
       println(branches) // <---- only prints first branch
      
       //stop containers for non existing branches...
       containers.each{ containername ->
        if(branches.findAll({branch -> branch.contains(containername)}).isEmpty()){
         println("trying to stop ${containername}")
         //sh ("docker stop ${containername} || true") // container might already be stopped
         println("removing ${containername}")
         //sh ("docker rm ${containername}")
        }
       }
      }

      As a workaround replace eachLine with split('\n').each { ... }

          [JENKINS-46988] String.eachLine only reads first line

          Marc Schlegel created issue -
          Marc Schlegel made changes -
          Description Original: As with JENKINS-26481 the eachLine-method on String only works for the first iteration.

          Using version 3.39

          We use a cleanup-pipeline to find all running docker-containers without a corresponding feature-branch (deleted after merge).
          {code:java}
          stage('clean') {
           def branches = []
           // extract available branches from git
           sh (returnStdout: true, script: "ssh-agent bash -c 'ssh-add /var/lib/jenkins/.ssh/id_rsa &>/dev/null; git ls-remote --heads --refs ssh://git@myrepo/project.git&#39; | cut -f 2")
            .eachLine { branches << it }
           // extract all containers (including stopped)
           def containers = []
           sh (returnStdout: true, script: "docker ps -a --format '{{.Names}}' --filter name=project")
            .trim()
            .eachLine { containers << it }
           println(containers) // <---- only prints first container
           println(branches) // <---- only prints first branch

           //stop containers for non existing branches...
           containers.each{ containername ->
            if(branches.findAll({branch -> branch.contains(containername)}).isEmpty()){
             println("trying to stop ${containername}")
             //sh ("docker stop ${containername} || true") // container might already be stopped
             println("removing ${containername}")
             //sh ("docker rm ${containername}")
            }
           }
          }{code}
          New: As with -JENKINS-26481- the eachLine-method on String only works for the first iteration.

          Using version 3.39

          We use a cleanup-pipeline to find all running docker-containers without a corresponding feature-branch (deleted after merge).
          {code:java}
          stage('clean') {
           def branches = []
           // extract available branches from git
           sh (returnStdout: true, script: "ssh-agent bash -c 'ssh-add /var/lib/jenkins/.ssh/id_rsa &>/dev/null; git ls-remote --heads --refs ssh://git@myrepo/project.git&#39; | cut -f 2")
            .eachLine { branches << it }
           // extract all containers (including stopped)
           def containers = []
           sh (returnStdout: true, script: "docker ps -a --format '{{.Names}}' --filter name=project")
            .trim()
            .eachLine { containers << it }
           println(containers) // <---- only prints first container
           println(branches) // <---- only prints first branch

           //stop containers for non existing branches...
           containers.each{ containername ->
            if(branches.findAll({branch -> branch.contains(containername)}).isEmpty()){
             println("trying to stop ${containername}")
             //sh ("docker stop ${containername} || true") // container might already be stopped
             println("removing ${containername}")
             //sh ("docker rm ${containername}")
            }
           }
          }{code}
          As a workaround replace _eachLine_ with _split('\n').each \{ ... }_

          I lost an afternoon to this bug and it's real and still open. The workaround mentioned of the split each works great. Just chiming in that this does actually need to be fixed.

          Kevin Nuckolls added a comment - I lost an afternoon to this bug and it's real and still open. The workaround mentioned of the split each works great. Just chiming in that this does actually need to be fixed.

          Katie Sissons added a comment -

          Chiming in as well, having the same issue. Example:

          	def tagged_branches = sh(returnStdout: true, script: "git branch --contains tags/${tag_name}")
          	println tagged_branches
          	tagged_branches.eachLine {
          		println it
          	}
          

          Outputs:

          12:36:41  + git branch --contains tags/v0.6.20
          12:36:41  [Pipeline] echo
          12:36:41    feature/install_from_net_drive
          12:36:41  * master
          12:36:41  
          12:36:42  [Pipeline] echo
          12:36:42    feature/install_from_net_drive
          12:36:42  [Pipeline] }
          12:36:42  [Pipeline] // script
          12:36:42  [Pipeline] }
          

          Katie Sissons added a comment - Chiming in as well, having the same issue. Example: def tagged_branches = sh(returnStdout: true , script: "git branch --contains tags/${tag_name}" ) println tagged_branches tagged_branches.eachLine { println it } Outputs: 12:36:41 + git branch --contains tags/v0.6.20 12:36:41 [Pipeline] echo 12:36:41 feature/install_from_net_drive 12:36:41 * master 12:36:41 12:36:42 [Pipeline] echo 12:36:42 feature/install_from_net_drive 12:36:42 [Pipeline] } 12:36:42 [Pipeline] // script 12:36:42 [Pipeline] }

          Just ran into this issue as well, but got this nice warning in the Jenkins output which helped me find the cause (i.e. this issue):

          expected to call java.lang.String.eachLine but wound up catching org.jenkinsci.plugins.workflow.cps.CpsClosure2.call; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/

          Stefan Thurnherr added a comment - Just ran into this issue as well, but got this nice warning in the Jenkins output which helped me find the cause (i.e. this issue): expected to call java.lang.String.eachLine but wound up catching org.jenkinsci.plugins.workflow.cps.CpsClosure2.call; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/

          node {
             def data = """# some useless text
                           |# even more
                           |finally interesting text"""
          data.eachLine { String line ->
            println line
          }
          
          }
          

          Same issue when we execute the above script.

          expected to call java.lang.String.eachLine but wound up catching org.jenkinsci.plugins.workflow.cps.CpsClosure2.call; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
          

          Rakesh Nagarajan added a comment - node { def data = """# some useless text |# even more |finally interesting text""" data.eachLine { String line -> println line } } Same issue when we execute the above script. expected to call java.lang.String.eachLine but wound up catching org.jenkinsci.plugins.workflow.cps.CpsClosure2.call; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/

          Workaround is working really fine

          As a workaround replace eachLine with split('\n').each { ... }

           

          Rakesh Nagarajan added a comment - Workaround is working really fine As a workaround replace eachLine with split('\n').each { ... }  

          Jo Rhett added a comment - - edited

          I don't feel that this issue is Minor, nor do I feel that the workaround is an acceptable solution. This basically means that every Jenkins user worldwide will burn some hours diagnosing this problem only to end up here.

          That this bug is more than 2 years old speaks to a significant lack of care.

          Jo Rhett added a comment - - edited I don't feel that this issue is Minor, nor do I feel that the workaround is an acceptable solution. This basically means that every Jenkins user worldwide will burn some hours diagnosing this problem only to end up here. That this bug is more than 2 years old speaks to a significant lack of care.

          I'd like to affirm the previous comment.  I just did exactly that – I spent a couple of hours trying to figure out why my code wasn't working, and ended up here when I realized it was a bug in the Jenkins groovy interpreter for scripted pipelines.

          Andrew Lawrence added a comment - I'd like to affirm the previous comment.  I just did exactly that – I spent a couple of hours trying to figure out why my code wasn't working, and ended up here when I realized it was a bug in the Jenkins groovy interpreter for scripted pipelines.

          Likewise. Just burned a bit of time on this. Moving to the workaround.

          Dominique Thornton added a comment - Likewise. Just burned a bit of time on this. Moving to the workaround.

            Unassigned Unassigned
            lostiniceland Marc Schlegel
            Votes:
            32 Vote for this issue
            Watchers:
            26 Start watching this issue

              Created:
              Updated: