Modular YAML configuration
Modular YAML Configuration enables you to break down large, complex YAML files into smaller, modular components. It allows easier reuse across multiple repositories.
Enterprise only
Modular YAML configuration is only available for Workspaces with Enterprise plans. You also need to store your configuration files in your own repository, not on bitrise.io.
If you are not on an Enterprise plan but interested in modular YAML, contact us!
Modular YAML configuration enables you to break down large, complex YAML files into smaller, modular components. It allows easier reuse across multiple repositories. By modularizing YAML files, you can quickly locate and update configurations, reducing the risk of errors and merge conflicts.
A modular YAML configuration includes:
-
A
bitrise.ymlfile in the root of your repository. -
Other YAML files in the same or a different repository. To include a file from a different repository, the repository must belong to the same Git account or organization as the primary repository.
-
One or more
includekeywords in thebitrise.ymlfile. These point to other YAML files and bring their configuration into the main project configuration.
After an additional YAML file has been included in the bitrise.yml file, you can refer to any of its Workflows or Pipelines as to any other Workflow or Pipeline in your configuration.
Including configuration from multiple YAML files
To create a modular configuration, you need to:
-
Store your
bitrise.ymlfile in your repository. -
Create more YAML files in addition to
bitrise.ymland commit them to your repository. We refer to these files as configuration modules.
File limit
You can have a total of 35 configuration files, including the root level bitries.yml file.
In bitrise.yml, you can include the YAML configuration modules with the include keyword. If the module is in the same repository as the bitrise.yml file, the include keyword requires one parameter: path which points to the location of the module.
The provided path must be relative to the repository's root:
include: - path: file/path/common.yml
You can include a YAML configuration module from a different repository by specifying the repository that contains the file. In addition to the repository property, you need to also set at least one of the following:
-
branch: The branch containing the YAML configuration module. -
commit: The specific commit hash from which to include the YAML configuration module. -
tag: The Git tag that points to the YAML configuration module.
The repository must belong to the same Git account or organization that your project's primary repository belongs to. You can check your Bitrise project's repository URL on bitrise.io. For example, if your repository URL is [email protected]:MyOrg/main_repo.git, you can only refer to repositories belonging to MyOrg on GitHub.
You only need to refer to the repository's name. For example, you can refer to [email protected]:MyOrg/another_repo.git with the value another_repo.
include:
- path: shared/common.yml
branch: test_branch
repository: another_repo
Accessing other repositories
Bitrise needs read access to all repositories where configuration YAML files are hosted. There are two ways to make sure Bitrise can access your repo:
-
If you use the GitHub App integration, you can link additional repositories to your project.
-
For other authentication methods, check out this guide: Projects with submodules or private repo dependencies
The include format
|
Parameter |
Required? |
Description |
|---|---|---|
|
|
Required |
The location of the YAML file you want to include. The path is relative to either:
|
|
|
Optional |
The branch from which to include the YAML file. |
|
|
Optional |
The tag from which to include the YAML file. If |
|
|
Optional |
The specific commit hash from which to include the YAML file. If |
|
|
Optional |
The repository from which to pull the YAML file. You just need to set the name of the repository, not the URL. |
Defining configuration modules
A configuration module is a full YAML configuration file. That means that all configuration elements of a valid bitrise.yml file are available: you can define the format_version, app level Environment Variables, default stacks and machine types, and of course Pipelines,
Stages, and Workflows in a configuration module.
For example, you can create a bare minimum bitrise.yml file that simply points to another module:
include: - path: path/to/config_module.yml
And in this case, config_module.yml contains the entire configuration for the build:
format_version: 13
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: android
app:
envs:
- MY_NAME: My Name
workflows:
test:
steps:
- script:
inputs:
- content: echo "Hello ${MY_NAME}!"
A configuration module can contain any configuration entity defined on the root level. For example, a configuration module defining only a single Workflow or just app-level Environment Variables is perfectly valid.
The bitrise.yml file:
format_version: 13 default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git include: - path: path/to/config_module.yml
The config_module.yml file:
app:
envs:
- USER_NAME: UserName
workflows:
test:
steps:
- script:
inputs:
- content: echo "Hello ${USERNAME}!"
However, non-root level entities cannot stand alone in a separate module file either: you can't, for example, include Step inputs like this.
Nesting included modules
You can use the include property in included configuration files:
Root level bitrise.yml file:
format_version: 13 default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git include: - path: path/to/config_module.yml
The config_module.yml file:
include: - path: path/to/another_module.yml
The another_module.yml file:
workflows:
ui_test:
steps:
- pull-intermediate-files@1:
inputs:
- artifact_sources: build_tests.build_for_ui_testing
With this configuration, you'll be able to run the ui_test Workflow.
Nesting has the following limitations:
-
A depth of 5, including the root level file.
-
Maximum 35 configuration files in total, including the root level file.
Merge rules for included modules
When Bitrise runs a build, we merge your configuration modules into a single bitrise.yml file:
-
Included modules are read and merged into the configuration in the order defined in the root
bitrise.ymlfile. -
If an included module also uses include, the nested module is merged first recursively.
-
After all configuration files added with include are merged together, the resulting configuration is merged with the
bitrise.ymlfile on the root level. As such, you can override configuration values on the root level.
Switching back to bitrise.io
If you have a modular configuration with multiple YAML files and you switch back to storing your configuration on
bitrise.io, we use the same merge rules to merge all your files into a single bitrise.yml file.
When merging the configurations, it is possible to encounter overlaps and override included configuration values. When merging YAML modules, the most recently read file takes priority over the existing merged configuration. Here are the rules:
-
Items of simple types (such as integers and booleans): The value from the most recently read file is used.
-
Items of object type (for example, Pipelines, Stages, Workflows):
-
If a property is only present in the existing merged configuration, that value is retained.
-
If a property is present in both, and their values are hash maps, the values are merged.
-
In any other case, the value from the most recently read file is used.
-
-
Items of array type (for example, lists of Environment Variables or trigger map items): if the collection is present in both the most recently read file and the existing merged configuration, the merged value is an ordered array of values, with all values from the merged configuration followed by the values from the most recently read file.
You can see the merged configuration file in the Workflow Editor: select bitrise.yml from the left navigation menu to view it.
We have the root bitrise.yml file which includes a config_module.yml file.
The bitrise.yml:
format_version: 13 default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git project_type: android include: - path: path/to/config_module.yml app: envs: - USER_ID: UserId - PASSWORD: SecurePassphrase
The config_module.yml:
format_version: 10
app:
envs:
- USERNAME: UserName
workflows:
test:
steps:
- script:
inputs:
- content: echo "Hello ${USERNAME}!"
During the merge, the config_module.yml and is merged into the configuration. Then the root level bitrise.yml is read and then merged. The final configuration looks like this:
format_version: 13
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: android
app:
envs:
- USER_ID: UserId
- PASSWORD: SecurePassphrase
- USERNAME: UserName
workflows:
test:
steps:
- script:
inputs:
- content: echo "Hello ${USERNAME}!"
-
The root level
format_versionproperty is present in both files. The root levelbitrise.ymlfile is merged into the overall configuration last, therefore its value offormat_versionis used. -
The
appsproperty is present in both files so all key-value pairs are added to the overall configuration. -
The
testWorkflow is only present inconfig_module.ymlso it's added to the overall configuration andbitrise.ymldoes not override it.