Skip to content
Spinnaker pipelines as code
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Gradle build tidying Feb 25, 2019

Canal Spinnaker Pipeline DSL

Build Status

Canal - an artificial waterway constructed to allow the passage of boats or ships out to sea

Spinnaker pipelines are a great way to deploy your services to the cloud. There is already a beautiful UI for creating them and watching them execute.

Image of Spinnaker pipeline UI

Many people use the JSON representation of a pipeline as the source of truth for their pipelines in version control. But pipelines often get complicated and the JSON can get unruly.

Image of Spinnaker pipeline JSON UI

Canal allows you to actually write your pipeline description as code.

  • Use common programming constructs (loops, conditionals, composition...) for conciseness, reduced duplication, and reuse.
  • A compiler and IDE assistance help validate your pipeline as you write it.
  • Unit tests can make assertions on your pipeline structure and expression evaluations.

Image of Canal in Idea

If you have ever modified the pipeline JSON directly you will immediately notice how much simpler the pipeline definition below is over the equivalent JSON.

  • No longer required to maintain the tedious 'refId' and 'requisiteStageRefIds' relationships. Instead, build the stage graph implicitly with 'then' blocks.
  • Based on class and method definitions, gain an understanding of what attributes are available and which of those are required. The duplicate and unnecessary attributes are hidden from you.
  • Use String interpolation and any language feature of Kotlin when writing your pipelines.
pipeline("Canal Example") {
    stages = stages {
                                "\${ {'Corinth', 'Panama', 'Suez'}.contains(trigger['parameters']['canalName']) }"
                name = "Check canal name"
        ) then {
            stage(Wait(1), name = "Wait for decent weather")
            stage(Wait(2), name = "Wait for reservation #${reservationNumber}")
            stage(Wait(3), name = "Wait for lock to open")
        } then {
                    name = "Travel through canal"
                    org = "canal-pipelines",
                    repo = "canal"

You can already use Spring Expression Language (SpEL) in your pipeline to dynamically evaluate certain values. It can, however, be difficult to understand the results of more complicated expressions or even confirm they are valid. With Canal you can unit test the structure of your resulting pipeline including expression evaluations given a specific pipeline execution context.

val pipelineExecution = PipelineExecution(
                "parameters" to mapOf(
                        "canalName" to "Panama"
val evaluator = ExpressionEvaluator(pipelineExecution)

val evaluatedPipeline = evaluator.evaluate(pipeline)


Note that the example above is contrived. A real pipeline would likely involve triggering based on commit hooks, building an artifact, deploying that through environments (like test, stage, prod), and running integration tests along the way. This example was kept simple so that it could be put into Spinnaker and run quickly and without any modifications. Check out the unit tests for more examples.

You can’t perform that action at this time.