---
url: /zh/build/simplify-configuration.md
---
## YAML 高级语法

由于`.cnb.yml`配置文件是 `YAML` 格式，所以可以利用更多 `YAML` 特性（如锚点 `&` 、别名 `*` 和对象合并 `<<` 符号）来简化配置文件。

一个简单的运用锚点和别名简化的例子如下：

```yaml title=".cnb.yml"
# pull_request 和 push 事件的流水线完全一致，这种方式可以减少重复
.pipeline: &pipeline
  docker:
    image: node:22
  stages:
    - name: install
      script: npm install
    - name: test
      script: npm test

main:
  pull_request:
    - <<: *pipeline
  push:
    - <<: *pipeline
```

支持多级嵌套：

```yaml title=".cnb.yml"
.jobs: &jobs
  - name: install
    script: npm install
  - name: test
    script: npm test

.pipeline: &pipeline
  docker:
    image: node:22
  stages: *jobs

main:
  pull_request:
    - <<: *pipeline
  push:
    - <<: *pipeline
```

:::tip

以上是 `YAML` 自带特性，仅在解析单个YAML文件时有效，不能跨文件使用。

:::

## 文件引用

为了方便复用流水线配置，`云原生构建` 实现了以下特性：

* [include](./grammar.md#include)：可以跨文件引用流水线模板。
* [imports](./grammar.md#pipeline-imports)：可以跨文件引用变量。
* [optionsFrom](./grammar.md#job-optionsfrom)：可以跨文件引用内置任务参数。
* [settingsFrom](./grammar.md#job-settingsfrom)：可以跨文件引用插件任务参数。

详细文件引用说明见 [文件引用](./file-reference.md)

## 变量引用

为了解决YAML锚点和别名不能跨文件使用的问题。`云原生构建` 实现了以下特性：

### reference (扩展标签)

YAML 标准不支持跨文件引用。`云原生构建` 通过扩展的 `!reference` 自定义标签实现了按属性路径引用值的功能，可与 [`include`](#include) 结合实现跨文件配置复用。

:::tip 注意事项

1. `!reference` 支持嵌套引用，最多 10 层。
2. 合并配置时，第一层的同名变量会被覆盖，不会合并。
3. 解析顺序：先加载并合并所有 `include` 的文件和主文件 `.cnb.yml`，**然后**再解析 `!reference` 标签。合并过程基于原始文本，不感知引用解析后的值。
   :::

#### 示例 {#reference-example}

```yaml title="a.yml"
.val1:
  echo1: echo hello
.val2:
  friends:
    - one:
        name: tom
        say: !reference [.val1, echo1] # 引用本文件内的值
```

```yaml title=".cnb.yml"
include:
  - ./a.yml # 引入 a.yml

.val3:
  size: 100

main:
  push:
    - stages:
        - name: echo hello
          # 跨文件引用 a.yml 中的值
          script: !reference [.val2, friends, "0", say]
        - name: echo size
          env:
            # 引用本文件 .cnb.yml 中的值
            SIZE: !reference [".val3", "size"]
          script: echo my size ${SIZE}
```

**解析后的等效配置:**

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: echo hello
          script: echo hello # 解析后的值
        - name: echo size
          env:
            SIZE: 100 # 解析后的值
          script: echo my size ${SIZE}
```

#### 进阶示例：复用整条流水线

```yaml title=".cnb.yml"
.common-pipeline:
  - stages:
      - name: echo
        script: echo hello

main:
  push: !reference [.common-pipeline] # 引用整条流水线
test:
  push: !reference [.common-pipeline] # 引用整条流水线
```

**解析后的等效配置:**

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: echo
          script: echo hello
test:
  push:
    - stages:
        - name: echo
          script: echo hello
```

#### VSCode 配置

为了在 VSCode 中编写带 `!reference` 标签的 YAML 文件时避免语法报错，需要进行如下配置：

在 `settings.json` 中添加：

```json
{
  "yaml.customTags": ["!reference sequence"]
}
```

:::tip
为避免系统解析时根据 schema 将顶层的变量名误认为分支名而产生错误提示，建议使用点号 (`.`) 开头命名用于 `reference` 的顶层变量（例如 `.var`）。
:::
