Deklaratywny a skryptowy rurociąg - Kluczowe różnice

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

Wybór odpowiedniego podejścia programistycznego do projektu jest kluczowy dla jego sukcesu. W tym artykule wyjaśniamy, czym jest Jenkins pipeline oraz jakie są różne typy pipelines w tym narzędziu open source. Dowiedz się, czym różni się scripted pipeline od declarative pipeline.

Tworząc Jenkins pipeline, inżynierowie mają wybór – mogą zdecydować się na zbudowanie scripted pipeline lub declarative pipeline. W Jenkins pipeline można krótko zdefiniować jako zbiór zdarzeń/zadań powiązanych ze sobą. Celem tej kombinacji pluginów jest wsparcie wdrażania i integracji continuous delivery pipelines. Możesz zdecydować się na stworzenie Jenkins scripted pipeline lub declarative pipeline. Aby dowiedzieć się więcej o tych dwóch rozwiązaniach, porównajmy: Jenkins declarative vs scripted pipeline.

Czym jest Jenkins?

Jeśli szukasz narzędzia open source do automatyzacji dla swojej firmy, warto rozważyć Jenkins. To narzędzie automatyzujące oparte na Javie upraszcza proces integracji i dostarczania oprogramowania dzięki Continuous Integration i Continuous Delivery. Jest to bardzo popularne narzędzie w procesach CI/CD, szczególnie ze względu na funkcje takie jak scripted i declarative pipelines. Jenkins pipelines ułatwiają proces dostarczania i pomagają firmom szybko wdrożyć DevOps.

Pipeline scripting

Zanim wybierzesz, które rozwiązanie jest lepsze – scripted czy declarative pipeline – musisz zrozumieć, czym jest Jenkins Pipeline i dlaczego jest potrzebny. Zacznijmy od continuous delivery pipeline – to proces dostarczania oprogramowania z systemu kontroli wersji bezpośrednio do użytkowników i klientów. Obejmuje on wszelkie workflow, aktywności i automatyzacje potrzebne do przeniesienia nowej funkcjonalności od pomysłu do wydania. Wyobraź sobie zestaw pluginów wspierających wdrażanie i integrację continuous delivery pipelines w Jenkins. Pipeline można zaimplementować jako kod DSL (Domain Specific Language) w Jenkins File (plik tekstowy definiujący pipeline). Możesz użyć tego pliku do zapisania kroków potrzebnych do uruchomienia Jenkins Pipeline. Dzięki temu możesz automatycznie budować pipelines dla wszystkich branchy i wykonywać pull requesty za pomocą jednego Jenkins File.

Jenkins pipeline – declarative vs scripted pipelines

Jenkins pozwala użytkownikom korzystać z dwóch typów pipelines – declarative lub scripted. Warto porównać declarative vs scripted pipelines, aby poznać różnice przed wyborem odpowiedniej składni. Scripted pipeline był jedyną dostępną opcją, gdy Jenkins pojawił się jako narzędzie open source. Declarative pipeline pojawił się później i zyskuje na popularności.

Scripted pipeline

Początkowo Jenkins pozwalał pisać pipeline tylko jako kod, czyli scripted pipeline. Taki pipeline zapisuje się w Jenkins File w web UI narzędzia Jenkins. Możesz napisać scripted pipeline w DSL (domain specific language) i użyć składni opartej na Groovy. Groovy to język programowania oparty na JVM. Używając go w scripted Jenkins pipeline, zyskujesz dostęp do szerokiego zestawu API dostępnych w Java Development Kit (JDK).

Jak każde rozwiązanie, scripted pipeline w Jenkins ma swoje zalety i wady.

Zalety scripted pipeline:

  • Użycie DSL (domain specific language) upraszcza wiele zadań dla developera Jenkins.
  • Kod Groovy można wstrzykiwać do pipelines w dowolnym momencie.
  • Daje dużą kontrolę nad skryptem i pozwala budować złożone pipelines w kodzie.

Wady scripted pipeline:

  • Wielu specjalistów IT zna Java i Groovy, ale osoby bez doświadczenia z Jenkins często piszą zbyt skomplikowany kod Groovy, dodając funkcjonalności już dostępne przez Jenkins DSL.
  • Nie ma formalnej struktury czy przepływu, co może prowadzić do powstawania niestabilnego kodu pipeline, trudnego w utrzymaniu i interpretacji.
Declarative pipeline script

Declarative pipelines to stosunkowo nowa funkcja w Jenkins. Dzięki niej kod pipeline jest łatwiejszy do napisania i późniejszego odczytu. Jednak jest to quid pro quo – kod jest uproszczony, bo składnia declarative jest bardziej ograniczona. Nie można wstrzykiwać kodu do pipelines w dowolnym momencie. Ten model nie jest najlepszy, jeśli planujesz budować pipeline o złożonej logice.

Czy declarative pipeline to nowoczesny sposób budowania pipelines?

  • Mimo wielu ograniczeń, declarative pipelines stały się standardem w rozwoju pipelines.
  • Dzięki declarative syntax zyskujesz bardziej uporządkowane i prostsze pipelines.
  • Declarative pipelines mają integrację z interfejsem Blue Ocean.

Czy są powody, by nie używać declarative pipeline w Jenkins?

  • Nie wszystkie pluginy są kompatybilne z Declarative Pipelines.
  • Declarative syntax jest bardziej restrykcyjna, więc ogranicza swobodę developera.

Scripted vs declarative pipelines w Jenkins – różnice

Jakie są główne różnice? Oto najważniejsze rzeczy, które warto wiedzieć:

  • Declarative i scripted pipelines różnią się podejściem programistycznym: jeden używa modelu deklaratywnego, drugi imperatywnego.
  • Declarative pipelines dzielą stages na wiele kroków, w scripted pipelines nie jest to wymagane.

Przykład

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()
        }
    }
}

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()
        }
    }
}


W rzeczywistości różnice są subtelne. Wydajność, skalowalność i elastyczność obu typów Jenkins pipelines są podobne, ale… choć może się wydawać, że declarative pipelines dają developerom mniej swobody niż scripted pipelines, wielu uważa, że nowe rozwiązanie Jenkins jest lepsze od pierwotnego.

Czy declarative pipeline jest lepszy od scripted pipeline?

Declarative pipeline używa prostszej i bardziej restrykcyjnej składni do tworzenia Jenkins Pipeline. Deklaratywny charakter tego rozwiązania narzuca ograniczenia i zmusza developera do pracy w ramach zdefiniowanych struktur. Dzięki prostocie jest to świetny wybór do budowy nieskomplikowanych continuous delivery pipelines. Model Jenkins scripted pipeline polecany jest tym, którzy mają wiele specyficznych wymagań wobec swojego pipeline. Możesz też połączyć oba podejścia, używając declarative pipelines z krokiem script(), by uruchomić stworzony scripted pipeline.

Jak zwykle, wybór odpowiedniego rozwiązania zależy od wymagań projektu oraz umiejętności, doświadczenia i preferencji developera. Jeśli nie znalazłeś wszystkich odpowiedzi w tym artykule, zajrzyj na naszego bloga lub skontaktuj się z nami – chętnie przeanalizujemy Twoje potrzeby i pomożemy rozwiązać wyzwania.

Skorzystaj z naszego bloga, aby znaleźć więcej artykułów na temat Databricks:

Share this post
Nauka o danych
Laura Kszczanowicz
MORE POSTS BY THIS AUTHOR
Laura Kszczanowicz

Curious how we can support your business?

TALK TO US