Declarative Pipeline im Vergleich zu skriptgesteuerten Pipelines — Hauptunterschiede

Laura Kszczanowicz
Laura Kszczanowicz
May 22, 2025
8 min read
Loading the Elevenlabs Text to Speech AudioNative Player...

Die Wahl des richtigen Programmieransatzes für ein Projekt ist entscheidend für dessen Erfolg. In diesem Artikel erklären wir, was eine Jenkins Pipeline ist und welche verschiedenen Pipeline-Typen es in diesem Open-Source-Tool gibt. Erfahren Sie die Unterschiede zwischen einer scripted pipeline und einer declarative pipeline.

Wenn Sie eine Jenkins Pipeline erstellen, haben die Entwickler die Wahl – sie können eine scripted pipeline oder eine declarative pipeline bauen. In Jenkins kann eine Pipeline kurz als eine Sammlung von Ereignissen/Jobs definiert werden, die miteinander verknüpft sind. Ziel dieser Plugin-Kombination ist es, die Implementierung und Integration von continuous delivery pipelines zu unterstützen. Sie können sich entscheiden, eine Jenkins scripted pipeline oder eine declarative pipeline zu erstellen. Um mehr über diese beiden Lösungen zu erfahren, vergleichen wir: Jenkins declarative vs scripted pipeline.

Was ist Jenkins?

Wenn Sie ein Open-Source-Automatisierungstool für Ihr Unternehmen suchen, sollten Sie Jenkins in Betracht ziehen. Dieses Java-basierte Automatisierungstool vereinfacht den Software-Integrations- und Delivery-Prozess durch Continuous Integration und Continuous Delivery. Es ist ein weit verbreitetes Tool im CI/CD-Prozess, insbesondere wegen seiner speziellen Features wie scripted und declarative pipelines. Jenkins pipelines erleichtern den Delivery-Prozess und helfen Unternehmen, DevOps schnell einzuführen.

Pipeline scripting

Bevor Sie entscheiden, was besser ist – scripted oder declarative pipeline – müssen Sie verstehen, was eine Jenkins Pipeline ist und warum Sie eine brauchen. Beginnen wir mit einer continuous delivery pipeline – das ist der Prozess, Ihre Software direkt aus der Versionskontrolle zu den Nutzern und Kunden zu bringen. Sie umfasst alle Arten von Workflows, Aktivitäten und Automatisierungen, die erforderlich sind, um neue Funktionalitäten von der Idee bis zum Release zu bringen. Stellen Sie sich eine Reihe von Plugins vor, die die Implementierung und Integration von continuous delivery pipelines in Jenkins unterstützen. Die Pipeline kann als DSL (Domain Specific Language) Code in einer Jenkins File (Textdatei, die die Pipeline definiert) implementiert werden. Sie können diese Datei verwenden, um die Schritte für die Ausführung einer Jenkins Pipeline zu schreiben. So können Sie Pipelines automatisch für alle Branches erstellen und Pull Requests mit nur einer Jenkins File ausführen.

Jenkins pipeline – declarative vs scripted pipelines

Jenkins ermöglicht es Benutzern, einen von zwei Pipeline-Typen zu verwenden – declarative oder scripted. Sie sollten declarative vs scripted pipelines vergleichen, um die Unterschiede zu verstehen, bevor Sie sich für eine Syntax entscheiden. Die scripted pipeline war die einzige verfügbare Option, als Jenkins als Open-Source-Automatisierungstool eingeführt wurde. Die declarative pipeline kam später und wird immer beliebter.

Scripted pipeline

Ursprünglich erlaubte Jenkins nur das Schreiben der Pipeline als Code, also als scripted pipeline. Eine solche Pipeline wird in einer Jenkins File in der Web-UI von Jenkins geschrieben. Sie können eine scripted pipeline mit DSL (domain specific language) und Groovy-basierter Syntax schreiben. Groovy ist eine auf der JVM basierende Programmiersprache. Durch die Verwendung in einer scripted Jenkins pipeline erhalten Sie Zugriff auf die umfangreichen APIs des Java Development Kit (JDK).

Wie jede Lösung hat auch die scripted pipeline in Jenkins ihre Vor- und Nachteile.

Vorteile der scripted pipeline:

  • Die Verwendung von DSL (domain specific language) vereinfacht viele Aufgaben für Jenkins-Entwickler.
  • Groovy-Code kann jederzeit in die Pipelines injiziert werden.
  • Sie bietet große Kontrolle über das Skript und ermöglicht den Aufbau komplexer Pipelines im Code.

Nachteile der scripted pipeline:

  • Es gibt viele IT-Experten mit Java- und Groovy-Kenntnissen, aber diejenigen ohne Jenkins-Erfahrung schreiben oft zu komplexen Groovy-Code, um Funktionen hinzuzufügen, die bereits durch Jenkins DSL verfügbar sind.
  • Es gibt keine formale Struktur oder Ablauf, was zu instabilem Pipeline-Code führen kann, der schwer zu warten oder zu interpretieren ist.
Declarative pipeline script

Declarative pipelines sind eine relativ neue Funktion in Jenkins. Dank dieser Option ist der Pipeline-Code leichter zu schreiben und später zu lesen. Allerdings ist das ein quid pro quo – der Code ist vereinfacht, weil die declarative Syntax stärker eingeschränkt ist. Sie können keinen Code jederzeit in die Pipelines injizieren. Dieses Modell ist nicht die beste Wahl, wenn Sie eine Pipeline mit komplexer Logik erstellen möchten.

Ist die declarative pipeline der moderne Weg, Pipelines zu bauen?

  • Trotz vieler Einschränkungen sind declarative pipelines bereits zum Standard in der Pipeline-Entwicklung geworden.
  • Mit declarative syntax erhalten Sie strukturiertere und einfachere Pipelines.
  • Declarative pipelines sind mit der Blue Ocean-Oberfläche integriert.

Gibt es Gründe, keine declarative pipeline in Jenkins zu verwenden?

  • Nicht alle Plugins sind mit Declarative Pipelines kompatibel.
  • Die declarative syntax ist strikter, was die Freiheit des Entwicklers einschränkt.

Scripted vs declarative pipelines in Jenkins – Unterschiede

Was sind die Hauptunterschiede? Hier die wichtigsten Punkte:

  • Declarative und scripted pipelines unterscheiden sich im Programmieransatz: eine verwendet das deklarative, die andere das imperative Modell.
  • Declarative pipelines unterteilen stages in mehrere Schritte, bei scripted pipelines ist das nicht erforderlich.

Beispiel für eine declarative pipeline:

pipeline {
    agent {
        // executes on an executor with the label 'some-label' or 'docker'
        label "some-label || docker"
    }
    
    // Define environment variables that will be used across stages
    environment {
        DOCKER_IMAGE = 'ubuntu'
    }
    
    stages {
        stage("foo") {
            steps {
                script {
                    // Create docker image and store its reference
                    def dockerImage = docker.image(DOCKER_IMAGE)
                    
                    // Store image name in environment variable for cross-stage access
                    env.DOCKER_IMAGE_NAME = dockerImage.imageName()
                    
                    // Echo the image name
                    echo "foo: ${dockerImage.imageName()}"
                }
            }
        }
        
        stage("bar") {
            steps {
                script {
                    // Access environment variable set in previous stage
                    echo "bar: ${env.DOCKER_IMAGE_NAME}"
                    
                    // If docker image name is needed, access it through environment variable
                    echo "docker image: ${env.DOCKER_IMAGE_NAME}"
                }
            }
        }
    }
    
    // Optional post section for actions to be taken after pipeline completion
    post {
        success {
            echo 'Pipeline executed successfully!'
        }
        failure {
            echo 'Pipeline execution failed!'
        }
        always {
            // Cleanup steps if needed
            cleanWs()
        }
    }
}

Scripted pipelines erlauben das Injizieren von Code, was bei declarative Jenkins pipeline nicht möglich ist. Beispiel:

node {
    // Stage for SCM checkout
    stage('Checkout') {
        // Clone the repository
        git url: 'https://github.com/jfrogdev/project-examples.git'
    }

    // Stage for Artifactory configuration
    stage('Configure Artifactory') {
        // Get Artifactory server instance, defined in the Artifactory Plugin administration page
        def server = Artifactory.server "SERVER_ID"

        // Define download specification
        def downloadSpec = """
            {
                "files": [
                    {
                        "pattern": "libs-snapshot-local/*.zip",
                        "target": "dependencies/",
                        "props": "p1=v1;p2=v2"
                    }
                ]
            }
        """

        // Define upload specification
        def uploadSpec = """
            {
                "files": [
                    {
                        "pattern": "resources/Kermit.*",
                        "target": "libs-snapshot-local",
                        "props": "p1=v1;p2=v2"
                    },
                    {
                        "pattern": "resources/Frogger.*",
                        "target": "libs-snapshot-local"
                    }
                ]
            }
        """

        try {
            // Download artifacts from Artifactory
            stage('Download from Artifactory') {
                echo "Starting download from Artifactory..."
                def buildInfo1 = server.download spec: downloadSpec
                echo "Download completed successfully"
            }

            // Upload artifacts to Artifactory
            stage('Upload to Artifactory') {
                echo "Starting upload to Artifactory..."
                def buildInfo2 = server.upload spec: uploadSpec
                echo "Upload completed successfully"

                // Merge the upload and download build-info objects
                buildInfo1.append buildInfo2

                // Publish the build information to Artifactory
                server.publishBuildInfo buildInfo1
                echo "Build info published successfully"
            }
        } catch (Exception e) {
            currentBuild.result = 'FAILURE'
            error "Failed to process Artifactory operations: ${e.message}"
        }
    }

    // Post-build actions
    post {
        success {
            echo 'Artifactory operations completed successfully'
        }
        failure {
            echo 'Artifactory operations failed'
        }
        always {
            // Cleanup workspace
            cleanWs()
        }
    }
}

Tatsächlich sind die Unterschiede subtil. Die Laufzeitleistung, Skalierbarkeit und Flexibilität beider Jenkins pipeline-Typen sind ähnlich, aber… obwohl es scheint, dass declarative pipelines Entwicklern weniger Freiheit geben als scripted pipelines, sagen viele, dass die neue Jenkins-Funktionalität besser ist als die ursprüngliche Lösung.

Ist eine declarative pipeline besser als eine scripted pipeline?

Eine declarative pipeline verwendet eine einfachere und strengere Syntax für die Erstellung einer Jenkins Pipeline. Der deklarative Charakter dieser Lösung schränkt ein, was der Entwickler tun kann, und zwingt ihn, innerhalb vordefinierter Strukturen zu arbeiten. Aufgrund ihrer Einfachheit ist sie eine gute Wahl für die Entwicklung nicht-komplexer continuous delivery pipelines. Das Jenkins scripted pipeline-Modell wird für diejenigen empfohlen, die viele spezifische Anforderungen an ihre Pipeline haben. Sie können auch einen „Best of both worlds“-Ansatz wählen, indem Sie declarative pipelines mit dem script()-Schritt verwenden, um eine scripted pipeline auszuführen.

Wie immer hängt die Wahl der richtigen Lösung von den spezifischen Anforderungen des Projekts sowie den Fähigkeiten, der Erfahrung und den Vorlieben des Entwicklers ab. Wenn Sie in diesem Artikel nicht alle Antworten gefunden haben, schauen Sie auf unserem Blog vorbei oder kontaktieren Sie uns direkt – wir analysieren gerne Ihre Bedürfnisse und helfen Ihnen, Herausforderungen zu meistern.


In unserem Blog finden Sie ausführlichere Artikel zu Databricks:

Share this post
Datenwissenschaft
Laura Kszczanowicz
MORE POSTS BY THIS AUTHOR
Laura Kszczanowicz

Curious how we can support your business?

TALK TO US