# 关于 CodeQL 工作区

CodeQL 工作区允许你开发和维护多个相关的 CodeQL 包，直接从源代码解析它们之间的依赖关系。

## 关于 CodeQL 工作区

CodeQL 工作区通常用于开发一组相互依赖的库和查询包。 如果使用 CodeQL 工作区，运行解析查询的 CodeQL 命令时，工作区中的所有 CodeQL 包都可用作彼此的\_源依赖项\_。 这使得可更轻松地开发、维护和发布多个相关的 CodeQL 包。 有关 CodeQL 包的详细信息，请参阅 [使用 CodeQL 包自定义分析](/zh/code-security/codeql-cli/getting-started-with-the-codeql-cli/customizing-analysis-with-codeql-packs)。

工作区通常存储在单个 Git 存储库中，以便可以一起开发和发布相关包。

## 源依赖项

在 CodeQL 工作区中，工作区中包含的所有包都被视为彼此的**源依赖项**。 这意味着它们直接从本地文件系统解析，而不是从 CodeQL 包缓存解析。

由于工作区包从源解析：

* 在一个组件中进行的本地变更会立即在工作区的其他组件中可见。
* 在工作区中发现的依赖项替代包缓存中的版本。
* 由于版本是由工作区内容决定的，因此文件 `qlpack.yml` 中的版本约束被忽略。

同时开发多个相关包时，此行为特别有用。 例如：

* 依赖项尚未发布，并且仅在本地存在。
* 你正在跨多个包进行协调更改，并需要它们在测试期间相互解析。

在工作区外部，依赖项将从包缓存解析，并且必须与在中 `qlpack.yml`定义的版本约束匹配。 在工作区中，解析会优先考虑本地源内容。

## CodeQL 工作区和查询解析

工作区依赖项模型会影响包的安装和发布方式。

* 在安装过程中，工作区中找到的依赖项不会下载到包缓存中，也不会写入 `codeql-pack.lock.yml` 文件。
* 发布期间，工作区提供的依赖项使用其本地源内容（而不是包缓存中的版本）捆绑在一起。

例如，在工作区的包目录中运行 `codeql pack install` 将使用工作区中找到的所有依赖项，而不是将它们下载到包缓存中或记录到 `codeql-pack.lock.yml` 文件中。 请参阅“[创建并使用 CodeQL 包](/zh/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#adding-and-installing-dependencies)”。

### Example

CodeQL 工作区由名为 `codeql-workspace.yml` 的 YAML 文件定义。 请考虑以下 `codeql-workspace.yml` 文件：

```yaml
provide:
  - "**/qlpack.yml"
```

工作区中的以下 CodeQL 库包 `qlpack.yml` 文件：

```yaml
name: my-company/my-library
library: true
version: 1.0.0
```

工作区中的以下 CodeQL 查询包 `qlpack.yml` 文件：

```yaml
name: my-company/my-queries
version: 1.0.0
dependencies:
  my-company/my-library: "*"
  codeql/cpp-all: ~0.2.0
```

请注意，CodeQL 查询包 `dependencies` 的 `my-company/my-queries` 块将 `"*"` 指定为库包的版本。 由于库包已在 `codeql-workspace.yml` 中定义为源依赖项，因此库包的内容始终从工作区内部解析。 在这种情况下，将忽略你定义的任何版本约束。 使用 `"*"` 源依赖项可以明确说明版本是从工作区继承的。

从查询包目录执行 `codeql pack install` 时，会将 `codeql/cpp-all` 的相应版本下载到本地包缓存中。 此外，还会创建一个 `codeql-pack.lock.yml` 文件，其中包含 `codeql/cpp-all` 的解析版本。 锁定文件不包含 `my-company/my-library` 的条目，因为它是从源依赖项解析的。
`codeql-pack.lock.yml` 文件将如下所示：

```yaml
dependencies:
  codeql/cpp-all:
    version: 0.2.2
```

从查询包目录执行 `codeql pack publish` 时，包缓存中的 `codeql/cpp-all` 依赖项和工作区中的 `my-company/my-library` 与 `my-company/my-queries` 捆绑在一起，并发布到 GitHub 容器注册表。

##

```
          `codeql-workspace.yml`文件示例
```

CodeQL 工作区由名为 `codeql-workspace.yml` 的 YAML 文件定义。 此文件包含 `provide` 块，还根据需要包含 `ignore` 和 `registries` 块。

* ```
          `provide` 块包含一个 glob 模式列表，这些模式定义了工作区中可用的 CodeQL 包。
  ```

* ```
          `ignore` 块包含一个 glob 模式列表，这些模式定义了工作区中不可用的 CodeQL 包。
  ```

* ```
          `registries` 块包含一个 GHES URL 和包模式的列表，它们控制哪个容器注册表用于发布 CodeQL 包。 请参阅“[AUTOTITLE](/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/publishing-and-using-codeql-packs#working-with-codeql-packs-on-ghes)”。

          `provide` 或 `ignore` 部分中的每个条目都必须映射到 `qlpack.yml` 文件的位置。 所有 glob 模式均相对于包含工作区文件的目录进行定义。 有关此文件中接受的模式列表，请参阅 [@actions/glob](https://github.com/actions/toolkit/tree/main/packages/glob#patterns)。
  ```

例如，以下 `codeql-workspace.yml` 文件定义一个工作区，其中包含 `codeql-packs` 目录中以递归方式找到的所有 CodeQL 包，但 `experimental` 目录中的包除外。
`registries` 块指定应从 `codeql/\*`（即 GitHub 的默认容器注册表）下载 `https://ghcr.io/v2/` 包。 应从位于 `GHE_HOSTNAME` 的注册表下载所有其他包，也应将这些包发布到此处。

```yaml
provide:
  - "*/codeql-packs/**/qlpack.yml"
ignore:
  - "*/codeql-packs/**/experimental/**/qlpack.yml"

registries:
 - packages: 'codeql/*'
   url: https://ghcr.io/v2/

 - packages: '*'
   url: https://containers.GHE_HOSTNAME/v2/
```

可以通过在工作区目录中运行 `codeql pack ls` 来列出工作区中包含的包。

## 在 `${workspace}` 文件中使用 `qlpack.yml` 作为版本范围

工作区中的 CodeQL 包可以使用特殊 `${workspace}`、`~${workspace}` 和 `^${workspace}` 版本范围占位符。 这些占位符指示此包取决于当前在工作区中的指定包的版本。 此占位符通常用于库包内的依赖项，以确保发布这些库包时，其 `qlpack.yml` 文件中的依赖项反映发布时工作区的状态。

### Example

请考虑同一工作区中的以下两个库包：

```yaml
name: my-company/my-library
library: true
version: 1.2.3
dependencies:
  my-company/my-library2: ${workspace}
```

```yaml
name: my-company/my-library2
library: true
version: 4.5.6
```

当 `my-company/my-library` 发布到 GitHub 容器注册表时，已发布 `my-company/my-library2` 文件中 `qlpack.yml` 依赖项的版本将写入为 `4.5.6`。

同样，如果依赖项是位于源包中的 `my-company/my-library2: ^${workspace}`，然后发布该包，则已发布 `my-company/my-library2` 文件中的 `qlpack.yml` 依赖项版本将写入为 `^4.5.6`，指示版本 `>= 4.5.6` 和 `< 5.0.0` 都与此库包兼容。

如果依赖项是位于源包中的 `my-company/my-library2: ~${workspace}`，然后发布该包，则已发布 `my-company/my-library2` 文件中的 `qlpack.yml` 依赖项版本将写入为 `~4.5.6`，指示版本 `>= 4.5.6` 和 `< 4.6.0` 都与此库包兼容。