Add stages to Jenkins declarative pipeline through shared library Is there a way to write a stage in a Jenkins shared library so that it can be added to declarative pipelines?
Background
For many projects, I need to run tests on multiple different servers.  My solution is to create a bunch of parallel stages, one for each of the servers that I want to run on.  I've gotten to this pipeline (running on 2 servers as an example):
pipeline {
    agent any
    stages {
        stage('Test') {
            parallel {
                stage('San Jose') {
                    agent {
                        label &quot;test &amp;&amp; san-jose&quot;
                    }
                    steps {
                        sh 'run-tests'
                    }
                }
                stage('Dallas') {
                    agent {
                        label 'test dallas'
                    }
                    steps {
                        sh 'run-tests'
                    }
                }
            }
        }
    }
}

Which is great, but I'd really like to keep my code DRY and not have to copy and paste this Test stage to every project I have (especially since this has to run on about 10 servers, with only the label changing each time).
I could put the whole pipeline into my shared libary (like Jenkins's example in the documentation), but then I can't customize the other stages (for example, adding a release stage).
What I'd really like to do is this:
pipeline {
    agent any
    stages {
        runOnServers {
            sh 'run-tests'
        }
        stage('Release') {
            echo 'release'
        }
    }
}

Question
Is there a way I can do this?
Yes, but (to the best of my knowledge) you will have to use Scripted Pipeline within the shared library.  This means that the closure that you will pass to the shared library (in the below example, the closure is sh 'run-tests') will also have to be Scripted.
Jenkinsfile:
pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                runOnServers {
                    sh 'run-tests'
                }
            }
        }
        stage('Release') {
            echo 'release'
        }
    }
}

In your shared library, a file named vars/runOnServers.groovy:
def call(Closure closure) {
  parallel({
    SanJose: {
      node(&quot;test &amp;&amp; san-jose&quot;) {
        stage('SanJose') {
          closure()
        }
      } 
    },
    Dallas: {
      node('test dallas') {
        stage('Dallas') {
          closure()
        }
      } 
    } 
  } 
}