What is YAML?
YAML (pronounced "yam-ul") is a human-readable data serialization language. It is used primarily for configuration files in DevOps, CI/CD pipelines, and application settings. YAML originally stood for “Yet Another Markup Language”, but this later evolved into "YAML Ain't Markup Language" to emphasize the focus on structuring data, not documents. If you've ever worked with Docker, Kubernetes, or CI/CD tools like Bitrise, you've likely encountered YAML files before (.yml or .yaml extensions).
YAML is designed to be easily readable for both humans and computers, making it an excellent option for configuration files and exchanging data across various programming languages. YAML uses indentation and newlines, which makes them cleaner and easier to read, especially if you spend a lot of time interacting with configuration files. We use YAML to define CI/CD configurations on Bitrise.
How to write YAML
YAML uses indentation and key-value pairs to arrange data, making it a readable and intuitive format for serialization. It handles a range of data types, such as scalars (strings, numbers, booleans), lists (or arrays), dictionaries (or maps), and can represent much more complex nested structures as well.
Below is an overview of YAML’s structure and the ways different kinds of data are expressed in a YAML document. From simple key-value pairs to multi-layered data, YAML’s clear, hierarchical layout keeps information understandable and easy to work with.
Example YAML
Here's an example of someone's Bitrise mobile CI/CD pipeline in YAML, showcasing the different data structures.
format_version: 11
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
app:
envs:
- BITRISE_PROJECT_PATH: MyApp.xcworkspace
- BITRISE_SCHEME: &scheme MyApp
description: >
This app workflow handles cloning, dependency installation,
testing, and archiving for iOS release builds.
workflows:
primary:
steps:
- activate-ssh-key: {}
- git-clone: {}
- cache-pull: {}
- cocoapods-install: {}
- script:
inputs:
- content: |
#!/bin/bash
# Run linting before the build kicks off
echo "Running pre-build checks"
bundle exec fastlane lint
- xcode-test:
inputs:
- scheme: *scheme
- xcode-archive:
inputs:
- scheme: *scheme
- deploy-to-bitrise-io: {}
The basic structure of a YAML file is a map or a dictionary, which are both terms for an object that maps a collection of key-value pairs. We’ll use the term “dictionary” throughout this guide.
Below, we breakdown all the constituent parts of the YAML file and show you where to find each example.
Key-value pairs example
Every file written in YAML is made up of a set of key-value pairs. Each pair is written in the same structure key: value, where whitespace after the colon is required. The example above is packed full of key-value pairs, but to highlight a couple:
format_version: 11
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.gitScalars example
In YAML, various scalar types are used to represent values. Scalars are simple yet indivisible values such as strings, numbers, booleans, or null. Scalars can be written without special syntax. For example, format_version and BITRISE_SCHEME in the example represent scalar values - a number and a string, respectively.
format_version: 11 # number
BITRISE_SCHEME: MyApp # string
is_always_run: false # booleanLists example
Lists (or arrays) are defined by hyphens ("-"). Each item in the list is indented with a hyphen and a space before the item. Lists can contain as many items as needed.
steps:
- activate-ssh-key: {}
- git-clone: {}
- cache-pull: {}
- cocoapods-install: {}
Dictionaries example
Dictionaries are collections of key-value pairs into clear hierarchical structures with nesting. These pairs (sometimes referred to as “children”) are written on new lines under the key to which they belong (the “parent”). For example, workflows: is the parent of primary:, which is itself the parent of steps:
workflows:
primary:
steps:
- xcode-test:
inputs:
- scheme: *scheme
- xcode-archive:
inputs:
- scheme: *scheme
Multi-line strings example
When you need to write a multi-line string as a value, you've got two options:
The pipe (|) — literal style
Use this when formatting matters. It keeps your line breaks and indentation exactly as you wrote them. Perfect for code snippets, documentation, or anywhere whitespace carries meaning.
- content: |
#!/bin/bash
# Run linting before the build kicks off
echo "Running pre-build checks"
bundle exec fastlane lint
The angle bracket (>) — folded style
This one treats line breaks as spaces (except when you add a blank line for a paragraph break). Good for long-form text that you want to wrap naturally without manual formatting.
description: >
This app workflow handles cloning, dependency installation,
testing, and archiving for iOS release builds.
Most of the time, the literal style with | is your best bet as it's predictable and does what you expect.
Note: The folded style (>) converts single newlines between same-indented lines to spaces. However, blank lines are preserved as newlines, and more-indented lines are kept literal. This makes it useful for long descriptions or option strings that should be read as a single paragraph in the output, while still being legible in the source file.
Both styles support a chomping indicator that controls trailing newlines:
- | / > — default ("clip"): keeps exactly one trailing newline
- |- / >- — "strip": removes all trailing newlines
- |+ / >+ — "keep": preserves all trailing newlines as-is
In CI/CD configs, |- is the most common choice for script blocks and condition expressions, where a trailing newline would break evaluation.
Comments example
Comments in YAML start with the “#” symbol. They allow you to add notes or explanations without affecting functionality. In the example, comments are used to describe the sections of the YAML file.
- content: |
#!/bin/bash
# Run linting before the build kicks off
echo "Running pre-build checks"
Anchors (aliases) example
Anchors reduce repetition. &scheme attaches an anchor to the value MyApp, and *scheme references it wherever the scheme name is needed, so you only ever update it in one place.
So, anchors reduce effort and avoid you repeating yourself over and over and over again. (See what we did there?)
- BITRISE_SCHEME: &scheme MyApp
- xcode-test:
inputs:
- scheme: *scheme
- xcode-archive:
inputs:
- scheme: *scheme
Indentation and formatting in YAML
One of the reasons YAML has a reputation for being a bit fiddly is that you must use spaces for indentation; tab characters are not allowed. Incorrect formatting, such as using tabs or incorrect spacing, can result in syntax errors, which may cause build processes to stall or hang. At Bitrise, we always recommend that you validate your bitrise.yml file using an online YAML validator or the Bitrise Command Line Interface (CLI).
What is YAML used for?
We’ve covered what YAML is and how to write it. But what is it used for? Here’s a summary on its most common use cases including data serialization, configuration files, APIs, and managing metadata.
What are some YAML best practices?
When working with YAML, following best practices is a smart way to ensure your configurations are error-free, readable, and compatible across platforms. Here are some best practices to follow and common mistakes to avoid.
YAML best practices
- Use spaces (not tabs) for indentation. Be consistent about how many (commonly 2 or 4). This avoids syntax errors and cross‑platform issues.
- Follow proper syntax. Put a space after colons (:) and dashes (-) and keep structure predictable.
- Be consistent with style. Use a single indentation size throughout, stick to one naming convention, and choose either single or double quotes for strings, use quotes when strings contain special characters or reserved words.
- Quote strings. Use quotation marks for strings that could be misinterpreted, such as those containing special characters, leading zeros, or values that look like booleans or numbers.
- Add comments with #. Use comments to explain non‑obvious configuration choices so the file’s intent is clear to others (and to future you).
- Validate your YAML. Use a linter or validator to catch syntax and structural errors before using the file.
- Break large files into smaller, modular pieces. This improves reusability and maintainability.
- Treat sensitive data carefully. Don’t store passwords or secrets in plain text; use encryption, secret management, or other appropriate protections and validate any user input to avoid injection issues.
Common YAML mistakes to avoid
- Inconsistent indentation. oOnly use spaces and never tabs to create indentations. Use the same amount of spaces throughout (commonly 2 or 4). Not being consistent could cause parsers to fail or interpret nesting incorrectly, causing errors or misconfigured data at runtime.
- Missing colons after keys. Every key must be followed by : otherwise keys or values may be misread causing syntax errors and breaking configuration.
- Not quoting special characters. While YAML doesn’t require quoting of most strings, you’ll want to quote special characters or risk values being misinterpreted.
- Mixing tabs and spaces. Always stick to spaces. Similar to the issues that arise with inconsistent indentation, some parsers process indentation differently, producing parse failures or incorrect structure.
- Duplicate keys. Ensure keys are unique within the same dictionary. Duplicating a value later typically overwrites the earlier ones which causes unexpected configuration and subtle bugs.
- Watch out for booleans. Depending on whether you’re using YAML 1.1 or YAML 1.2, many short words (e.g. No, ON, yes) can be parsed as true/false. Quote them when they are intended as strings or risk causing logic errors or invalid data.
- In YAML 1.1 (which many parsers, including some CI/CD toolchains, still implement) short words like yes, no, on, and off are parsed as booleans.
- YAML 1.2 restricts this to true and false only. Since parser versions vary by tool, quote these values whenever you mean them as strings.
By avoiding these common mistakes and following the best practices from earlier, your YAML will be easier to read, safer to use, and more reliable across tools and platforms.
What’s the difference between YAML and JSON?
YAML and JSON do the same job: they store structured data. But they look and feel different for a key reason.
YAML (.yaml or .yml) is built for people: it’s readable, uses indentation, and is more forgiving. It’s also a superset of JSON, so any valid JSON is also valid YAML. JSON is more explicit: braces, brackets and quotes make structure obvious for machines and libraries. That’s why JSON is the go-to for APIs and data exchange.
Below is a summary of the main differences:
Why YAML matters for CI/CD
CI systems use YAML to declare what to run, when, and how. On Bitrise, your bitrise.yml defines build steps, inputs, and environment variables. Because YAML is human-friendly, teams can review and tweak pipelines in pull requests instead of wrestling with GUIs.
The content in this guide should be all you need to get started, or at least get comfortable with writing in YAML. If you’re looking to write a config file for your Bitrise CI/CD pipeline, do check out our documentation pages for Bitrise-specific YAML examples.
See what Bitrise can do for you
Confidently build, test, and ship high-quality mobile apps with Bitrise.
Frequently Asked Questions
What does YAML stand for?
YAML originally stood for "Yet Another Markup Language." It was later redefined as "YAML Ain't Markup Language", a recursive acronym that highlights an important distinction: YAML is a data serialization language, not a markup language. It structures data rather than formatting documents.
What is the difference between YAML and JSON?
Both YAML and JSON store structured data, but they're designed for different things. YAML is built for readability and uses indentation instead of brackets, supports comments, and is the go-to for configuration files in tools like Kubernetes, Docker, and CI/CD platforms. JSON is stricter and more explicit, which makes it better suited for APIs and data exchange between systems.
What is the difference between .yml and .yaml?
There's no functional difference, .yml and .yaml are both valid file extensions for YAML files and are treated identically by parsers. The .yaml extension is the officially recommended one by the YAML specification, but .yml became widely used because older Windows systems had a three-character extension limit. You'll see both in the wild; pick one and stay consistent across your project.
Is YAML a programming language?
No. YAML is a data serialization language, not a programming language. It can't execute logic, define functions, or run loops. It's used purely to represent and structure data, so you'll most commonly encounter YAML in configuration files for tools like Docker, Kubernetes, Ansible, and CI/CD platforms, where it defines what should happen rather than how to do it.
How do I convert JSON to YAML?
Since YAML is a superset of JSON, conversion is straightforward. Most programming languages have libraries that handle it, for example, Python's PyYAML and json modules, or JavaScript's js-yaml package. There are also free browser-based converters if you need a quick one-off conversion. Keep in mind that YAML features like comments and anchors have no JSON equivalent, so converting from YAML to JSON may lose some information.
