The most surprising thing about CircleCI’s continuation orb is that it doesn’t actually run anything itself; it’s purely a signaling mechanism that delegates execution to other jobs.
Let’s see it in action. Imagine you have a multi-stage deployment process. You want to build your Docker image, push it to a registry, and then deploy to different environments (staging, then production). We can use the continuation orb to chain these steps together, ensuring they run sequentially and only proceed if the previous stage succeeds.
Here’s a simplified .circleci/config.yml demonstrating this:
version: 2.1
orbs:
continuation: circleci/continuation@0.3.0
docker: circleci/docker@1.1.0
jobs:
build-docker:
docker:
- image: cimg/base:stable
steps:
- checkout
- setup_remote_docker
- docker/build:
image: my-repo/my-app
tag: ${CIRCLE_SHA1}
- docker/push:
image: my-repo/my-app
tag: ${CIRCLE_SHA1}
- continuation/continue:
configuration_path: .circleci/staging_deployment.yml
deploy-staging:
docker:
- image: cimg/base:stable
steps:
- checkout
- run: echo "Deploying to staging..."
- run: echo "Deployment to staging complete."
- continuation/continue:
configuration_path: .circleci/production_deployment.yml
deploy-production:
docker:
- image: cimg/base:stable
steps:
- checkout
- run: echo "Deploying to production..."
- run: echo "Deployment to production complete."
workflows:
build-and-deploy:
jobs:
- build-docker
In this setup, the build-docker job, after successfully building and pushing the image, uses continuation/continue to trigger a new workflow defined in .circleci/staging_deployment.yml. This file would contain the deploy-staging job. Once deploy-staging completes, it would similarly trigger the deploy-production job via another continuation configuration.
The core problem this solves is managing complex, multi-job pipelines without a monolithic configuration file. As your deployment stages grow, trying to define them all in one config.yml becomes unwieldy and difficult to maintain. The continuation orb allows you to break down your pipeline into smaller, manageable YAML files, each representing a distinct stage or set of jobs. This modularity is key for clarity and reusability.
Internally, when a continuation/continue step executes, CircleCI doesn’t run the jobs defined in the referenced file directly within the current job’s context. Instead, it takes the YAML content from the configuration_path, parses it, and then schedules new jobs based on that content to run in a new pipeline execution. The original pipeline execution that invoked the continuation step then terminates. The configuration_path is simply the location of the next part of your pipeline definition. You can even use templating or dynamic generation to create these continuation configuration files on the fly.
The configuration_path parameter is crucial; it points to a valid CircleCI configuration file that will be loaded and executed as the next step in the sequence. This file can define new jobs, workflows, or even include other orbs, effectively allowing you to build arbitrarily complex pipelines by chaining together smaller configuration fragments. The filter parameter within the continuation/continue step is surprisingly powerful, allowing you to conditionally trigger subsequent pipeline configurations based on branch, tag, or even environment variables, giving you fine-grained control over your pipeline flow.
Once you’ve mastered chaining workflows with the continuation orb, you’ll likely start looking into how to pass complex state or artifacts between these dynamically generated pipeline segments.