Jenkins Pipeline Syntax: Ein umfassender Leitfaden für Anfänger

Entmystifizieren Sie die Jenkins Pipeline-Syntax mit diesem umfassenden Leitfaden für Anfänger. Lernen Sie die Grundlagen von deklarativen und skriptbasierten Pipelines kennen, einschließlich Agents, Stages, Steps, Post-Actions, Environments, Parameters und Best Practices. Befähigen Sie sich, robuste CI/CD-Workflows effektiv mit praktischen Beispielen und umsetzbaren Ratschlägen zu erstellen.

Jenkins Pipeline-Syntax: Ein umfassender Leitfaden für Anfänger

Die Jenkins-Pipeline-Syntax ermöglicht es Ihnen, Ihren Build-, Test- und Bereitstellungsprozess in einer Jenkinsfile zu beschreiben, die mit Ihrem Code lebt. Das ist wichtig, weil Ihre Pipeline-Änderungen wie Anwendungscode überprüft, versioniert und zurückgesetzt werden können.

Wenn Sie neu bei Jenkins-Pipelines sind, beginnen Sie mit der deklarativen Pipeline-Syntax. Sie ist strukturiert, lesbar und deckt die meisten CI/CD-Workflows ab, ohne dass viel Groovy-Wissen erforderlich ist.

Deklarative vs. Skriptbasierte Pipeline

Jenkins unterstützt zwei Pipeline-Stile.

Die deklarative Pipeline verwendet eine strenge pipeline { ... }-Struktur. Sie ist die beste Standardeinstellung für die meisten Teams, da Jenkins die Form der Datei validieren und Stages sauber in der Benutzeroberfläche anzeigen kann.

Die skriptbasierte Pipeline verwendet Groovy innerhalb von node { ... }-Blöcken. Sie gibt Ihnen mehr Kontrolle, aber es ist einfacher, schwer wartbare Pipelines zu erstellen, wenn Ihr Team nicht mit Groovy vertraut ist.

Verwenden Sie zuerst die deklarative Pipeline. Greifen Sie nur dann zur skriptbasierten Pipeline, wenn Sie Logik benötigen, die die deklarative Pipeline nicht sauber ausdrücken kann.

Eine minimale deklarative Pipeline

Eine grundlegende Jenkinsfile hat einen Agenten, Stages und Steps:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo 'Building the application'
                sh 'mvn clean package'
            }
        }

        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
    }
}

agent any weist Jenkins an, die Pipeline auf jedem verfügbaren Agenten auszuführen. Jede stage wird in der Jenkins-Benutzeroberfläche separat angezeigt. Der steps-Block enthält die Befehle, die Jenkins ausführt.

Verwenden Sie auf Windows-Agenten bat anstelle von sh:

bat 'gradlew.bat test'

Die agent-Direktive

Die agent-Direktive legt fest, wo die Pipeline oder Stage ausgeführt wird.

Auf jedem verfügbaren Agenten ausführen:

agent any

Auf einem Agenten mit einem bestimmten Label ausführen:

agent { label 'linux && docker' }

Einen globalen Agenten überspringen und einen pro Stage auswählen:

pipeline {
    agent none

    stages {
        stage('Build') {
            agent { label 'linux' }
            steps {
                sh './build.sh'
            }
        }
    }
}

agent none ist nützlich, wenn verschiedene Stages unterschiedliche Umgebungen benötigen, z. B. Linux für Builds und Windows für Installertests.

Stages und Steps

Verwenden Sie Stages, um die Pipeline in Arbeit aufzuteilen, die ein Entwickler auf einen Blick verstehen kann: Checkout, Build, Test, Paketieren, Bereitstellen.

stages {
    stage('Checkout') {
        steps {
            checkout scm
        }
    }

    stage('Unit Tests') {
        steps {
            sh 'npm test'
        }
    }
}

Halten Sie Stages sinnvoll. Eine Stage namens Run mit fünfzig Befehlen ist schwer zu debuggen. Eine Pipeline mit zwanzig winzigen Stages ist unübersichtlich. Zielen Sie auf Stages ab, die echten Workflow-Meilensteinen entsprechen.

Umgebungsvariablen

Verwenden Sie environment für Werte, die mehrere Stages benötigen:

pipeline {
    agent any

    environment {
        APP_NAME = 'orders-api'
        IMAGE = "registry.example.com/team/orders-api:${env.BUILD_NUMBER}"
    }

    stages {
        stage('Build Image') {
            steps {
                sh 'docker build -t "$IMAGE" .'
            }
        }
    }
}

In Groovy-Strings können Sie Variablen über env.APP_NAME lesen. In Shell-Schritten exportiert Jenkins Umgebungsvariablen, sodass $APP_NAME und $IMAGE innerhalb der Shell funktionieren.

Legen Sie keine Geheimnisse in environment ab. Verwenden Sie Jenkins-Anmeldeinformationen mit withCredentials.

Parameter

Parameter ermöglichen es jemandem, Werte auszuwählen, wenn ein Build manuell gestartet wird:

pipeline {
    agent any

    parameters {
        string(name: 'BRANCH_NAME', defaultValue: 'main', description: 'Git branch to build')
        booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Run unit tests')
        choice(name: 'DEPLOY_ENV', choices: ['dev', 'staging', 'prod'], description: 'Target environment')
    }

    stages {
        stage('Show Inputs') {
            steps {
                echo "Branch: ${params.BRANCH_NAME}"
                echo "Deploy target: ${params.DEPLOY_ENV}"
            }
        }
    }
}

Verwenden Sie Parameter für Dinge, die zwischen den Läufen variieren sollten. Verwenden Sie sie nicht, um die Überprüfung von Produktionsänderungen zu umgehen.

Bedingte Stages mit when

Die when-Direktive steuert, ob eine Stage ausgeführt wird:

stage('Deploy to Production') {
    when {
        branch 'main'
    }
    steps {
        sh './deploy-prod.sh'
    }
}

Sie können auch einen Ausdruck verwenden:

stage('Test') {
    when {
        expression { return params.RUN_TESTS }
    }
    steps {
        sh 'npm test'
    }
}

Setzen Sie when auf die Stage, nicht innerhalb von steps.

Post-Aktionen

post-Blöcke werden ausgeführt, nachdem eine Stage oder Pipeline abgeschlossen ist. Sie sind nützlich zum Veröffentlichen von Testergebnissen, Archivieren von Build-Nachweisen und Bereinigen.

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
    }

    post {
        failure {
            echo 'Pipeline failed'
        }
        always {
            cleanWs()
        }
    }
}

junit veröffentlicht Testergebnisse, auch wenn Tests fehlschlagen. cleanWs() stammt aus dem Workspace Cleanup-Plugin, installieren Sie dieses Plugin also, bevor Sie es verwenden.

Optionen

Verwenden Sie options, um das Pipeline-Verhalten festzulegen:

pipeline {
    agent any

    options {
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '20'))
    }

    stages {
        stage('Build') {
            steps {
                sh './build.sh'
            }
        }
    }
}

Diese Optionen machen Logs lesbarer, stoppen hängende Builds, verhindern überlappende Ausführungen desselben Jobs und begrenzen den alten Build-Verlauf.

Eine praktische Anfänger-Pipeline

Dieses Beispiel checkt Code aus, erstellt ein Java-Projekt, veröffentlicht Testergebnisse und archiviert das gepackte JAR:

pipeline {
    agent { label 'linux' }

    options {
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }

        stage('Publish') {
            steps {
                junit 'target/surefire-reports/*.xml'
                archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
            }
        }
    }
}

Dies ist ein besserer Ausgangspunkt als eine riesige Bereitstellungs-Pipeline. Sobald der Build zuverlässig ist, fügen Sie Image-Veröffentlichung, Sicherheitsscans oder Bereitstellungs-Stages hinzu.

Grundlagen der skriptbasierten Pipeline

Eine einfache skriptbasierte Pipeline sieht so aus:

node('linux') {
    stage('Checkout') {
        checkout scm
    }

    stage('Build') {
        sh 'mvn clean package'
    }
}

Wickeln Sie keinen deklarativen pipeline {}-Block innerhalb einer skriptbasierten Pipeline ein. Halten Sie die beiden Stile getrennt, es sei denn, Sie haben einen bestimmten, getesteten Grund, kleine skriptbasierte Abschnitte innerhalb von deklarativen script { ... }-Blöcken zu mischen.

Gute Pipeline-Gewohnheiten

Speichern Sie die Jenkinsfile in der Versionskontrolle. Halten Sie Geheimnisse in Jenkins-Anmeldeinformationen. Geben Sie Stages Namen, die der Arbeit entsprechen, die sie ausführen. Veröffentlichen Sie Berichte in post-Blöcken, sodass Fehler immer noch nützliche Beweise hinterlassen. Fügen Sie Timeouts hinzu, bevor ein Build über Nacht hängen bleibt.

Die meisten Anfängerprobleme mit Pipelines resultieren aus versteckten Annahmen: Ein Tool existiert auf einem Agenten, aber nicht auf einem anderen, ein Geheimnis ist fest codiert, oder ein Bericht wird nur bei Erfolg veröffentlicht. Machen Sie diese Annahmen in der Pipeline explizit, und Jenkins wird viel vertrauenswürdiger.