Sergey Nivens - Fotolia
Declarative vs. scripted pipelines: What's the difference?
Scripted pipelines were once the standard for CI/CD but they are nearly extinct, and since supplanted by declarative pipelines. See how they compare and when each works best.
Jenkins provides two different syntaxes for pipelines. When DevOps engineers write a Jenkins pipeline, they can choose between declarative and scripted. The differences between the two are both subtle and significant.
Let's explore how declarative vs. scripted pipelines differ in Jenkins development, and what developers need to know before they choose the syntax.
Groovy scripted pipelines
When the Jenkins pipeline was first introduced, the scripted pipeline was the only available option. Software developers enthusiastically embraced the scripted pipeline for two big reasons:
- It provided a domain specific language that simplified many tasks a Jenkins developer would perform.
- At the same time, it allowed developers to inject Groovy code into their pipelines any time.
Groovy is a JVM-based programming language, which means a scripted Jenkins pipeline that uses Groovy has access to the vast array of APIs that are packaged with the JDK. The scripted pipeline developer has an immense amount of power.
Too much power, in fact.
Scripted pipeline drawbacks
The development community found that pipeline builders with strong Java and Groovy skills, but little experience with Jenkins, would often write complicated Groovy code to add functionality that's already available through the Jenkins DSL.
A Jenkins pipeline should be a simple, easy-to-read and easy-to-manage component. Excessive code in a scripted pipeline violates one of the fundamental CI/CD principles.
As a result, Jenkins corrected this trend when it introduced the declarative pipeline.
Declarative vs. scripted pipelines
In contrast to the scripted pipeline, the declarative Jenkins pipeline doesn't permit a developer to inject code. A Groovy script or a Java API reference in a declarative pipeline will cause a compilation failure.
While this restriction might sound limiting on the surface, it's not.
The Jenkins DSL provides a variety of facilities to introduce simple conditional logic. A declarative pipeline supports conditional statement usage, allows access to environment variables and provides facilities to add logging and error handling. The tradeoff is that declarative pipelines don't allow deep integration into Groovy and Java APIs.
But what about those difficult corner cases that can only be addressed when a developer accesses the rich set of APIs provided by the Groovy and Java programming languages? Won't the inability to write Groovy code on a pipeline limit its ability to solve the difficult and challenging CI/CD problems that inevitably arise in the enterprise?
The short answer is no, it does not.
Simply put, never put complex code into a pipeline, regardless of whether it seems possible. Jenkins provides several ways to make complex logic available to both scripted and declarative pipelines. One approach to isolate complex code is to code the logic into a Jenkins plugin. It provides the added benefit of reusability across multiple Jenkins installations. Jenkins also supports shared libraries, which allow developers to write and maintain complex code in a standard IDE, which can then be referenced through an import in a build pipeline.
It's always been a best practice to keep complex code out of a Jenkins pipeline. The declarative pipeline simply enforces this.
The same, but different
Scripted vs. declarative pipelines are different only in their programmatic approach. One uses a declarative programming model, while the other uses an imperative programming model.
But they both run on the same Jenkins pipeline sub-system. There are no differences in the runtime performance, scalability and problem solvability perspective in the declarative vs. scripted pipeline debate. They only differ in the syntactic approach used to achieve an end goal.
Pipeline syntax differences
Declarative pipelines always begin with the word pipeline. Scripted pipelines, on the other hand, always begin with the word node. Declarative pipelines break down stages into individual stages that can contain multiple steps. Scripted pipelines use Groovy code and references to the Jenkins pipeline DSL within the stage elements without the need for steps.
These are the key differences that allow a developer to quickly differentiate between a scripted pipeline and a declarative pipeline.
Now what about the choice between declarative vs. scripted pipelines for a new project? The answer to that question is most definitely the declarative pipeline.
The development industry has largely moved toward a declarative programming model for CI/CD pipelines. Both GitHub Actions and GitLab CI support only YAML pipelines, which are very similar to declarative Jenkins pipelines.
Furthermore, declarative pipelines are easier to maintain and they tend to have a lower learning curve. The declarative syntax is the best approach to use when new CI/CD workflows are built.
Dig Deeper on DevOps-driven, cloud-native app development
Related Q&A from Cameron McKenzie
What are checked vs. unchecked exceptions in Java?
Understand the difference between checked and unchecked exceptions in Java, and learn how to handle these problem conditions properly and gracefully. Continue Reading
Git fork vs. clone: What's the difference?
Both Git fork and clone create copies of a repository, but they offer drastically different levels of access, isolation and control over the target ... Continue Reading
Kebab vs. camel case: How these naming conventions differ
What is the difference between a variable written in kebab case vs. camel case? Here we'll show you how these naming conventions differ and when to ... Continue Reading