---
url: /zh/build/internal-steps.md
---
在每一阶段（Stage）操作中，除了使用自定义任务，
CNB 还扩展了一些常用的内置任务，以供开发者使用。

## 总览

* docker:
  * [cache](#docker-cache): 构建 Docker 镜像缓存，加速依赖安装
* cnb:
  * [await-resolve](#cnb-await-resolve): 等待/通知机制，多流水线协作
  * [apply](#cnb-apply): 触发同仓库下的子流水线
  * [trigger](#cnb-trigger): 触发指定仓库下的子流水线
  * [read-file](#cnb-read-file): 导出文件内容为环境变量
  * [destroy-token](#cnb-destroy-token): 销毁流水线 [CNB\_TOKEN](../build-in-env.md#cnb_token)
* vscode:
  * [go](#vscode-go): 控制云原生开发环境可用时机
* git:
  * [reviewer](#git-reviewer): PR 自动添加评审人
  * [auto-merge](#git-auto-merge): PR 自动合并
  * [issue-update](#git-issue-update): 更新 Issue 状态
  * [release](#git-release): 仓库发布 Release
  * [pr-commit-message-preset](#git-pr-commit-message-preset): 预先设置 PR 的 提交信息
  * [pr-update](#git-pr-update): 更新 PR 的标题、标签
* testing:
  * [coverage](#testing-coverage): 单测覆盖率上报
* artifact
  * [remove-tag](#artifact-remove-tag): 删除 CNB 制品标签
* tapd
  * [status-update](#tapd-status-update): 更新 TAPD 关联项（story、task 或 bug）状态
  * [comment](#tapd-comment): 提交 TAPD 关联项（story、task 或 bug）评论
* knowledge:
  * [update](#knowledge-update): 构建仓库的文档、Issue 等，并将其上传到知识库中
* npc:
  * [go](#npc-go): 执行 NPC 任务

## Docker

### cache {#docker-cache}

`docker:cache`

\==Docker 缓存==，构建一个 Docker 镜像作为缓存，在未来的构建中重复使用。

可以避免网络资源如 `依赖包` 重复下载。

* [适用事件](./#docker-cache-applicable-events)
* [参数](./#docker-cache-parameters)
* [输出结果](./#docker-cache-output)
* [配置样例](./#docker-cache-configuration-examples)

#### 适用事件 {#docker-cache-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#docker-cache-parameters}

* [dockerfile](./#docker-cache-parameters-dockerfile)
* [by](./#docker-cache-parameters-by)
* [versionBy](./#docker-cache-parameters-versionBy)
* [buildArgs](./#docker-cache-parameters-buildArgs)
* [target](./#docker-cache-parameters-target)
* [sync](./#docker-cache-parameters-sync)
* [ignoreBuildArgsInVersion](./#docker-cache-parameters-ignoreBuildArgsInVersion)

##### dockerfile {#docker-cache-parameters-dockerfile}

* type: `String`
* required: `true`

用于构建缓存镜像的 Dockerfile 路径。

为避免超长时间构建，Docker 镜像构建超时时间受 [job.timeout](../grammar.md#job-timeout) 参数控制。

##### by {#docker-cache-parameters-by}

* type: `Array<String>` | `String`
* required: `false`

用来声明缓存镜像构建过程中依赖的文件列表。

**注意：未出现在 `by` 列表中的文件，除了 Dockerfile，其他在构建镜像过程中，都当不存在处理。**

* 支持数组格式
* 支持字符串格式，多个文件用英文逗号分隔。

##### versionBy {#docker-cache-parameters-versionBy}

* type: `Array<String>` | `String`
* required: `false`

用来进行版本控制，未传入 `versionBy`，则默认取 `by` 的值进行版本控制。

`versionBy` 所指向的文件内容发生变化，我们就会认为是一个新的版本， 具体的计算逻辑见这个表达式：

`sha1(Dockerfile + versionBy + buildArgs + target + arch)`

* 支持数组格式。
* 支持字符串格式，多个文件用英文逗号分隔。

##### buildArgs {#docker-cache-parameters-buildArgs}

* type: `Object`
* required: `false`

在 build 时插入额外的构建参数 (`--build-arg $key=$value`), value 值为 null 时只加入 key (`--build-arg $key`)。

##### target {#docker-cache-parameters-target}

* type: `String`
* required: `false`

对应 docker build 中的 --target 参数，可以选择性地构建 Dockerfile 中的特定阶段，而不是构建整个 Dockerfile。

##### sync {#docker-cache-parameters-sync}

* type: `Boolean`
* required: `false`
* default: `false`

是否同步模式，`true` 则会等待缓存镜像 push 成功后才继续后续任务。

##### ignoreBuildArgsInVersion {#docker-cache-parameters-ignoreBuildArgsInVersion}

* type: `Boolean`
* required: `false`
* default: `false`

版本计算是否忽略 `buildArgs`。

参见 [版本控制](#docker-cache-parameters-versionBy)

#### 输出结果 {#docker-cache-output}

```javascript
{
  // 缓存对应的 docker image name
  name;
}
```

#### 配置样例 {#docker-cache-configuration-examples}

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        image: node:14
      stages:
        - name: build cache image
          type: docker:cache
          options:
            dockerfile: cache.dockerfile
            # by 支持以下两种形式：数组、字符串
            by:
              - package.json
              - package-lock.json
            # versionBy: package-lock.json
            versionBy:
              - package-lock.json
          exports:
            name: DOCKER_CACHE_IMAGE_NAME
        - name: use cache
          image: $DOCKER_CACHE_IMAGE_NAME
          # 将 cache 中的文件拷贝过来使用
          commands:
            - cp -r "$NODE_PATH" ./node_modules
        - name: build with cache
          script:
            - npm run build
```

其中 cache.dockerfile 是一个用于构建缓存镜像的 Dockerfile，示例：

```dockerfile
# 选择一个 Base 镜像
FROM node:14

# 设置工作目录
WORKDIR /space

# 将 by 中的文件列表 COPY 过来
COPY . .

# 根据 COPY 过来的文件进行依赖的安装
RUN npm ci

# 设置好需要的环境变量
ENV NODE_PATH=/space/node_modules
```

## cnb

### await {#cnb-await}

参见 [await-resolve](./#cnb-await-resolve)

### resolve {#cnb-resolve}

参见 [await-resolve](./#cnb-await-resolve)

### await-resolve {#cnb-await-resolve}

* `cnb:await`
* `cnb:resolve`

await 会等待 resolve 的执行，resolve 可以向 await 传递变量。

通过 `await-resolve`，可以让多个并发的 pipeline 相互配合，实现更灵活的顺序控制。

:::tip

`await-resolve` 同 `apply`、`trigger` 的区别：

前者指一个构建中某 pipeline 执行到 await 任务时等待对应 `key` 的其他 pipeline 的 resolve 通知才会继续进行。

后者指一个 pipeline 触发新 pipeline。可以异步调用，也可以同步等待。还可以跨仓库。
:::

* [使用限制](./#cnb-await-resolve-usage-limitations)
* [死锁检测](./#cnb-await-resolve-deadlock-detection)
* [适用事件](./#cnb-await-resolve-applicable-events)
* [await 参数](./#cnb-await-resolve-await-parameters)
* [resolve 参数](./#cnb-await-resolve-resolve-parameters)
* [输出结果](./#cnb-await-resolve-output)

#### 使用限制 {#cnb-await-resolve-usage-limitations}

1. 只能对 `同一个事件` 触发的 pipeline 进行 await 和 resolve 操作
2. 一个 `key` 仅能 resolve 一次，但可以 await 多次
3. 通过 `key` 对 await 和 resolve 进行分组
4. await-resolve 任务只能运行在流水线的 `stages` 中，不能运行在 `endStages` 和 `failStages` 中

#### 死锁检测 {#cnb-await-resolve-deadlock-detection}

await 和 resolve 相互配合可以完成灵活的流程控制，但也会引入更复杂的边界情况，比如：

* 死锁
  * pipeline-1 和 pipeline-2 相互 await
  * 多条 pipeline 间存在 await 环
* 无限等待
  * await 一个不存在的 key，或者 key 没有关联 resolve
  * resolve 所在 pipeline 执行失败
* 重复 resolve
  * 多个 resolve 任务关联同一个 key

`死锁检测` 机制会自动检测以上异常，结束 await 的等待状态，抛出 `dead lock found.` 异常。

await 和 resolve 的在配置文件中顺序不影响运行结果，即最后 await 任务一定是会等待相应的 resolve 完成，这种情况不会被 `死锁检测` 机制终止。

#### 适用事件 {#cnb-await-resolve-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### await 参数 {#cnb-await-resolve-await-parameters}

##### key {#cnb-await-resolve-await-parameters-key}

* type: String
* required: true

配对 ID

##### resolve 参数 {#cnb-await-resolve-resolve-parameters}

###### key {#cnb-await-resolve-resolve-parameters-key}

* type: String
* required: true

配对 ID

###### data {#cnb-await-resolve-resolve-parameters-data}

* type: object
* required: false

要传递的对象

`key: value` 格式，支持多级。示例：

```yaml{4-8}
- name: resolve a json
  type: cnb:resolve
  options:
    key: demo
    data:
      a: 1
      b:
        c: 2
```

await 任务的结果，是 resolve 声明的 `data` 对象。
可以通过 `exports` 访问这个对象，示例：

```yaml{3-7}
- name: await a json
  type: cnb:await
  options:
    key: demo
  exports:
    a: VAR_A
    b.c: VAR_B
- name: show var
  script:
    - echo ${VAR_A} # 1
    - echo ${VAR_B} # 2
```

当然，也可以不传送任务内容，仅仅表示一个等待动作：

```yaml
- name: ready
  type: cnb:resolve
  options:
    key: i-am-ready
```

```yaml
- name: ready
  type: cnb:await
  options:
    key: i-am-ready
```

###### 输出结果 {#cnb-await-resolve-output}

```javascript
{
  // resolve 返回的 data 内容
  data;
}
```

### apply {#cnb-apply}

`cnb:apply`

在当前仓库中，触发当前仓库的自定义事件流水线。

* [适用事件](./#cnb-apply-applicable-events)
* [参数](./#cnb-apply-parameters)
  * [环境变量相关](./#cnb-apply-environment-variables)
  * [config 取值优先级](./#cnb-apply-config-priority)
* [输出结果](./#cnb-apply-output)
* [配置样例](./#cnb-apply-configuration-examples)

#### 适用事件 {#cnb-apply-applicable-events}

* `push`
* `commit.add`
* `branch.create`
* `pull_request.target`
* `pull_request.mergeable`
* `tag_push`
* `pull_request.merged`
* `api_trigger`
* `web_trigger`
* `crontab`
* `tag_deploy`

#### 参数 {#cnb-apply-parameters}

* [config](./#cnb-apply-parameters-config)
* [configFrom](./#cnb-apply-parameters-configFrom)
* [event](./#cnb-apply-parameters-event)
* [sync](./#cnb-apply-parameters-sync)
* [continueOnBuildError](./#cnb-apply-parameters-continueOnBuildError)
* [title](./#cnb-apply-parameters-title)

##### config {#cnb-apply-parameters-config}

* type: `String`
* required: `false`

完整的 CI 配置文件内容。

##### configFrom {#cnb-apply-parameters-configFrom}

* type: `String`
* required: `false`

指定一个本地文件作为配置文件。

##### event {#cnb-apply-parameters-event}

* type: `String`
* required: `false`
* default: `api_trigger`

要执行的自定义事件名，必须为 `api_trigger` 或以 `api_trigger_` 开头。

##### sync {#cnb-apply-parameters-sync}

* type: `Boolean`
* required: `false`
* default: `false`
  是否同步执行。

同步模式下会等待本次 apply 流水线执行成功，再执行下一个任务。

##### continueOnBuildError {#cnb-apply-parameters-continueOnBuildError}

* type: `Boolean`
* required: `false`
* default: `false`

同步模式下，触发的流水线构建失败时，是否继续执行下个任务。

##### title {#cnb-apply-parameters-title}

* type: `String`
* required: `false`

自定义流水线标题

#### 环境变量相关 {#cnb-apply-environment-variables}

传递给新的流水线当前 Job 可见的、业务定义的环境变量。

默认值中有如下环境变量，**用户无法覆盖**：

* `APPLY_TRIGGER_BUILD_ID`，含义同 CI 默认环境变量中的 `CNB_BUILD_ID`
* `APPLY_TRIGGER_PIPELINE_ID`，含义同 CI 默认环境变量中的 `CNB_PIPELINE_ID`
* `APPLY_TRIGGER_REPO_SLUG`，含义同 CI 默认环境变量中的 `CNB_REPO_SLUG`
* `APPLY_TRIGGER_REPO_ID`，含义同 CI 默认环境变量中的 `CNB_REPO_ID`
* `APPLY_TRIGGER_USER`，含义同 CI 默认环境变量中的 `CNB_BUILD_USER`
* `APPLY_TRIGGER_BRANCH`，含义同 CI 默认环境变量中的 `CNB_BRANCH`
* `APPLY_TRIGGER_COMMIT`，含义同 CI 默认环境变量中的 `CNB_COMMIT`
* `APPLY_TRIGGER_COMMIT_SHORT`，含义同 CI 默认环境变量中的 `CNB_COMMIT_SHORT`
* `APPLY_TRIGGER_ORIGIN_EVENT`，含义同 CI 默认环境变量中的 `CNB_EVENT`
* `CNB_PULL_REQUEST_ID`，含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_ID`
* `CNB_PULL_REQUEST_IID`，含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_IID`
* `CNB_PULL_REQUEST_MERGE_SHA`，含义同 CI 默认环境变量中的 `CNB_PULL_REQUEST_MERGE_SHA`

##### Config 取值优先级 {#cnb-apply-config-priority}

按以下顺序依次取值，取到为止：

1. `config`
2. `configFrom`
3. 当前仓库 `.cnb.yml`
4. 若在 `pull_request.merged` 事件中调用 apply 内置任务，取合并后的配置文件
5. 若在 `pull_request.target`、`pull_request.mergeable` 事件中调用 `apply` 内置任务，取目标分支的配置文件
6. 其他情况取当前分支配置文件

`configFrom` 只支持本地文件如 `./test/.cnb.yml`，远程文件可先自行下到本地。

#### 输出结果 {#cnb-apply-output}

```json
{
  "sn": "cnb-i5o-1ht8e12hi", // 构建号
  "buildLogUrl": "https://cnb.share.ralphlauren.cn/<your-repo-slug>/-/build/logs/cnb-i5o-1ht8e12hi", // 构建日志链接
  "message": "success",
  "buildSuccess": true, // 触发的构建是否成功，此key仅在同步模式下存在
  "lastJobExports": {} // 触发的流水线最后一个job导出的环境变量
}
```

#### 配置样例 {#cnb-apply-configuration-examples}

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: trigger
          type: cnb:apply
          options:
            configFrom: ./test/.cnb.yml
            event: api_trigger_test
```

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: trigger
          type: cnb:apply
          options:
            config: |
              main:
                api_trigger_test: 
                - stages:
                  - name: test
                    script: echo test

            event: api_trigger_test
```

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: trigger
          type: cnb:apply
          options:
            # 执行当前配置文件的其它事件
            event: api_trigger_test
  api_trigger_test:
    - stages:
        - name: test
          script: echo test
```

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: trigger
          type: cnb:apply
          options:
            configFrom: .xxx.yml
            event: api_trigger_test
            sync: true
```

### trigger {#cnb-trigger}

`cnb:trigger`

在当前仓库中，触发指定仓库的自定义事件流水线（需要有触发对应仓库流水线的权限）。

* [适用事件](./#cnb-trigger-applicable-events)
* [参数](./#cnb-trigger-parameters)
* [输出结果](./#cnb-trigger-output)
* [配置样例](./#cnb-trigger-configuration-examples)
  * [基本使用](./#cnb-trigger-configuration-examples-basic-usage)

#### 适用事件 {#cnb-trigger-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#cnb-trigger-parameters}

* [token](./#cnb-trigger-parameters-token)
* [slug](./#cnb-trigger-parameters-slug)
* [event](./#cnb-trigger-parameters-event)
* [branch](./#cnb-trigger-parameters-branch)
* [sha](./#cnb-trigger-parameters-sha)
* [env](./#cnb-trigger-parameters-env)
* [sync](./#cnb-trigger-parameters-sync)
* [continueOnBuildError](./#cnb-trigger-parameters-continueOnBuildError)
* [title](./#cnb-trigger-parameters-title)

##### token {#cnb-trigger-parameters-token}

* type: `String`
* default: 环境变量 [CNB\_TOKEN](../build-in-env.md#cnb_token)

个人访问令牌。

新流水线触发者为令牌对应用户，会判断有无触发目标仓库流水线权限。

##### slug {#cnb-trigger-parameters-slug}

* type: `String`
* required: `true`

目标仓库的完整路径，如：group/repo。

##### event {#cnb-trigger-parameters-event}

* type: `String`
* required: `true`

触发的自定义事件名，必须是 `api_trigger` 或以 `api_trigger_` 开头。

需要目标仓库配置了对应分支、对应事件的流水线，才可以触发。

##### branch {#cnb-trigger-parameters-branch}

* type: `String`
* required: `false`

触发分支，默认为目标仓库主分支。

##### sha {#cnb-trigger-parameters-sha}

* type: `String`
* required: `false`

触发分支中的 CommitId，默认取 branch 的最新提交记录。

##### env {#cnb-trigger-parameters-env}

* type: [TriggerEnv](./#cnb-trigger-parameters-type-definitions-TriggerEnv)
* required: `false`

触发目标仓库流水线时指定传递过去的环境变量。

默认值中有如下环境变量，用户无法覆盖：

* `API_TRIGGER_BUILD_ID`，含义同 CI 默认环境变量中的 `CNB_BUILD_ID`
* `API_TRIGGER_PIPELINE_ID`，含义同 CI 默认环境变量中的 `CNB_PIPELINE_ID`
* `API_TRIGGER_REPO_SLUG`，含义同 CI 默认环境变量中的 `CNB_REPO_SLUG`
* `API_TRIGGER_REPO_ID`，含义同 CI 默认环境变量中的 `CNB_REPO_ID`
* `API_TRIGGER_USER`，含义同 CI 默认环境变量中的 `CNB_BUILD_USER`
* `API_TRIGGER_BRANCH`，含义同 CI 默认环境变量中的 `CNB_BRANCH`
* `API_TRIGGER_COMMIT`，含义同 CI 默认环境变量中的 `CNB_COMMIT`
* `API_TRIGGER_COMMIT_SHORT`，含义同 CI 默认环境变量中的 `CNB_COMMIT_SHORT`

##### sync {#cnb-trigger-parameters-sync}

* type: `Boolean`
* required: `false`
* default: `false`

是否同步执行，同步模式下会等待本次 trigger 流水线执行成功后，再执行下一个任务。

##### continueOnBuildError {#cnb-trigger-parameters-continueOnBuildError}

* type: `Boolean`
* required: `false`
* default: `false`

同步模式下，触发的流水线构建失败时，是否继续执行下个任务。

##### title {#cnb-trigger-parameters-title}

* type: `String`
* required: `false`

自定义流水线标题

##### 类型定义 {#cnb-trigger-parameters-type-definitions}

###### TriggerEnv {#cnb-trigger-parameters-type-definitions-TriggerEnv}

```javascript
{
    [key: String]: String | Number | Boolean
}
```

#### 输出结果 {#cnb-trigger-output}

```json
{
  "sn": "cnb-i5o-1ht8e12hi", // 构建号
  "buildLogUrl": "https://cnb.share.ralphlauren.cn/<your-repo-slug>/-/build/logs/cnb-i5o-1ht8e12hi", // 构建日志链接
  "message": "success",
  "buildSuccess": true, // 触发的构建是否成功，此key仅在同步模式下存在
  "lastJobExports": {} // 触发的流水线最后一个job导出的环境变量
}
```

#### 配置样例 {#cnb-trigger-configuration-examples}

##### 基本使用 {#cnb-trigger-configuration-examples-basic-usage}

在当前仓库触发指定仓库 main 分支下事件名为 `api_trigger_test` 的流水线。

该流水线配置文件使用仓库 main 分支的 `.cnb.yml` 文件。

使用访问令牌 `$TOKEN` 查询用户是否有触发目标仓库流水线权限。

```yaml title="cnb.yml"
main:
  push:
    - stages:
        - name: trigger
          type: cnb:trigger
          imports: https://cnb.cool/<your-repo-slug>/-/blob/main/xxx/envs.yml
          options:
            token: $TOKEN
            slug: a/b
            branch: main
            event: api_trigger_test
```

### read-file {#cnb-read-file}

`cnb:read-file`

读取指定文件内容，可导出为环境变量供后续任务使用。

用 `##[set-output key=value]` 指令输出变量更便捷，但会将内容输出到日志，不适用于敏感信息。

对于事先确定的敏感信息可以用 `imports` 导入，对于构建过程中生成的敏感信息，可写入文件，用该内置任务读取。

`imports` 只支持远端仓库存在的文件，该内置任务只支持读取本地存在的文件。

文件类型通过后缀判断，目前支持 `.json`、 `.yml`、`.yaml`、 纯文本（`key=value` 结构）。

* [适用事件](./#cnb-read-file-applicable-events)
* [参数](./#cnb-read-file-parameters)
* [输出结果](./#cnb-read-file-output)
* [配置样例](./#cnb-read-file-configuration-examples)

#### 适用事件 {#cnb-read-file-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#cnb-read-file-parameters}

##### filePath

* type: String
* required: true

本地文件路径。

#### 输出结果 {#cnb-read-file-output}

```json
{
  // 读到的对象
}
```

#### 配置样例 {#cnb-read-file-configuration-examples}

将一些后续任务需要的变量写入文件，用该内置任务读取文件导出为环境变量，供后续任务使用。

```json title="myJson.json"
{
  "myVar": "myVar",
  "deep": {
    "myVar": "myVar in deep"
  },
  "deepWithEnvKey": {
    "myVar": "myVar in deepWithEnvKey"
  }
}
```

```yaml title="cnb.yml"
main:
  push:
    - env:
        myKey: deepWithEnvKey
      stages:
        - name: write env file
          script: echo "write env to myJson.json"
        - name: export env
          type: cnb:read-file
          options:
            filePath: myJson.json
          exports:
            myVar: ENV_MY_VAR
            deep.myVar: ENV_DEEP_MY_VAR # 指定多级的key
            $myKey.myVar: ENV_ENV_KEY_MY_VAR # 通过环境变量指定获取的key
        - name: echo env
          script:
            - echo $ENV_MY_VAR
            - echo $ENV_DEEP_MY_VAR
            - echo $ENV_ENV_KEY_MY_VAR
```

### destroy-token {#cnb-destroy-token}

`cnb:destroy-token`

流水线启动前会创建 [CNB\_TOKEN](../build-in-env.md#cnb_token)，结束后会销毁。使用该任务可提前销毁 CNB\_TOKEN 并去掉该环境变量。

* [适用事件](./#cnb-read-file-applicable-events)
* [参数](./#cnb-read-file-parameters)
* [输出结果](./#cnb-read-file-output)
* [配置样例](./#cnb-read-file-configuration-examples)

#### 适用事件 {#cnb-destroy-token-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#cnb-destroy-token-parameters}

无

#### 输出结果 {#cnb-destroy-token-output}

无

#### 配置样例 {#cnb-destroy-token-configuration-examples}

流水线中使用 CNB\_TOKEN 后主动销毁，降低 CNB\_TOKEN 滥用风险。

```yaml title="cnb.yml"
main:
  push:
    - stages:
        - name: use CNB_TOKEN
          script: echo "Make API calls using the CNB_TOKEN."
        - name: destroy token
          type: cnb:destroy-token
```

## vscode

### go {#vscode-go}

`vscode:go`

云原生开发中是否配置该内置任务的区别：

* \==使用该任务==： 启动云原生开发时，需等待该任务执行完，才出现 WebIDE 和 VSCode/Cursor 客户端入口。
* \==不使用该任务==： 流水线 prepare 阶段执行完（code-server 代码服务启动），stages 任务执行前，就会出现 WebIDE 和 VSCode/Cursor 客户端入口。

上述入口出现时机区别：仅指从 `loading` 等待页到跳转入口选择页出现的时机。 实际上无论是否使用该任务，在 `code-server` 代码服务启动后，云原生开发已经是可用状态。

**注意：使用该任务将增加等待时间。如果需要延迟开发者进入时机，在某些任务执行完才允许进入云原生开发环境，可使用该任务。**

* [适用事件](./#vscode-go-applicable-events)
* [输出结果](./#vscode-go-output)
* [配置样例](./#vscode-go-configuration-examples)

#### 适用事件 {#vscode-go-applicable-events}

* `vscode`
* `branch.create`
* `api_trigger`
* `web_trigger`

#### 输出结果 {#vscode-go-output}

```json
{
  // webide url
  "url": ""
}
```

#### 配置样例 {#vscode-go-configuration-examples}

```yaml title=".cnb.yml"
$:
  # vscode 事件：专供页面中启动云原生开发用
  vscode:
    - docker:
        # 使用自定义镜像作为开发环境，未传入此参数，将使用默认镜像 cnbcool/default-dev-env:latest
        image: cnbcool/default-dev-env:latest
      services:
        - vscode
        - docker
      stages:
        # 希望等该任务执行完再进入开发环境
        - name: ls
          script: ls -al
        - name: vscode go
          type: vscode:go
        # 可以在进入开发环境后再执行的任务
        - name: ls
          script: ls -al
```

## git

### auto-merge {#git-auto-merge}

`git:auto-merge`

\==自动合并 Pull Request==，一般用于 PR 通过 `pull_request` 流水线检查 和 Code Review 后，在 `pull_request.mergeable` 流水线中自动合并 `PR`。无需人工点击合并按钮。

`pull_request.mergeable` 事件触发条件和时机参考[事件](../trigger-rule.md#pull_request-mergeable)。

* [适用事件](./#git-auto-merge-applicable-events)
* [参数](./#git-auto-merge-parameters)
* [输出结果](./#git-auto-merge-output)
* [配置样例](./#git-auto-merge-configuration-examples)
  * [单独使用](./#git-auto-merge-configuration-examples-standalone-usage)
  * [配合目标分支的 push 事件使用](./#git-auto-merge-configuration-examples-used-with-target-branch-push-event)
* [最佳实践](./#git-auto-merge-best-practices)
  * [使用 squash 自动合并](./#git-auto-merge-best-practices-using-squash-auto-merge)
  * [使用 auto 自动选择合并类型](./#git-auto-merge-best-practices-using-auto-automatically-select-merge-type)
  * [建立专用的 CR 群交叉走查自动合并](./#git-auto-merge-best-practices-establishing-dedicated-cr-group-cross-review-auto-merge)

#### 适用事件 {#git-auto-merge-applicable-events}

`pull_request.mergeable`

#### 参数 {#git-auto-merge-parameters}

* [mergeType](./#git-auto-merge-parameters-mergeType)
* [mergeCommitMessage](./#git-auto-merge-parameters-mergeCommitMessage)
* [mergeCommitFooter](./#git-auto-merge-parameters-mergeCommitFooter)
* [removeSourceBranch](./#git-auto-merge-parameters-removeSourceBranch)
* [ignoreAssignee](./#git-auto-merge-parameters-ignoreAssignee)

##### mergeType {#git-auto-merge-parameters-mergeType}

* type: `merge` | `squash` | `rebase` | `auto`
* required: `false`
* default: `auto`

合并策略，默认为 auto：如果多人提交走 merge ，否则走 squash 。

##### mergeCommitMessage {#git-auto-merge-parameters-mergeCommitMessage}

* type: `String`
* required: `false`

合并点提交信息。

1. 当合并策略为 `rebase` 的时候，该信息无效，无需填写。

2. 当合并策略为 `merge` 时，默认为 `chore: merge node(merged by CNB)` ，会自动追加 PR 引用、评审人名单、PR 包含的提交人名单。举例说明：

```txt
chore: merge node(merged by CNB)

PR-URL: !916
Reviewed-By: tom
Reviewed-By: jerry
Co-authored-by: jack
```

3. 当合并策略为 `squash` 时，默认值为该 PR 的第一条 commit message。并会自动追加 PR 引用和 评审人名单、PR 包含的提交人名单。举例说明：

```yaml title=".cnb.yml"
main:
  pull_request.mergeable:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: squash
```

该配置会产生如下效果：

某个 PR (feat/model-a -> main) 中有两条提交记录：

* 提交记录 1：2023-10-1 日提交

```txt
feat(model-a): 给模块 A 增加一个新特性

由于某某原因，新增某某特性

close #10
```

* 提交记录 2：修复了在 cr 时被指出的一些问题，2023-10-2 日提交

```txt
fix(model-a): 修复评审中指出的问题
```

在自动合并后将会在 main 分支上产生一个这样的提交节点，即后续的提交记录（也就是提交记录 2）将会被抹掉

```txt
feat(model-a): 给模块 A 增加一个新特性

由于某某原因，新增某某特性

close #10

PR-URL: !3976
Reviewed-By: tom
Reviewed-By: jerry
Co-authored-by: jack
```

4. 也可以直接指定

如通过环境变量指定为当前 PR 的标题：

```yaml title=".cnb.yml"
main:
  pull_request.mergeable:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeCommitMessage: $CNB_PULL_REQUEST_TITLE
```

##### mergeCommitFooter {#git-auto-merge-parameters-mergeCommitFooter}

* type: `String`
* required: `false`

合并点需要设置的脚注，多个脚注用 `\n` 分隔，仅在 `merge` 和 `squash` 生效。

当合并策略为 `rebase` 的时候，该信息无效，无需填写。

当合并策略为 `merge` 或 `squash` 时，会将传入信息按行加入到脚注中，再追加 PR 引用、评审人名单、PR 包含的提交人名单。举例说明：

```yaml title=".cnb.yml"
main:
  pull_request.mergeable:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: squash
            mergeCommitMessage: "add feature for some jobs"
            mergeCommitFooter: "--story=123\n--story=456"
```

```txt
add feature for some jobs

--story=123
--story=456
PR-URL: #916
Reviewed-By: tom
Reviewed-By: jerry
Co-authored-by: jack
```

##### removeSourceBranch {#git-auto-merge-parameters-removeSourceBranch}

* type: `Boolean`
* required: `false`
* default: `false`

合并后是否删除源分支。

源分支与目标分支不同仓库时，该值无效。

##### ignoreAssignee {#git-auto-merge-parameters-ignoreAssignee}

* type: `Boolean`
* required: `false`
* default: `false`

是否忽略 `assignee`。

当该 PR 有指定 `assignee` （指派人）的时候，本任务不会执行自动合并的逻辑。 因为 `assignee` 的本意就是指派某人手动来处理。

当为 `true` 时，可忽略 `assignee` 强行合并。

#### 输出结果 {#git-auto-merge-output}

```javascript
{
    reviewedBy, // String，追加在提交信息后面的提交者信息
    reviewers, // Array<String>, 走查者列表
}
```

#### 配置样例 {#git-auto-merge-configuration-examples}

##### 单独使用 {#git-auto-merge-configuration-examples-standalone-usage}

```yaml title=".cnb.yml"
main:
  pull_request.mergeable:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: merge
```

当分支 main 上的 PR 触发了 `pull_request.mergeable` 事件，那么会将这个 PR 以 `merge` 的方式自动合并。

##### 配合目标分支的 `push` 事件使用 {#git-auto-merge-configuration-examples-used-with-target-branch-push-event}

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: build
          script: npm run build
        - name: publish
          script: npm run publish
  pull_request.mergeable:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: merge
```

当分支 main 上的 PR 触发了 `pull_request.mergeable` 事件，那么会将这个 PR 以 `merge` 的方式自动合并。
在合并之后，**最后一个评审通过的评审者会作为触发者**，触发目标分支（main）上的 `push` 事件，继续执行声明的 `build` 和 `publish` 流程。

#### 最佳实践 {#git-auto-merge-best-practices}

##### 使用 `squash` 自动合并 {#git-auto-merge-best-practices-using-squash-auto-merge}

使用 `squash` 合并，一次 PR 操作只在目标分支产生一个 Commit 节点，并且在有权限的情况下删除源分支。

```yaml title=".cnb.yml"
main:
  review:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: squash
            removeSourceBranch: true
```

##### 使用 `auto` 自动选择合并类型 {#git-auto-merge-best-practices-using-auto-automatically-select-merge-type}

如果多人提交走 `merge` ，否则走 `squash`。

```yaml title=".cnb.yml"
main:
  review:
    - stages:
        - name: automerge
          type: git:auto-merge
          options:
            mergeType: auto
```

##### 建立专用的 CR 群交叉走查自动合并 {#git-auto-merge-best-practices-establishing-dedicated-cr-group-cross-review-auto-merge}

1. 走查通过后自动合并
2. 记录走查者信息在提交信息中

```yaml title=".cnb.yml"
main:
  pull_request.mergeable:
    - stages:
        - name: CR 通过后自动合并
          type: git:auto-merge
          options:
            mergeType: squash
            mergeCommitMessage: $CNB_LATEST_COMMIT_MESSAGE
          exports:
            reviewedBy: REVIEWED_BY
        - name: notify
          image: tencentcom/wecom-message
          settings:
            robot: "155af237-6041-4125-9340-000000000000"
            msgType: markdown
            content: |
              > CR 通过后自动合并 <@${CNB_BUILD_USER}> 
              > 　
              > ${CNB_PULL_REQUEST_TITLE}
              > [${CNB_EVENT_URL}](${CNB_EVENT_URL})
              > 
              > ${REVIEWED_BY}

  pull_request:
    - stages:
        # ...省略其它任务
        - name: notify
          image: tencentcom/wecom-message
          options:
            robot: "155af237-6041-4125-9340-000000000000"
            msgType: markdown
            content: |
              > ${CURR_REVIEWER_FOR_AT}
              > 
              > ${CNB_PULL_REQUEST_TITLE}
              > [${CNB_EVENT_URL}](${CNB_EVENT_URL})
              > 
              > from ${CNB_BUILD_USER}
```

### issue-update {#git-issue-update}

`git:issue-update`

\==更新 Issue 状态==，关闭或打开 Issue，修改 Issue 标签。

* [适用事件](./#git-issue-update-applicable-events)
* [工作机制](./#git-issue-update-work-mechanism)
* [Issue ID 获取方式](./#git-issue-update-how-to-get-issue)
* [提交日志中如何带上 Issue ID](./#git-issue-update-how-to-include-issue-id-in-commit-logs)
* [参数](./#git-issue-update-parameters)
* [输出结果](./#git-issue-update-output)
* [权限检查](./#git-issue-update-permission-check)
* [配置样例](./#git-issue-update-configuration-examples)

#### 适用事件 {#git-issue-update-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 工作机制 {#git-issue-update-work-mechanism}

查找 Issue 是否存在 -> 检查是否符合 when 条件（可选） -> 检查是否符合 lint 条件（可选）-> 更新 issue 状态或标签

#### Issue 获取方式 {#git-issue-update-how-to-get-issue}

**1. 当传入 `fromFile` 或 `fromText` 参数时：**

从传入的文本文件或文本中解析获取。`fromFile` 优先级高于 `fromText`。

**2. 当未传入 `fromFile` 或 `fromText` 参数时：**

* **Issue 相关事件：**

  取当前 Issue。

* **PR 相关事件：**

  从该 PR 的 commits 的提交日志中解析获取。

* **`commit.add` 事件：**

  从新增 commits 的提交日志中解析获取。

* **非新建分支的 `push` 事件：**

  从本次推送 commits 的提交日志中解析获取。

* **其他情况：**

  从最新 commit 的提交日志中解析获取。

:::tip
如果需要在 `branch.delete` 事件中使用，由于分支已删除，无法从上下文中获取，需要使用 `fromText` 或者 `fromFile` 参数提供解析内容。
:::

获取方式：提取上述文本中如下两种格式

* `#IssueID`：表示当前仓库的 Issue。例如 #123，表示当前仓库 id 为 123 的 Issue。
* `groupName/repoName#IssueID`：表示跨仓库（其他仓库）的 Issue。例如：test/test#123，表示 test/test 仓库中 id 为 123 的 Issue。

注意 #123 或 test/test#123 前需要有空格。

#### 提交日志中如何带上 `IssueID` {#git-issue-update-how-to-include-issue-id-in-commit-logs}

提交代码时，可以在提交日志中加上关联的 `IssueID`， 可以在使用当前内置任务时可以自动提取到关联 Issue，用来更新 Issue 标签和状态

推荐在提交日志的 body 中带上 `IssueID`，命令行操作方式如下：

* 方法一：用 `shift + enter` 换行，建议 title 和 body 之间加上一个空行

```shell
git commit -m "fix(云原生构建): 修复一个错误

cnb/feedback#123"
```

* 方法二：

以下提交方式 title 和 body 之间会产生两个换行

```shell
git commit -m "fix(云原生构建): 修复一个错误" -m "cnb/feedback#123"
```

#### 参数 {#git-issue-update-parameters}

* [fromText](./#git-issue-update-parameters-fromText)
* [fromFile](./#git-issue-update-parameters-fromFile)
* [state](./#git-issue-update-parameters-state)
* [label](./#git-issue-update-parameters-label)
* [assignee](./#git-issue-update-parameters-assignee)
* [when](./#git-issue-update-parameters-when)
* [lint](./#git-issue-update-parameters-lint)
* [defaultColor](./#git-issue-update-parameters-defaultColor)
* [prefix](./#git-issue-update-parameters-prefix)

##### fromText {#git-issue-update-parameters-fromText}

* type: `String`
* required: `false`

从给定的文本中解析 `IssueId`。

不声明时，自动从上下文里的提交记录解析。可以指定一个包含 `IssueId` 引用的文本来声明操作对象，比如配合变更日志生成插件一起使用，将变更日志中的 `IssueId` 自动提取出来。

##### fromFile {#git-issue-update-parameters-fromFile}

* type: `String`
* required: `false`

从文本文件中读取内容并解析 `IssueId`。优先级高于 `fromText`。

**当内容过多时，建议使用该参数，将内容通过文件传递，避免超出限制。**

##### state {#git-issue-update-parameters-state}

* type: [IssueStateMap](#git-issue-update-parameters-type-definitions-issuestatemap)
* required: `false`

对应 `state` 属性，为 `close` 时，可关闭 `Issue`。

##### label {#git-issue-update-parameters-label}

* type: [UpdateLabel](#git-parameters-type-definitions-updatelabel)
* required: `false`

对 `label` 的操作描述。

##### assignee {#git-issue-update-parameters-assignee}

* type: [UpdateAssignee](#git-parameters-type-definitions-updateassignee)
* required: `false`

对 `处理人` 的操作描述。

##### when {#git-issue-update-parameters-when}

* type: [IssueUpdateStatus](#git-issue-update-parameters-type-definitions-issueupdatestatus)
* required: `false`

过滤条件，多个条件之间是 `or` 关系。为空时表示对所有 `Issue` 操作。

##### lint {#git-issue-update-parameters-lint}

* type: [IssueUpdateStatus](#git-issue-update-parameters-type-definitions-issueupdatestatus)
* required: `false`

检查 `Issue` 是否满足条件，不满足时抛出异常，多个条件之间是 `or` 关系，为空时表示不做检查。

##### defaultColor {#git-issue-update-parameters-defaultColor}

* type: `String`
* required: `false`

添加的标签的默认颜色，当有传入 `label.add` 参数时才有效。

##### prefix {#git-issue-update-parameters-prefix}

* type: `String[]`
* required: `false`

需要处理的 issue 前缀，例如如果传入的是 `close` 和 `closed`，则会处理所有带有 `close` 和 `closed` 前缀的 issue。例如 `close #123` 或 `closed #123 #456`

##### 类型定义 {#git-issue-update-parameters-type-definitions}

###### IssueStateMap {#git-issue-update-parameters-type-definitions-issuestatemap}

* `Enum<String>`:  open | close

###### UpdateLabel {#git-parameters-type-definitions-updatelabel}

* add
  * type: `Array<String>` | `String`
  * required: `false`

要添加的标签列表，标签不存在时，会自动创建。

* remove
  * type: `Array<String>` | `String`
  * required: `false`

要移除的标签列表

###### UpdateAssignee {#git-parameters-type-definitions-updateassignee}

* add
  * type: `Array<String>` | `String`
  * required: `false`

要添加的处理人列表。

* remove
  * type: `Array<String>` | `String`
  * required: `false`

要移除的处理人列表

###### IssueUpdateStatus {#git-issue-update-parameters-type-definitions-issueupdatestatus}

* label
  * type: `Array<String>` | `String`
  * required: `false`

标签，多个值之间是 `or` 关系

#### 输出结果 {#git-issue-update-output}

```javascript
{
    issues // issue 列表
}
```

#### 权限检查  {#git-issue-update-permission-check}

若需要更新的 Issue 属于流水线所属仓库，
且非 `pull_request`, `pull_request.update`, `pull_request.approved`, `pull_request.changes_requested` 事件，
则不会检查流水线触发者是否拥有修改 Issue 的权限。

#### 配置样例 {#git-issue-update-configuration-examples}

* 合并到 main 后，更新标签

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: update issue
          type: git:issue-update
          options:
            # 移除 “开发中” 标签，添加 “预发布” 标签
            label:
              add: 预发布
              remove: 开发中
            # 当有 “feature” 或 “bug” 标签才进行上述标签操作
            when:
              label:
                - feature
                - bug
```

* Tag push 时，关闭 Issue，更新标签

```yaml title=".cnb.yml"
$:
  tag_push:
    - stages:
        - name: 发布操作
          script: echo "可用发布任务替代当前任务"
        # 发布操作后执行 issue 更新操作
        - name: update issue
          type: git:issue-update
          options:
            # 关闭 issue
            state: close
            # 可选择指定需要关闭的 issue 前缀，如果设置了，则包含 close #123 或 closed #123 这种才会被关闭
            # prefix:
            #   - close
            #   - closed
            # 移除 “预发布” 标签，添加 “已发布” 标签
            label:
              add: 已发布
              remove: 预发布
            # 当有 “feature” 或 “bug” 标签才进行上述操作
            when:
              label:
                - feature
                - bug
```

* Tag push 时，根据当前 tag 和前一个 tag 的变更内容，找到变更内容中包含的 `IssueId`，并添加标签

```yaml title=".cnb.yml"
$:
  tag_push:
    - stages:
        - name: changelog
          image: cnbcool/changelog
          settings:
            latestChangeLogTarget: LATEST_CHANGELOG.md
        - name: update issue
          type: git:issue-update
          options:
            fromFile: LATEST_CHANGELOG.md
            label:
              add: 需求已接收
            when:
              label: feature
```

### reviewer {#git-reviewer}

`git:reviewer`

\==配置评审人或处理人==给 PR 添加、删除评审人/处理人，可指定备选评审人/处理人范围。

* [适用事件](./#git-reviewer-applicable-events)
* [参数](./#git-reviewer-parameters)
* [输出结果](./#git-reviewer-output)
* [配置样例](./#git-reviewer-configuration-examples)
* [最佳实践](./#git-reviewer-best-practices)

#### 适用事件 {#git-reviewer-applicable-events}

* `pull_request`
* `pull_request.target`
* `pull_request.update`

`pull_request` 和 `pull_request.update` 事件下会检查触发者是否有权限操作评审人/处理人。`pull_request.target` 事件下则不会。
对于跨仓提交的 PR，可能存在触发者无权限的情况。此时推荐使用 `pull_request.target` 事件。

#### 参数 {#git-reviewer-parameters}

* [type](./#git-reviewer-parameters-type)
* [reviewers](./#git-reviewer-parameters-reviewers)
* [count](./#git-reviewer-parameters-count)
* [exclude](./#git-reviewer-parameters-exclude)
* [reviewersConfig](./#git-reviewer-parameters-reviewersConfig)
* [role](./#git-reviewer-parameters-role)
* [skip\_on\_wip](./#git-reviewer-parameters-skip_on_wip)

##### type {#git-reviewer-parameters-type}

* type: [REVIEW\_OPERATION\_TYPE](./#git-reviewer-parameters-type-definitions-REVIEW_OPERATION_TYPE)
* required: `false`
* default: `add-reviewer`

操作类型：

* `add-reviewer`: 添加评审人，会从 `reviewers` 参数中选择指定数量的评审人
* `add-reviewer-from-repo-members`: 从仓库直接成员里选一名，添加为评审人
* `add-reviewer-from-group-members`: 从仓库父组织（直接上级组织）里选一名，添加为评审人
* `add-reviewer-from-outside-collaborator-members`: 从仓库的外部协作者里选一名，添加为评审人
* `remove-reviewer`: 从已有的评审人中删除指定的成员
* `add-assignee`: 添加处理人，添加 `reviewers` 参数传入的成员
* `remove-assignee`: 从已有的处理人中删除指定的成员

##### reviewers {#git-reviewer-parameters-reviewers}

* type: `Array<String>` | `String`
* required: `false`

要添加或删除的评审人用户名。多个使用 `,` 或 `;` 分隔。

`type` 为 `add-reviewer`、`remove-reviewer`、`add-assignee`、`remove-assignee` 时有效。

若同时配置了 `reviewers` 、 `reviewersConfig` ，则会在两者中随机选指定数量的评审人或处理人

##### count {#git-reviewer-parameters-count}

* type: `Number`
* required: `false`

指定要添加的评审人或处理人数量，随机抽取指定数量的评审人或处理人。

* 当 `type` 为 `add-reviewer` 或 `add-assignee` 时，`count` 缺省值为 `reviewers` 的数量，即全部添加
* 当 `type` 为 `add-reviewer-from-repo-members`、`add-reviewer-from-group-members` 或 `add-reviewer-from-outside-collaborator-members` 时：
  * 若目标分支为保护分支且设置了需要评审人批准，`count` 缺省值为需要批准的评审人数量
  * 其他情况，`count` 缺省值为 1

如果已有评审人或处理人的数量 `< count` ，那么补齐。

如果已有评审人或处理人的数量 `>= count` ，那么什么也不做。

##### exclude {#git-reviewer-parameters-exclude}

* type: `Array<String>` | `String`
* required: `false`

排除指定的用户。

##### reviewersConfig {#git-reviewer-parameters-reviewersConfig}

* type: [IReviewersConfig](./#git-reviewer-parameters-type-definitions-IReviewersConfig) | `String`
* required: `false`

文件评审人或处理人配置，如果配置中有配置当前变更文件的评审人或处理人，则会被添加为评审人或处理人。

`type` 为 `add-reviewer` 或 `add-assignee` 时有效。

支持两种格式：

* 字符串格式，传入配置文件相对路径(支持 `json` 文件)：

```json
{
  "reviewersConfig": "config.json"
}
```

```json title="config.json"
{
  "./src": "name1,name2",
  ".cnb.yml": "name3"
}
```

* 对象格式，传入文件评审人配置：

```json
{
  "reviewersConfig": {
    "./src": "name1,name2",
    ".cnb.yml": "name3"
  }
}
```

其中，文件评审人或处理人配置的 `key` 为文件相对路径；`value` 为评审人或处理人英文名，用英文逗号分隔。

若同时配置了 `reviewers` 、`reviewersConfig`，则会在两者中随机选指定数量的评审人或处理人。

##### role {#git-reviewer-parameters-role}

* type: [ROLE\_TYPE](./#git-reviewer-parameters-type-definitions-ROLE_TYPE)
* required: `false`

评审人或处理人可以添加的角色可选包括：`Developer`、`Master`、`Owner` 如果选择 `Developer`，则可添加 `Developer` 及以上权限成员，包括 `Developer`、`Master`、`Owner`

##### skip\_on\_wip {#git-reviewer-parameters-skip\_on\_wip}

* type: `Boolean`
* required: `false`
* default: `true`

是否跳过 `WIP` 状态的 PR（PR 标题开头带有 `[WIP]` 标记），默认跳过 `WIP` 状态的 PR。

* `true`: 当 PR 为 `WIP` 状态时，不会添加评审人或处理人。
* `false`: 当 PR 为 `WIP` 状态时，仍会添加评审人或处理人。

##### 类型定义 {#git-reviewer-parameters-type-definitions}

###### REVIEW\_OPERATION\_TYPE {#git-reviewer-parameters-type-definitions-REVIEW\_OPERATION\_TYPE}

* `Enum<String>`: add-reviewer | add-reviewer-from-repo-members | add-reviewer-from-group-members | add-reviewer-from-outside-collaborator-members | remove-reviewer | add-assignee | remove-assignee

###### IReviewersConfig {#git-reviewer-parameters-type-definitions-IReviewersConfig}

```javascript
{
    [key: String]: String
}
```

###### ROLE\_TYPE {#git-reviewer-parameters-type-definitions-ROLE\_TYPE}

* `Enum<String>`: Developer | Master | Owner

#### 输出结果 {#git-reviewer-output}

添加评审人的输出结果：

```json
{
  // 当前有效的评审人
  "reviewers": [],

  // reviewers 对应的 at 消息格式，方便发送通知
  "reviewersForAt": []
}
```

添加处理人的输出结果：

```json
{
  // 当前有效的处理人
  "assignees": [],

  // assignees 对应的 at 消息格式，方便发送通知
  "assigneesForAt": []
}
```

#### 配置样例 {#git-reviewer-configuration-examples}

* 添加评审人和处理人

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: 添加评审人
          type: git:reviewer
          options:
            type: add-reviewer
            reviewers: aaa;bbb

        - name: 添加处理人
          type: git:reviewer
          options:
            type: add-assignee
            reviewers: ccc;ddd
```

* 删除指定成员的评审人和处理人

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: 删除评审人
          type: git:reviewer
          options:
            type: remove-reviewer
            reviewers: aaa

        - name: 删除处理人
          type: git:reviewer
          options:
            type: remove-assignee
            reviewers: aaa
```

* 结合 `ifModify`，指定文件被修改时添加评审人和处理人

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: 改配置？需要特别 review
          ifModify:
            - ".cnb.yml"
            - "configs/**"
          type: git:reviewer
          options:
            type: add-reviewer
            reviewers: bbb

        - name: 改配置？需要特别处理
          ifModify:
            - ".cnb.yml"
            - "configs/**"
          type: git:reviewer
          options:
            type: add-assignee
            reviewers: ccc
```

* 结合 `if`，在指定条件下将某些人添加为评审人或处理人

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: 下班时间发版本？需指定人评审。
          if: |
            [ $(date +%H) -ge 18 ]
          type: git:reviewer
          options:
            type: add-reviewer
            reviewers: bbb

        - name: 下班时间发版本？需指定人处理。
          if: |
            [ $(date +%H) -ge 18 ]
          type: git:reviewer
          options:
            type: add-assignee
            reviewers: ccc
```

* 随机选择一名负责人走查代码

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: random
          image: tencentcom/random
          settings:
            from:
              - aaa
              - bbb
          exports:
            result: CURR_REVIEWER
        - name: show  CURR_REVIEWER
          script: echo ${CURR_REVIEWER}
        - name: add reviewer
          type: git:reviewer
          options:
            type: add-reviewer
            reviewers: ${CURR_REVIEWER}
```

* 从当前仓库成员里选一名评审人进行评审

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: add reviewer
          type: git:reviewer
          options:
            type: add-reviewer-from-repo-members
```

#### 最佳实践 {#git-reviewer-best-practices}

建立专用的 CR 群，交叉评审自动合并

1. PR 随机选择 N 名评审者，通知到群
2. 评审通过后自动合并
3. 记录评审者信息在提交信息中
4. Git 设置满足多人评审自动合并策略实现多人交叉评审

```yaml title=".cnb.yml"
main:
  review:
    - stages:
        - name: CR 通过后自动合并
          type: git:auto-merge
          options:
            mergeType: squash
            removeSourceBranch: true
            mergeCommitMessage: $CNB_LATEST_COMMIT_MESSAGE
          exports:
            reviewedBy: REVIEWED_BY
        # 将评审消息发送到企业微信机器人
        - name: notify
          image: tencentcom/wecom-message
          settings:
            msgType: markdown
            robot: "155af237-6041-4125-9340-000000000000"
            content: |
              > CR 通过后自动合并 <@${CNB_BUILD_USER}> 
              > 　
              > ${CNB_PULL_REQUEST_TITLE}
              > [${CNB_EVENT_URL}](${CNB_EVENT_URL})
              > 
              > ${REVIEWED_BY}

  pull_request:
    - stages:
        # ...省略其它任务

        # 发送到 CR 专用群
        - name: add reviewer
          type: git:reviewer
          options:
            reviewers: aaa,bbb,ccc,ddd
            count: 2
          exports:
            reviewersForAt: CURR_REVIEWER_FOR_AT
        - name: notify
          image: tencentcom/wecom-message
          settings:
            msgType: markdown
            robot: "155af237-6041-4125-9340-000000000000"
            content: |
              > ${CURR_REVIEWER_FOR_AT}
              > 　
              > ${CNB_PULL_REQUEST_TITLE}
              > [${CNB_EVENT_URL}](${CNB_EVENT_URL})
              > 　
              > from ${CNB_BUILD_USER}
```

### release {#git-release}

`git:release`

\==仓库发布 Release==

* [适用事件](./#git-release-applicable-events)
* [参数](./#git-release-parameters)
* [输出结果](./#git-release-output)
* [配置样例](./#git-release-configuration-examples)

#### 适用事件 {#git-release-applicable-events}

* `push`
* `commit.add`
* `branch.create`
* `tag_push`
* `pull_request.merged`
* `api_trigger`
* `web_trigger`
* `tag_deploy`

#### 参数 {#git-release-parameters}

* [overlying](./#git-release-parameters-overlying)
* [tag](./#git-release-parameters-tag)
* [title](./#git-release-parameters-title)
* [description](./#git-release-parameters-description)
* [descriptionFromFile](./#git-release-parameters-descriptionFromFile)
* [preRelease](./#git-release-parameters-preRelease)
* [latest](./#git-release-parameters-latest)

:::tip
该内置任务不支持上传附件，
可使用 [cnbcool/attachments](../../../plugin/#public/cnbcool/attachments) 任务上传附件。
:::

##### overlying {#git-release-parameters-overlying}

* type: `Boolean`
* required: `false`
* default: `false`

叠加模式

* `true`：叠加模式，即本次仅为编辑或更新 Release。
* `false`：非叠加模式，即先删除，再重新创建 Release。

:::warning
默认为 `false`，即，当 Release 版本已经存在时，会先删除这个版本，重新生成。
:::

##### tag {#git-release-parameters-tag}

* type: `String` | `Number`
* required: `false`

`release` 对应的 Tag 名，非必填

`tag_push` 事件无需传入，直接取触发 `tag_push` 事件的 Tag 名。

非 `tag_push` 事件必填，用来作为 Releas 对应的 Tag 名。

##### title {#git-release-parameters-title}

* type: `String`
* required: `false`
* default: `tag` 名

Release 的标题

##### description {#git-release-parameters-description}

* type: `String`
* required: `false`

Release 的描述。**当内容过多时，建议使用 `descriptionFromFile` 参数，将内容通过文件传递，避免超出限制。**

:::warning
`description` 和 `descriptionFromFile` 互斥，不能同时指定。
:::

##### descriptionFromFile {#git-release-parameters-descriptionFromFile}

* type: `String`
* required: `false`

从文件中读取内容作为 Release 的描述。

指定一个本地文件路径，系统会读取该文件的内容，然后将其作为 Release 的描述。

:::warning
`description` 和 `descriptionFromFile` 互斥，不能同时指定。
:::

##### preRelease {#git-release-parameters-preRelease}

* type: `Boolean`
* required: `false`
* default: `false`

是否将 `release` 设置为 预发布

##### latest {#git-release-parameters-latest}

* type: "true" | "false" | true | false
* required: `false`
* default: `false`

是否将 Release 设置为最新版本

#### 输出结果 {#git-release-output}

无

#### 配置样例 {#git-release-configuration-examples}

* 生成 changelog 并自动更新 Release 描述

```yaml title=".cnb.yml"
$:
  tag_push:
    - stages:
        - name: changelog
          image: cnbcool/changelog
          settings:
            latestChangeLogTarget: LATEST_CHANGELOG.md
        - name: upload release
          type: git:release
          options:
            title: release
            descriptionFromFile: LATEST_CHANGELOG.md
```

* 主分支 push 时发布 Release

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: git release
          type: git:release
          options:
            tag: Nightly
            description: description
```

### pr-commit-message-preset {#git-pr-commit-message-preset}

`git:pr-commit-message-preset`

\==预先设置 PR 的 提交信息。==

当用户在 PR 界面中选择 Merge 或者 Squash 合并时，会自动将该 message 填入提交消息内。

* [适用事件](./#git-pr-commit-message-preset-events)
* [参数](./#git-pr-commit-message-preset-parameters)
* [输出结果](./#git-pr-commit-message-preset-output)
* [配置样例](./#git-pr-commit-message-preset-configuration-examples)

#### 适用事件 {#git-pr-commit-message-preset-events}

* `pull_request`
* `pull_request.target`
* `pull_request.update`
* `pull_request.mergeable`
* `pull_request.approved`
* `pull_request.changes_requested`

#### 参数 {#git-pr-commit-message-preset-parameters}

* [message](./#git-pr-commit-message-preset-parameters-message)

##### message {#git-pr-commit-message-preset-parameters-message}

* type: `String`
* required: `true`

预先设置的 PR 的 提交信息。

#### 输出结果 {#git-pr-commit-message-preset-output}

无

#### 配置样例 {#git-pr-commit-message-preset-configuration-examples}

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: prepare pull request commit message
          type: git:pr-commit-message-preset
          options:
            message: Pull request commit message set by CI.
```

### pr-update {#git-pr-update}

`git:pr-update`

\==更新 PR 的标签、标题==。

* [适用事件](./#git-pr-update-applicable-events)
* [PR ID 获取方式](./#git-pr-update-how-to-get-pr)
* [提交日志中如何带上 PR ID](./#git-pr-update-how-to-include-pr-id-in-commit-logs)
* [参数](./#git-pr-update-parameters)
* [输出结果](./#git-pr-update-output)
* [权限检查](./#git-pr-update-permission-check)
* [配置样例](./#git-pr-update-configuration-examples)

#### 适用事件 {#git-pr-update-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### PR 获取方式 {#git-pr-update-how-to-get-pr}

**1. 当传入 `fromFile` 或 `fromText` 参数时：**

从传入的文本文件或文本中解析获取。`fromFile` 优先级高于 `fromText`。

**2. 当未传入 `fromFile` 或 `fromText` 参数时：**

* **PR 相关事件：**

  从该 PR 的 commits 的提交日志中解析获取。同时追加当前 PR。

* **`commit.add` 事件：**

  从新增 commits 的提交日志中解析获取。

* **非新建分支的 `push` 事件：**

  从本次推送 commits 的提交日志中解析获取。

* **其他情况：**

  从最新 commit 的提交日志中解析获取。

:::tip
如果需要在 `branch.delete` 事件中使用，由于分支已删除，无法从上下文中获取，需要使用 `fromText` 或者 `fromFile` 参数提供解析内容。
:::

获取方式：提取上述文本中如下两种格式

* `PR-URL: <your-repo-slug>#<number>`
* `PR-URL: #<number>`

`your-repo-slug` 为仓库的路径，比如 `cnbcool/cnb`。
`number` 为 PR 的编号，为 PR 页面地址后的数字。

> 为了和 `Issue` 区分，需要在前面加上 `PR-URL:`。

注意 `#123` 或 `test/test#123` 前需要有空格。

#### 参数 {#git-pr-update-parameters}

* [fromText](./#git-pr-update-parameters-fromtext)
* [fromFile](./#git-pr-update-parameters-fromfile)
* [label](./#git-pr-update-parameters-label)
* [title](./#git-pr-update-parameters-title)
* [defaultColor](./#git-pr-update-parameters-defaultcolor)

##### fromText {#git-pr-update-parameters-fromtext}

* type: `String`
* required: `false`

从给定的文本中解析 PR。

不声明时，自动从上下文里的提交记录解析。可以指定一个包含 `PR ID` 引用的文本来声明操作对象，比如配合变更日志生成插件一起使用，将变更日志中的 `PR ID` 自动提取出来。

##### fromFile {#git-pr-update-parameters-fromfile}

* type: `String`
* required: `false`

从文本文件中读取内容并解析 PR。优先级高于 `fromText`。

##### label {#git-pr-update-parameters-label}

* type: [UpdateLabel](#git-parameters-type-definitions-UpdateLabel)
* required: `false`

需要添加、删除的标签。

##### title {#git-pr-update-parameters-title}

* type: `String`
* required: `false`

PR 的标题。

##### defaultColor {#git-pr-update-parameters-defaultcolor}

* type: `String`
* required: `false`

添加的标签的默认颜色，当有传入 `label.add` 参数时才有效。

#### 输出结果 {#git-pr-update-output}

```javascript
{
    pullRequests // 修改的 pr 列表
}
```

#### 权限检查  {#git-pr-update-permission-check}

若需要更新的 PR 属于流水线所属仓库，
且非 `pull_request`, `pull_request.update`, `pull_request.approved`, `pull_request.changes_requested` 事件，
则不会检查流水线触发者是否拥有修改 PR 的权限。

#### 配置样例 {#git-pr-update-configuration-examples}

如下流水线实现了以下功能：

1. `pull_request` 流水线失败，增加标签 `待修改`。
2. `pull_request` 流水线成功，增加标签 `待评审`，删除标签 `待修改`。
3. `pull_request.merged` 流水线，增加标签 `待发布`，删除标签 `待评审`。

```yaml title=".cnb.yml"
main:
  pull_request:
    - stages:
        - name: check
          script: echo "do some check"
        - name: 添加PR标签-待评审
          type: git:pr-update
          options:
            label:
              add:
                - 待评审
              remove:
                - 待修改
      failStages:
        - name: 添加PR标签-待修改
          type: git:pr-update
          options:
            label:
              add:
                - 待修改

  pull_request.merged:
    - stages:
        - name: check
          script: echo "do some check"
        - name: 添加PR标签-待发布
          type: git:pr-update
          options:
            label:
              add:
                - 待发布
              remove:
                - 待评审
```

## testing

### coverage {#testing-coverage}

`testing:coverage`

\==单测覆盖率==，通过单测结果报告，计算单测覆盖率结果，并上报徽章数据。

可以在仓库的 `洞察` 页面以图表的形式按分支查看最近 100 个 Commit 的覆盖率徽章数据上报结果。

:::tip
Pull Request 相关事件（除了 `pull_request.merged`）触发的流水线上传的覆盖率数据，要查看单元测试洞察曲线，需要切换到合并请求视图。
:::

* [适用事件](./#testing-coverage-applicable-events)
* [全量覆盖率](./#testing-coverage-full-coverage)
* [增量覆盖率](./#testing-coverage-incremental-coverage)
* [参数](./#testing-coverage-parameters)
* [输出结果](./#testing-coverage-output)
* [配置样例](./#testing-coverage-configuration-examples)

#### 适用事件 {#testing-coverage-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 全量覆盖率 {#testing-coverage-full-coverage}

![coverage](//cnb.share.ralphlauren.cn/svg/badge/coverage?message=18.67%25\&color=l2)
![coverage](//cnb.share.ralphlauren.cn/svg/badge/coverage?message=38.67%25\&color=l3)
![coverage](//cnb.share.ralphlauren.cn/svg/badge/coverage?message=58.67%25\&color=l4)
![coverage](//cnb.share.ralphlauren.cn/svg/badge/coverage?message=78.67%25\&color=l5)

从本地覆盖率报告文件解析而来，目前可识别以下格式的报告：

* `json(js)`（推荐使用）
* `json-summary`
* `lcov`（推荐使用）
* `jacoco`
* `golang`

#### 增量覆盖率 {#testing-coverage-incremental-coverage}

![coverage-pr](//cnb.share.ralphlauren.cn/svg/badge/coverage%20%40pr?message=18.67%25\&color=l2)
![coverage-pr](//cnb.share.ralphlauren.cn/svg/badge/coverage%20%40pr?message=38.67%25\&color=l3)
![coverage-pr](//cnb.share.ralphlauren.cn/svg/badge/coverage%20%40pr?message=58.67%25\&color=l4)
![coverage-pr](//cnb.share.ralphlauren.cn/svg/badge/coverage%20%40pr?message=78.67%25\&color=l5)

#### 参数 {#testing-coverage-parameters}

* [key](./#testing-coverage-parameters-key)
* [name](./#testing-coverage-parameters-name)
* [pattern](./#testing-coverage-parameters-pattern)
* [lines](./#testing-coverage-parameters-lines)
* [diffLines](./#testing-coverage-parameters-diffLines)
* [allowExts](./#testing-coverage-parameters-allowExts)
* [lang](./#testing-coverage-parameters-lang)
* [breakIfNoCoverage](./#testing-coverage-parameters-breakIfNoCoverage)

##### key {#testing-coverage-parameters-key}

* type: `String`
* required: `false`

覆盖率数据 key 值，用于区分不同类型的覆盖率数据，例如 frontend、backend 等。如果仓库仅包含一种覆盖率数据，则可以忽略此参数。

##### name {#testing-coverage-parameters-name}

* type: `String`
* required: `false`

覆盖率数据名称，用于展示在徽章中，和覆盖率数据 key 一一对应，key 不存在时，name 将被忽略。

例如：`key: frontend`, `name: 前端覆盖率`

##### pattern {#testing-coverage-parameters-pattern}

* type: `String`
* required: `false`

Glob 格式，指定覆盖率报告文件位置，相对于当前工作目录。 缺省时，将尝试查找当前目录（包括子目录）下的以下文件：coverage.json、jacoco\*.xml、lcov.info、\*.lcov。

##### lines {#testing-coverage-parameters-lines}

* type: `Number`
* required: `false`

指定全量覆盖率红线，判断如果全量覆盖率百分比小于该值，阻断工作流退出流水线。

##### diffLines {#testing-coverage-parameters-diffLines}

* type: `Number`
* required: `false`

指定增量覆盖率红线，判断如果全量覆盖率百分比小于该值，阻断工作流退出流水线。 `pull_request`、`pull_request.update`、`pull_request.target` 事件支持计算增量覆盖率结果，其他事件只计算全量覆盖率。

##### allowExts {#testing-coverage-parameters-allowExts}

* type: `String`
* required: `false`

参与覆盖率计算的代码文件类型白名单，逗号分隔, 如：`.json`, `.ts`, `.js`。 缺省时报告中的文件都会参与计算。

##### lang {#testing-coverage-parameters-lang}

* type: `String`
* required: `false`

当覆盖率结果报告目标格式为 `golang` 时，请指定此参数 为 `go`，否则会出现计算误差。其他情况可忽略该参数。

##### breakIfNoCoverage {#testing-coverage-parameters-breakIfNoCoverage}

* type: `Boolean`
* required: `false`

没有找到覆盖率报告文件时，是否抛出错误终止流程。

#### 输出结果 {#testing-coverage-output}

```json
{
  // 代码行覆盖率，例如 100，计算出错时值为 NA
  "lines": 100,
  // 代码增量行覆盖率，例如 100，计算出错时值为 NA
  "diff_pct": 100
}
```

#### 配置样例 {#testing-coverage-configuration-examples}

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: coverage
          type: testing:coverage
          options:
            breakIfNoCoverage: false
          exports:
            lines: LINES
        - name: result
          script: echo $LINES
```

## artifact

### remove-tag {#artifact-remove-tag}

`artifact:remove-tag`

\==删除 CNB 制品标签==，目前仅删除支持 CNB Docker 和 Helm 标签。需要有仓库写权限。

* [适用事件](./#artifact-remove-tag-applicable-events)
* [参数](./#artifact-remove-tag-parameters)
* [配置样例](./#artifact-remove-tag-configuration-examples)

#### 适用事件 {#artifact-remove-tag-applicable-events}

* `push`
* `commit.add`
* `tag_push`
* `tag_deploy`
* `pull_request.merged`
* `api_trigger`
* `web_trigger`
* `crontab`
* `branch.create`

#### 参数 {#artifact-remove-tag-parameters}

* [name](./#artifact-remove-tag-parameters-name)
* [tags](./#artifact-remove-tag-parameters-tags)
* [type](./#artifact-remove-tag-parameters-type)

##### name {#artifact-remove-tag-parameters-name}

* type: `String`
* required: `true`

制品包名

##### tags {#artifact-remove-tag-parameters-tags}

* type: `Array<string>`
* required: `true`

##### type {#artifact-remove-tag-parameters-type}

* type: `String`
* required: `false`
* default: `docker`

制品类型，目前仅支持 Hocker 和 Helm

#### 配置样例 {#artifact-remove-tag-configuration-examples}

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: remove tag
          type: artifact:remove-tag
          options:
            # 包名
            # 包名示例1，仓库同名制品：reponame
            # 包名示例2，仓库非同名制品：reponame/name
            name: reponame/name
            tags:
              - tag1
              - tag2
            type: docker
```

## tapd

在代码提交时，您可以在**提交信息**或**PR 描述**中添加 TAPD 源码关键字，云原生构建系统将自动识别并关联 Commits、PR 和 TAPD 工作项。

在代码推送、 PR 和 Tag 相关流水线中，可以通过以下任务更新 TAPD 关联项的信息。

**前提条件**

* 需在根组织中启用 TAPD 功能。
* 流水线触发者需绑定 TAPD 账号。

**TAPD 关联项筛选规则**

流水线将根据以下规则筛选关联的 TAPD 工作项：

**1. 当传入 `fromFile` 或 `fromText` 参数时：**

从传入的文本文件或文本中解析出 commit IDs，并查询其关联的 TAPD 工作项。

`fromFile` 优先级高于 `fromText`。

**2. 当未传入 `fromFile` 或 `fromText` 参数时：**

* **PR 相关事件：**

  查询该 PR 的 commits 以及 PR 描述中关联的 TAPD 工作项。

* **`commit.add` 事件：**

  查询新增 commits 关联的 TAPD 工作项。

* **非新建分支的 `push` 事件：**

  从本次推送的所有 commits 的提交日志中获取关联的 TAPD 工作项。

* **其他情况：**

  查询最新 commit 所关联的 TAPD 工作项。

通过以上规则，确保代码变更与 TAPD 工作项的系统化、高效关联。

**TAPD 关联项类型**

TAPD 工作项 `源码关键字` 中的类型即为工作项类型，如：story、task、bug。

> 需要注意的是，TAPD 任务的源码关键字可能为 story 或 task，请注意区分。

### status-update {#tapd-status-update}

`tapd:status-update`

\==更新 tapd 关联项（story、task 或 bug）状态==

* [适用事件](./#tapd-status-update-applicable-events)
* [参数](./#tapd-status-update-parameters)
* [配置样例](./#tapd-status-update-configuration-examples)

#### 适用事件 {#tapd-status-update-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#tapd-status-update-parameters}

* [status](./#tapd-status-update-parameters-status)
* [when](./#tapd-status-update-parameters-when)
* [type](./#tapd-status-update-parameters-type)
* [fromText](./#tapd-status-update-parameters-from-text)
* [fromFile](./#tapd-status-update-parameters-from-file)

##### status {#tapd-status-update-parameters-status}

* type: `String`
* required: `true`

目标状态。

##### when {#tapd-status-update-parameters-when}

* type: `String` | `Array<String>`
* required: `false`

更新指定状态的工作项，为空时不做过滤。

##### type {#tapd-status-update-parameters-type}

* `Enum<String>`: story | task | story
* required: `false`

更新指定类型的工作项，为空时不做过滤。

##### fromText {#tapd-status-update-parameters-from-text}

* type: `String`
* required: `false`

从文本中解析出 commit id，查询其关联的工作项。

##### fromFile {#tapd-status-update-parameters-from-file}

* type: `String`
* required: `false`

从文本文件中解析出 commit id，查询其关联的工作项。

#### 配置样例 {#tapd-status-update-configuration-examples}

1. 对所有 TAPD 关联项进行状态扭转

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: update tapd status
          type: tapd:status-update
          options:
            status: 进行中
```

2. 对符合条件的 TAPD 关联项进行状态扭转

```yaml title=".cnb.yml"
main:
  pull_request.merged:
    - stages:
        - name: update tapd status
          type: tapd:status-update
          options:
            status: 已完成
            when:
              - 进行中
            type: story
```

3. 从 `fromText` 中解析 commit id，查询 TAPD 关联项进行状态扭转

```yaml title=".cnb.yml"
$:
  tag_push:
    - stages:
        - name: 生成 changelog
          image: cnbcool/changelog
          settings:
            dryRun: true
            linkReferences: false
          exports:
            latestChangeLog: RELEASE_NOTES
        - name: tapd
          type: tapd:status-update
          options:
            status: 已发布
            type: story
            fromText: $RELEASE_NOTES
```

### comment {#tapd-comment}

`tapd:comment`

\==提交 tapd 关联项（story、task 或 bug）评论==

* [适用事件](./#tapd-comment-applicable-events)
* [参数](./#tapd-comment-parameters)
* [配置样例](./#tapd-comment-configuration-examples)

#### 适用事件 {#tapd-comment-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 参数 {#tapd-comment-parameters}

* [comment](./#tapd-comment-parameters-comment)
* [when](./#tapd-comment-parameters-when)
* [type](./#tapd-comment-parameters-type)
* [fromText](./#tapd-status-update-parameters-from-text)
* [fromFile](./#tapd-status-update-parameters-from-file)

##### comment {#tapd-comment-parameters-comment}

* type: `String`
* required: `true`

评论内容。

##### when {#tapd-comment-parameters-when}

* type: `String` | `Array<String>`
* required: `false`

对符合指定状态的工作项进行评论，为空时不做过滤。

##### type {#tapd-comment-parameters-type}

* `Enum<String>`: story | task | story
* required: `false`

对符合指定类型的工作项进行评论，为空时不做过滤。

##### fromText {#tapd-comment-parameters-from-text}

* type: `String`
* required: `false`

从文本中解析出 commit id（最多50个），查询其关联的工作项。

##### fromFile {#tapd-comment-parameters-from-file}

* type: `String`
* required: `false`

从文本文件中解析出 commit id，查询其关联的工作项。

#### 配置样例 {#tapd-comment-configuration-examples}

1. 对所有 TAPD 关联项进行评论：

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: add tapd comment
          type: tapd:comment
          options:
            comment: 开始开发
```

2. 对符合条件的 TAPD 关联项进行评论：

```yaml title=".cnb.yml"
main:
  pull_request.merged:
    - stages:
        - name: add tapd comment
          type: tapd:comment
          options:
            comment: 已合并
            when:
              - 进行中
            type: story
```

3. 从 `fromText` 中解析 commit id，查询 TAPD 关联项进行评论

```yaml title=".cnb.yml"
$:
  tag_push:
    - stages:
        - name: 生成 changelog
          image: cnbcool/changelog
          settings:
            dryRun: true
            linkReferences: false
          exports:
            latestChangeLog: RELEASE_NOTES
        - name: tapd
          type: tapd:comment
          options:
            comment: 已发布
            type: story
            fromText: $RELEASE_NOTES
```

## knowledge

### update {#knowledge-update}

`knowledge:update`

\==更新知识库== ，用于把 Issue、仓库文档等构建进入知识库。

* [适用事件](./#knowledge-update-applicable-events)
* [参数](./#knowledge-update-parameters)
* [配置样例](./#knowledge-update-configuration-examples)

#### 适用事件 {#knowledge-update-applicable-events}

[所有事件](../trigger-rule.md#trigger-event)

#### 工作机制 {#knowledge-update-how-it-works}

拉取仓库的 Issue、仓库文档 -> 切片 -> 向量化 -> 进入知识库

#### 参数 {#knowledge-update-parameters}

* [include](./#knowledge-update-parameters-include)
* [exclude](./#knowledge-update-parameters-exclude)
* [chunkSize](./#knowledge-update-parameters-chunkSize)
* [chunkOverlap](./#knowledge-update-parameters-chunkOverlap)
* [embeddingModel](./#knowledge-update-parameters-embeddingModel)
* [issueSyncEnabled](./#knowledge-update-parameters-issueSyncEnabled)
* [issueState](./#knowledge-update-parameters-issueState)
* [issueLabels](./#knowledge-update-parameters-issueLabels)
* [issueExcludeLabels](./#knowledge-update-parameters-issueExcludeLabels)
* [forceRebuild](./#knowledge-update-parameters-forceRebuild)
* [ignoreProcessFailures](./#knowledge-update-parameters-ignoreProcessFailures)

##### include {#knowledge-update-parameters-include}

* type: `String` | `Array<String>`
* required: `false`
* default: `**/**.md`

指定需要包含的文件，使用 `Glob` 模式匹配，默认为 `**/**.md`（包含所有 Markdown 文件），支持数组或逗号分隔。当前支持的文件类型有：.md、.mdx、.docx、.txt、.pdf。

##### exclude {#knowledge-update-parameters-exclude}

* type: `String` | `Array<String>`
* required: `false`

指定需要排除的文件，使用 `Glob` 模式匹配，默认不排除任何文件，支持数组或逗号分隔。

##### chunkSize {#knowledge-update-parameters-chunkSize}

* type: `Number`
* required: `false`
* default: `1500`

指定文本分块大小。

##### chunkOverlap {#knowledge-update-parameters-chunkOverlap}

* type: `Number`
* required: `false`
* default: `0`

指定相邻两个分块之间的重叠 token 数量。

##### embeddingModel {#knowledge-update-parameters-embeddingModel}

* type: `String`
* required: `false`
* default: `hunyuan`

嵌入模型，目前仅支持 `hunyuan`。

##### issueSyncEnabled {#knowledge-update-parameters-issueSyncEnabled}

* type: `Boolean`
* required: `false`
* default: `true`

是否启用 Issue 同步功能。启用后会自动拉取仓库的 Issue 数据并加入知识库。

##### issueState {#knowledge-update-parameters-issueState}

* type: `String`
* required: `false`

仅同步指定状态的 Issue，默认包含全部 Issue，可选值为 `open` | `closed`。

##### issueLabels {#knowledge-update-parameters-issueLabels}

* type: `String` | `Array<String>`
* required: `false`

仅同步指定标签的 Issue，默认包含全部 Issue，支持数组或逗号分隔。

##### issueExcludeLabels {#knowledge-update-parameters-issueExcludeLabels}

* type: `String` | `Array<String>`
* required: `false`

排除带有指定标签的 Issue，默认不排除任何 Issue，支持数组或逗号分隔。当与 `issueLabels` 存在交集时，exclude 优先。

##### forceRebuild {#knowledge-update-parameters-forceRebuild}

* type: `Boolean`
* required: `false`
* default: `false`

是否删除知识库并重新构建。当设置为 `true` 时，删除并重新创建知识库。

##### ignoreProcessFailures {#knowledge-update-parameters-ignoreProcessFailures}

* type: `Boolean`
* required: `false`
* default: `false`

是否忽略文档处理失败。当设置为 `true` 时，即使有文件处理失败也会更新知识库。

#### 配置样例 {#knowledge-update-configuration-examples}

##### 基本使用 {#knowledge-update-configuration-examples-basic-usage}

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: build knowledge base
          type: knowledge:update
          options:
            include: "**/**.md"
```

## npc

### go {#npc-go}

`npc:go`

在 Issue 或 PR 评论中 @NPC 角色时，在指定的 Docker 镜像中执行任务。
可以在镜像中安装 NPC 运行时需要 CLI 工具和 Skills ，例如使用 [CNB Skill](https://cnb.cool/cnb/skills/cnb-skill)。更多 NPC 相关配置，请查阅 [NPC 事件](../npc.md)。

* [适用事件](./#npc-go-applicable-events)
* [参数](./#npc-go-parameters)
* [配置样例](./#npc-go-configuration-examples)

#### 适用事件 {#npc-go-applicable-events}

`issue.comment@npc`、`pull_request.comment@npc`、`api_trigger`、`crontab`

#### 参数 {#npc-go-parameters}

:::warning
以下参数仅在 `api_trigger` 、`crontab` 事件中生效，其他事件无需配置。
:::

* [role](./#npc-go-parameters-role)
* [systemPrompt](./#npc-go-parameters-systemPrompt)
* [userPrompt](./#npc-go-parameters-userPrompt)

##### role {#npc-go-parameters-role}

* type: `String`
* required: `true`

NPC 角色名称，需要在 `.cnb/settings.yml` 文件中的 NPC 的 roles 字段中定义，可以参考 [UI 定制](../repo/settings.md)。

##### systemPrompt {#npc-go-parameters-systemPrompt}

* type: `String`
* required: `true`

NPC 系统提示词。

##### userPrompt {#npc-go-parameters-userPrompt}

* type: `String`
* required: `true`

NPC 用户输入, 主要用于用户向 NPC 描述任务。

#### 配置样例 {#npc-go-configuration-examples}

```yaml title=".cnb.yml"
$:
  issue.comment@npc:
    - docker:
        # 指定镜像，内含 NPC 运行时需要的 CLI 工具和 Skills
        image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest
      stages:
        - name: npc go
          type: npc:go

# 构建并推送 Docker 镜像
main:
  push:
    - services:
        - docker
      stages:
        - name: Docker build
          script: docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
        - name: Docker push
          script: docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
```

在 Dockerfile 中，需要安装 NPC 运行时需要的 Skills 和 CLI 工具。例如，下面的示例安装了 `cnb-skill` 和 `cnb-cli` 工具。

```Dockerfile title="Dockerfile"
FROM node:22-bookworm-slim

RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates git git-lfs curl jq ripgrep \
    && rm -rf /var/lib/apt/lists/* \
    && git lfs install \
    && npm install -g @cnbcool/cnb-cli skills \
    && npx skills add https://cnb.cool/cnb/skills/cnb-skill.git -g -y
```

Skills 支持自动加载以下目录：`~/.agents/skills`、`~/.codebuddy/skills` 以及对应的项目目录：`.agents/skills`、`.codebuddy/skills`。

项目级 Skills 优先级高于用户级，同名 Skill 项目级会覆盖用户级。

NPC 角色的 prompt 定义在 `.cnb/settings.yml` 文件中，请查阅 [NPC 事件](../npc.md)。
