> For the complete documentation index, see [llms.txt](https://circleci.com/docs/llms.txt)

# Using dynamic configuration

This page covers some dynamic configuration examples. The following examples are provided below:

*   [Pass parameters from setup to continuation workflow](#pass-parameters-to-continuation-workflow): In this example, a parameter is passed from the setup workflow to the continuation workflow using the continuation orb. The continuation workflow uses conditional logic to execute based on the parameter value.
    
*   [Continue a pipeline with a dynamically generated configuration file](#a-basic-example): In this example, a script is used to generate a YAML configuration file. The continuation orb is used to continue the pipeline using the generated configuration.
    
*   [Execute specific `workflows` or `steps` based on which files are modified](#execute-specific-workflows-or-steps-based-on-which-files-are-modified): In this example, two configuration files are used, a setup configuration and a continuation configuration. The path filtering orb is used to conditionally set pipeline parameters, and conditional workflow logic is used to generate and continue the pipeline based on the location of modified files.
    
*   [Generate a configuration file based on modified files](#generate-a-config-file-based-on-modified-files): In this example the continuation configuration is split into separate project-specific config files and a shared config file. Path filtering is used to generate a config file for continuation based on the location of modified files.
    
*   [Pack, generate, and validate a configuration file for pipeline continuation](#pack-generate-validate): In this example the continuation configuration is split into separate project-specific config files, and a shared config directory. Path filtering is used to pack, generate and validate a config file for continuation based on the location of modified files.
    

## Prerequisites

*   The content on this page assumes you have already read the [Dynamic Configuration](https://circleci.com/docs/guides/orchestrate/dynamic-config/) page.
    
*   If your project was created before December 1st 2023 you will need to enable dynamic configuration in your [Project Settings](https://circleci.com/docs/guides/orchestrate/dynamic-config/#enable-dynamic-config).
    

## Pass parameters from setup to continuation workflow

If you need to pass a parameter (and its associated value) from the setup workflow to the continuation workflow, you can leverage the `parameters` parameter of the continuation orb’s `continue` command.

Passing parameters is typically useful if you want the execution of the continuation workflow to depend on logic statements.

### Setup configuration: config.yml

The following example shows how to pass a parameter when continuing to a continuation workflow.

```yaml
version: 2.1

# define this file as the setup phase of your dynamic configuration
setup: true

# invoke the continuation orb to make the continuation/continue command available
orbs:
  continuation: circleci/continuation@1.1.0

jobs:
  set-param:
    docker:
      - image: cimg/node:24.0.1
    steps:
      - continuation/continue:
          parameters: '{ "further": true }'
          configuration_path: ./config_continue.yml

workflows:
  use-my-orb:
    jobs:
      - set-param
```

*   **Line 4**: Add the line `setup: true` to the top-level of the config, to designate it for use of CircleCI’s dynamic configuration feature.
    
*   **Line 8**: Invoke the `continuation` orb so we can use it.
    
*   **Lines 11-18**: Define a job called `set-param` that uses the continuation orb’s `continue` command to pass a parameter called `further` with a value of `true` to the continuation workflow.
    
*   **Line 16**: The `parameters` parameter accepts a JSON object as a string. Note the single quote encapsulating the full JSON object.
    

### Continuation configuration: config\_continue.yml

The continuation configuration receives the parameter passed from the setup configuration and uses conditional logic to determine whether to execute the workflow.

```yaml
version: 2.1

# define the parameter that will be passed from the setup workflow
parameters:
  further:
    type: boolean
    default: false

jobs:
  module-build:
    docker:
      - image: cimg/node:24.0.1
    steps:
      - run:
          name: Check directory
          command: pwd

workflows:
  module-workflow:
    when: << pipeline.parameters.further >>
    jobs:
      - module-build
```

*   **Lines 4-7**: Define a pipeline parameter called `further` with a type of `boolean` and a default value of `false`.
    
*   **Line 20**: Use the [`when` key](https://circleci.com/docs/reference/configuration-reference/#using-when-in-workflows) in the workflow to conditionally execute the workflow based on the value of the `further` parameter.
    

In the above scenario, the `module-workflow` will only execute if you specified `parameters: '{ "further": true }'` when invoking the `continuation/continue` command.

### Additional notes

You can pass several parameters when invoking the `continuation/continue` command. However, they need to be part of the same JSON object. For example:

```yaml
steps:
  - continuation/continue:
      parameters: '{ "further": true, "other_param": "a_string" }'
      configuration_path: ./config_continue.yml
```

Notice the absence of double-quotes around the boolean’s value.

The `parameters` parameter accepts either a JSON object or a path to a file containing a JSON object. Therefore, the following is also valid:

```yaml
steps:
  - run: echo '{ "further": true, "other_param": "a_string" }' > /home/circleci/parameters.json
  - continuation/continue:
      parameters: /home/circleci/parameters.json
      configuration_path: ./config_continue.yml
```

## Continue a pipeline with a dynamically generated configuration file

The following is a basic example using CircleCI’s dynamic configuration feature.

In this example, we assume that a `generate-config` script already exists. The script outputs a new configuration YAML based on some type of work it performs. For example, inspecting `git` history or pipeline values that get passed to it, or anything else you might do from inside a [Job](https://circleci.com/docs/reference/configuration-reference/#jobs).

```yaml
version: 2.1

# define this file as the setup phase of your dynamic configuration
setup: true

# invoke the continuation orb to make the continuation/continue command available
orbs:
  continuation: circleci/continuation@1

jobs:
  setup:
    executor: continuation/default
    steps:
      - checkout # checkout code
      - run: # run command to run script to generate YAML config
          name: Generate config
          command: |
            ./generate-config > generated_config.yml
      - continuation/continue:
          configuration_path: generated_config.yml # use newly generated config to continue the pipeline

workflows:
  my-setup-workflow:
    jobs:
      - setup
```

*   **Line 4**: Add the line `setup: true` to the top-level of our config, to designate it for use of CircleCI’s dynamic configuration feature.
    
*   **Line 8**: Invoke the `continuation` orb so we can use it.
    
*   **Lines 11-20**: Define a job called `setup` that uses the default [`executor`](https://circleci.com/docs/guides/execution-managed/executor-intro/) provided by the `continuation` orb. This job:
    
    *   Calls the [`checkout`](https://circleci.com/docs/reference/configuration-reference/#checkout) step to checkout code from the configured repository.
        
    *   Calls the [`run`](https://circleci.com/docs/reference/configuration-reference/#run) step to execute the existing `generate-config` script, so we can pass its output to the `continue` job of the `continuation` orb.
        
    *   Continues running the pipeline based on what configuration is provided to the required `configuration_path`.
        
    
*   **Line 25**: We call the `setup` job defined above as a part of our `workflow`.
    

Only one workflow that includes a continuation is allowed per pipeline. To adhere to this you can either only configure a single continuation workflow, or you can use [Conditional Logic](https://circleci.com/docs/reference/configuration-reference/#using-when-in-workflows) to ensure only one will run in a pipeline. This setup-workflow has access to a one-time-use token to create more workflows. The setup process does not cascade. Subsequent workflows in the pipeline cannot launch their own continuations.

For a more in-depth explanation of what the `continuation` orb does, review the orb’s source code in the [CircleCI developer hub](https://circleci.com/developer/orbs/orb/circleci/continuation?version=0.1.2).

## Execute specific `workflows` or `steps` based on which files are modified

Your project may benefit from conditionally running configuration based upon changes made to a specific set of files. Dynamically deciding the work to do in a pipeline based on the location of changes is beneficial when your code or microservices are stored in a monorepo. Without this ability, using _static_ configuration, each time a change is made to any file, all jobs and workflows would run even if they are unrelated to the actual change.

Use the [path filtering orb](https://circleci.com/developer/orbs/orb/circleci/path-filtering) to help simplify the process of using dynamic configuration based on the paths to modified files.

Consider a monorepo structure, as follows:

```shell
.
├── .circleci
│   ├── config.yml
│   └── continue_config.yml
├── service1
│   ├── Service1.java
├── service2
│   ├── Service2.java
├── tests
│   ├── IntegrationTests.java
```

An example implementation of CircleCI’s dynamic configuration for this structure is provided in the following `config.yml` and `continue_config.yml`.

### Setup configuration: config.yml

The `config.yml` file defines the initial setup phase.

In this example, the path filtering orb maps file paths with pipeline parameter values. If a file change matches a path regex, the corresponding parameter is set. Pipeline parameters are passed to the continuation configuration. These parameters determine which jobs run.

The path filtering orb uses the [continuation orb](https://circleci.com/developer/orbs/orb/circleci/continuation) under the hood to continue the pipeline.

The configuration used to continue the pipeline is described in the next section.

```yaml
version: 2.1

# define this file as the setup phase of your dynamic configuration
setup: true

# use the path-filtering orb to continue a pipeline based on
# the path of an updated set of files
orbs:
  path-filtering: circleci/path-filtering@1

workflows:
  always-run:
    jobs:
      # the path-filtering/filter job determines which pipeline
      # parameters to update.
      - path-filtering/filter:
          name: check-updated-files
          # 3-column, whitespace-delimited mapping. One mapping per
          # line:
          # <regex path-to-test> <parameter-to-set> <value-of-pipeline-parameter>
          mapping: |
            service1/.* run-build-service-1-job true
            service2/.* run-build-service-2-job true
          base-revision: main
          # this is the path of the configuration we should trigger once
          # path filtering and pipeline parameter value updates are
          # complete.
          config-path: .circleci/continue_config.yml # this is the default so not actually required but left in to illustrate options
```

### Continuation configuration: `continue_config.yml`

In this example, `continue_config.yml` is the _continuation configuration_. This means it runs once the initial `config.yml` finishes executing the `path-filtering/filter` job. The continuation configuration takes the updated pipeline parameter values, which are modified based on the paths to any changes in a commit. It uses them to conditionally run workflows using the `when` key. For more information on using `when` in workflows, see the [Configuration Reference](https://circleci.com/docs/reference/configuration-reference/#using-when-in-workflows).

```yaml
version: 2.1

orbs:
  maven: circleci/maven@1.2.0

# the default pipeline parameters, which will be updated according to
# the results of the path-filtering orb
parameters:
  run-build-service-1-job:
    type: boolean
    default: false
  run-build-service-2-job:
    type: boolean
    default: false

# here we specify our workflows, most of which are conditionally
# executed based upon pipeline parameter values. Each workflow calls a
# specific job. In this example all jobs are preconfigured in the Maven orb
workflows:
  # when pipeline parameter run-build-service-1-job is true, the
  # build-service-1 job is triggered.
  service-1:
    when: << pipeline.parameters.run-build-service-1-job >>
    jobs:
      - maven/test:
          name: build-service-1
          command: 'install -DskipTests'
          app_src_directory: 'service1'
  # when pipeline parameter run-build-service-2-job is true, the
  # build-service-2 job is triggered.
  service-2:
    when: << pipeline.parameters.run-build-service-2-job >>
    jobs:
      - maven/test:
          name: build-service-2
          command: 'install -DskipTests'
          app_src_directory: 'service2'
  # when pipeline parameter, run-build-service-1-job OR
  # run-build-service-2-job is true, run-integration-tests job is
  # triggered. see:
  # https://circleci.com/docs/configuration-reference/#logic-statements
  # for more information.
  run-integration-tests:
    when:
      or: [<< pipeline.parameters.run-build-service-1-job >>, << pipeline.parameters.run-build-service-2-job >>]
    jobs:
      - maven/test:
          name: run-integration-tests
          command: '-X verify'
          app_src_directory: 'tests'
```

*   **Line 4**: Invoke the Maven orb so we can use its preconfigured jobs.
    
*   **Lines 8-14**: Define our two boolean pipeline parameters, the same parameters we have defined in the setup phase: `run-build-service-1-job` and `run-build-service-2-job`.
    
*   Define three separate workflows to be conditionally executed based on the pipeline parameter values:
    
    *   **Lines 22-28**: The `service-1` workflow triggers the `maven/test` job on the `service-1` directory, when the pipeline parameter value mapped to run-build-service-1-job is set to `true`. This will only happen if a change was made in the `service-1` directory in the commit, as determined based on the path filtering in the setup phase (`config.yml`).
        
    *   **Lines 31-37**: The `service-2` workflow triggers the `maven/test` job on the `service-2` directory, when the pipeline parameter value mapped to run-build-service-2-job is set to `true`. This will only happen if a change was made in the `service-2` directory in the commit, as determined based on the path filtering in the setup phase (`config.yml`).
        
    *   **Lines 43-50**: The `run-integration-tests` workflow will run if the `run-build-service-1-job` or `run-build-service-2-job` pipeline parameters have been updated to `true` based on the results of the path filtering. This runs the `maven/test` job on the `tests` directory to run integration tests against the built services.
        
    

## Generate a configuration file based on modified files

This project is available on [GitHub](https://github.com/CircleCI-Public/dynamic-configuration-examples/tree/generate-config-file-main) and you can see it building on [CircleCI](https://app.circleci.com/pipelines/github/CircleCI-Public/dynamic-configuration-examples?branch=generate-config-file-main).

For this example, consider a project that includes:

*   Separate directories for code (`src/`) and docs (`docs/`).
    
*   A setup configuration, `config.yml`.
    
*   Separate configuration files for building the code and the docs, `code-config.yml` and `docs-config.yml`.
    
*   A `shared-config.yml` file that defines shared jobs to be used when building the code and the docs.
    
*   A `no-updates.yml` config file to be used in the event that a pipeline is triggered with no changes.
    

Each configuration file is explained in the following sections.

```shell
.
├── .circleci
│   ├── code-config.yml
│   ├── config.yml
│   ├── docs-config.yml
│   ├── no-updates.yml
│   └── shared-config.yml
├── README.md
├── docs
│   └── my-docs.txt
└── src
    └── my-code.txt
```

### Setup configuration

In this example, the setup configuration includes a single job referenced from the [path filtering orb](https://circleci.com/developer/orbs/orb/circleci/path-filtering#jobs-filter). This job maps pipeline parameter values and configuration files with paths to specific locations in the repository.

Under the hood the following steps are taken when the pipeline is triggered:

*   A script runs to check for modified files in a commit against a base branch (in this example, the default, `generate-config-file-main`).
    
*   A continuation configuration is generated using the relevant config files from the project, and the pipeline parameter values are set.
    
*   The pipeline is continued using the continuation configuration.
    

```yaml
version: 2.1

# define this file as the setup phase of your dynamic configuration
setup: true

# invoke the path-filtering orb to make the filter job available.
orbs:
  path-filtering: circleci/path-filtering@1.0.0

workflows:
  setup-workflow:
    jobs:
      - path-filtering/filter:
          base-revision: generate-config-file-main
          config-path: .circleci/no-updates.yml
          mapping: | # The mapping will be used to generate the dynamic configuration for all conditions that match.
            .* always-continue true .circleci/shared-config.yml
            src/.* build-code true .circleci/code-config.yml
            docs/.* build-docs true .circleci/docs-config.yml
```

### Shared configuration

In the event of changes to _any_ file in the repository (`.*`) the `shared-config.yml` configuration is included in the continuation configuration. The only time `shared-config.yml` will not be used is on a commit that contains no changes.

`shared-config.yml` is designed to be used either on its own or along with other partial configurations. You can include anything that _always_ runs in the shared configuration. `code-config.yml` or `docs-config.yml` include workflows that orchestrate the shared jobs defined in `shared-config.yml` and they can be combined together to create the required pipeline for a set of changes.

```yaml
version: 2.1

# define the parameters from the setup config.
parameters:
  always-continue:
    type: boolean
    default: false
  build-code:
    type: boolean
    default: false
  build-docs:
    type: boolean
    default: false

# define the shared jobs that will be available for all continued workflows.
jobs:
  lint:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Running linting"

  test:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Running tests"

  any-change:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "This is a shared job that will reun for any change in the project."

workflows:
  run-on-any-change:
    jobs:
      - any-change
```

### Directory-specific configuration

The config files for building the separate directories, `src/` and `/docs`, contain build jobs for the content and workflows to orchestrate the build and shared jobs described above. The `lint` job is used for both, and the `test` job is only used when the code is built, not the docs.

code-config.yml

```yaml
version: 2.1

jobs:
  build-code:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Building code"

workflows:
  code-workflow:
    jobs:
      - lint # use the shared lint job.
      - test # use the shared test job.
      - build-code
```

docs-config.yml

```yaml
version: 2.1

jobs:
  build-docs:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Building docs"

workflows:
  docs-workflow:
    jobs:
      - lint # use the shared lint job.
      - build-docs
```

### Configuration for no change

We have used the path filtering orb to map configuration files with file paths. This tells us which configuration will be used when a change is made in a specific location. If a pipeline is triggered with no changes in any of our defined paths, CircleCI needs to know what to do next.

One way to handle this scenario is to provide an alternative configuration using the `config-path` parameter (see line 27 [here](#setup-config-1)). `config-path` is ignored if a mapping is in place, but will be used if no mapping matches the path to modified files. In this example, we use a `no-updates.yml` configuration file. Another option would be to configure a step using the `finish` command from the [continuation orb](https://circleci.com/developer/orbs/orb/circleci/continuation#commands-finish).

```yaml
version: 2.1

# define the parameters from the setup config.
parameters:
  always-continue:
    type: boolean
    default: false
  build-code:
    type: boolean
    default: false
  build-docs:
    type: boolean
    default: false

jobs:
  no-updates:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "No updates have been made"

workflows:
  no-update-workflow:
    jobs:
      - no-updates
```

## Pack, generate, and validate a configuration file for pipeline continuation

This project is available on [GitHub](https://github.com/CircleCI-Public/dynamic-configuration-examples/tree/pack-validate-continue-main) and you can see it building on [CircleCI](https://app.circleci.com/pipelines/github/CircleCI-Public/dynamic-configuration-examples?branch=pack-validate-continue-main).

For this example, consider a project that includes:

*   Separate directories for code (`src/`) and docs (`docs/`).
    
*   A setup configuration, `config.yml`.
    
*   Separate configuration files for building the code and the docs, `code-config.yml` and `docs-config.yml`.
    
*   A `shared/` configuration directory containing our shared jobs in separate YAML files. This is used to generate `shared-config.yml` using the [CircleCI CLI Command](https://cli.circleci.com/reference/#circleci-config-pack-path) `circleci config pack`.
    
*   A `no-updates.yml` config file to be used in the event that there are no changes.
    

```shell
.
├── .circleci
│   ├── code-config.yml
│   ├── config.yml
│   ├── docs-config.yml
│   ├── no-updates.yml
│   ├── shared
│   │   └── jobs
│   │       ├── any-change.yml
│   │       ├── lint.yml
│   │       └── test.yml
│   │   └── workflows
│   │       ├── run-on-any-change.yml
|   |       └── @shared.yml
├── README.md
├── docs
│   └── my-docs.txt
└── src
    └── my-code.txt
```

`@shared.yml` exists to provide the required `version` key for the config in the event that a pipeline is triggered on a change outside the `src/` or `docs/` directories.

### Setup configuration

The setup configuration has a single job, `setup`, which has the following steps:

*   Checkout code
    
*   Install the CircleCI CLI.
    
*   Generate a shared configuration file.
    
*   Map file paths with pipeline parameter values and configuration files, using the path filtering orb.
    
*   Generate a configuration file to fit the changes included in the commit that triggered the pipeline.
    
*   Validate the configuration file using the CLI.
    
*   Continue the pipeline with the new configuration file using the continuation orb.
    

```yaml
version: 2.1

# define this file as the setup phase of your dynamic configuration
setup: true

# define the parameters that will be used to generate the dynamic configuration.
parameters:
  always-continue:
    type: boolean
    default: false
  build-code:
    type: boolean
    default: false
  build-docs:
    type: boolean
    default: false

# invoke the orbs to filter, pack and continue configs.
orbs:
  path-filtering: circleci/path-filtering@1.0.0
  circleci-cli: circleci/circleci-cli@0.1.9
  continuation: circleci/continuation@1.0.0

jobs:
  setup:
    executor: path-filtering/default
    steps:
      - checkout

      # Install the CircleCI CLI
      - circleci-cli/install

      # Generate the shared configuration from a directory with the pack command.
      - run:
          name: Generate shared configuration
          command: circleci config pack .circleci/shared >> .circleci/shared-config.yml

      # The mapping will be used to generate the dynamic configuration for all conditions that match.
      - path-filtering/set-parameters:
          base-revision: pack-validate-continue-main
          config-path: .circleci/no-updates.yml
          mapping: |
            .* always-continue true .circleci/shared-config.yml
            src/.* build-code true .circleci/code-config.yml
            docs/.* build-docs true .circleci/docs-config.yml

      # Generate the dynamic configuration based on the parameters set in the previous step.
      - path-filtering/generate-config

      # Optionally validate the generated configuration.
      - run:
          name: Validate config
          command: circleci config validate /tmp/generated-config.yml

      # Continue the pipeline with the generated configuration.
      - continuation/continue:
          configuration_path: /tmp/generated-config.yml
          parameters: /tmp/pipeline-parameters.json

workflows:
  setup-workflow:
    jobs:
      - setup
```

### Shared configuration

In this example, shared configuration elements are stored in individual YAML files using a directory structure compatible with the `circleci config pack` command.

Jobs are stored in a `jobs` folder, workflows stored in a `workflows` folder, and so on. These files can be used in the setup stage of our dynamic configuration to generate a shared configuration by "packing" the relevant components together.

When packing a config using `circleci config pack`, the component names are not included in the configuration files, they are taken from the file names.

#### `shared/workflows/run-on-any-change.yml`

This workflow runs the job `any-change` on all pipelines triggered by a change in the repository, even if that change is outside of the `/src` or `/docs` directories.

```yaml
jobs:
  - any-change
```

shared/jobs/any-change.yml

```yaml
docker:
  - image: cimg/base:stable
steps:
  - run: echo "This is a shared job that will run for any change in the project."
```

shared/jobs/lint.yml

```yaml
docker:
  - image: cimg/base:stable
steps:
  - run: echo "Running linting"
```

shared/jobs/test.yml

```yaml
docker:
  - image: cimg/base:stable
steps:
  - run: echo "Running tests"
```

### Directory-specific configuration

The config files for building the separate directories, `src/` and `/docs`, contain build jobs for the content and workflows to orchestrate the build and shared jobs described above. The `lint` job is used for both, and the `test` job is only used when the code is built, not the docs.

code-config.yml

```yaml
version: 2.1

jobs:
  build-code:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Building code"

workflows:
  code-workflow:
    jobs:
      - lint # use the shared lint job.
      - test # use the shared test job.
      - build-code
```

docs-config.yml

```yaml
version: 2.1

jobs:
  build-docs:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "Building docs"

workflows:
  docs-workflow:
    jobs:
      - lint # use the shared lint job.
      - build-docs
```

### Configuration for no change

We have used the path filtering orb to map configuration files with file paths. This tells us which configuration will be used when a change is made in a specific location. If a pipeline is triggered with no changes in any of our defined paths, CircleCI needs to know what to do next.

One way to handle this scenario is to provide an alternative configuration using the `config-path` parameter (see line 27 [here](#setup-config-1)). `config-path` is ignored if a mapping is in place, but will be used if no mapping matches the path to modified files. In this example, we use a `no-updates.yml` configuration file.

```yaml
version: 2.1

# define the parameters from the setup config.
parameters:
  always-continue:
    type: boolean
    default: false
  build-code:
    type: boolean
    default: false
  build-docs:
    type: boolean
    default: false

jobs:
  no-updates:
    docker:
      - image: cimg/base:stable
    steps:
      - run: echo "No updates have been made"

workflows:
  no-update-workflow:
    jobs:
      - no-updates
```

Another option would be to configure a step using the `finish` command from the [continuation orb](https://circleci.com/developer/orbs/orb/circleci/continuation#commands-finish).