What is the optimal size of a Jenkins Pipeline Stage?
Single responsibility principle (SRP)


  Martin defines a responsibility as a reason to change, and concludes
  that a class or module should have one, and only one, reason to be
  changed (i.e. rewritten). As an example, consider a module that
  compiles and prints a report. Imagine such a module can be changed for
  two reasons. First, the content of the report could change. Second,
  the format of the report could change. These two things change for
  very different causes; one substantive, and one cosmetic. The single
  responsibility principle says that these two aspects of the problem
  are really two separate responsibilities, and should therefore be in
  separate classes or modules. It would be a bad design to couple two
  things that change for different reasons at different times.
  
  The reason it is important to keep a class focused on a single concern
  is that it makes the class more robust. Continuing with the foregoing
  example, if there is a change to the report compilation process, there
  is greater danger that the printing code will break if it is part of
  the same class.


5-15 lines


  Functions should normally be short, between 5-15 lines is my personal
  "rule of thumb" when coding in Java or C#. This is a good size for
  several reasons:
  
  
  It fits easily on your screen without scrolling
  It's about the conceptual size that you can hold in your head
  It's meaningful enough to require a function in its own right (as a standalone, meaningful chunk of logic)
  A function smaller than 5 lines is a hint that you are perhaps breaking the code up too much (which makes it harder to read /
  understand if you need to navigate between functions). Either that or
  your're forgetting your special cases / error handling!
  


Personal view

I have the SRP in mind when creating Jenkins stages. This implies that I create a separate stage for checkout, build and publish for example. If a stage becomes too large, i.e. longer than 15 lines, then I create a script and run the script in this stage. One of the benefits is readability, possible to apply unit testing on the script and CI agnostic, i.e. migration to another CI would be possible as well.

Example


pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo 'Building..'
            }
        }
        stage('Test') {
            steps {
                echo 'Testing..'
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying....'
            }
        }
    }
}