关于 CodeQL 工作区
CodeQL 工作区通常用于开发一组相互依赖的库包和查询包。使用 CodeQL 工作区时,工作区中的所有 CodeQL 包在运行解析查询的 CodeQL 命令时,彼此之间都可以作为 源码依赖 使用。这使得开发、维护和发布多个相关的 CodeQL 包更加便捷。有关 CodeQL 包的更多信息,请参阅 使用 CodeQL 包自定义分析。
工作区通常存放在单个 Git 仓库中,以便相关的包可以一起开发和发布。
源码依赖
在 CodeQL 工作区中,工作区包含的所有包都被视为彼此的 源码依赖。这意味着它们直接从本地文件系统解析,而不是从 CodeQL 包缓存中解析。
因为工作区中的包从源码解析
- 一个包中的本地更改会立即对工作区中的其他包可见。
- 在工作区中找到的依赖会覆盖包缓存中的版本。
- 对于工作区依赖,
qlpack.yml文件中的版本约束会被忽略,因为版本由工作区内容决定。
当同时开发多个相关包时,此行为尤其有用。例如
- 某个依赖尚未发布,仅存在于本地。
- 您正在对多个包进行协调修改,并需要它们在测试期间相互解析。
在工作区之外,依赖会从包缓存中解析,并且必须匹配 qlpack.yml 中定义的版本约束。而在工作区内部,解析会优先使用本地源码内容。
CodeQL 工作区与查询解析
工作区依赖模型会影响包的安装和发布方式。
- 在安装期间,工作区中找到的依赖不会下载到包缓存中,也不会写入
codeql-pack.lock.yml文件。 - 在发布期间,工作区提供的依赖会使用其本地源码内容进行打包,而不是使用包缓存中的版本。
例如,在工作区内的某个包目录中运行 codeql pack install 时,会使用工作区中找到的任何依赖,而不是下载它们到包缓存或记录在 codeql-pack.lock.yml 文件中。参见 创建和使用 CodeQL 包。
示例
CodeQL 工作区由名为 codeql-workspace.yml 的 YAML 文件定义。请参考下面的 codeql-workspace.yml 文件示例
provide:
- "**/qlpack.yml"
以及工作区中的以下 CodeQL 库包 qlpack.yml 文件
name: my-company/my-library
library: true
version: 1.0.0
以及工作区中的以下 CodeQL 查询包 qlpack.yml 文件
name: my-company/my-queries
version: 1.0.0
dependencies:
my-company/my-library: "*"
codeql/cpp-all: ~0.2.0
请注意,CodeQL 查询包 my-company/my-queries 的 dependencies 区块将库包的版本指定为 "*"。由于该库包已在 codeql-workspace.yml 中声明为源码依赖,库包的内容始终从工作区内部解析。在这种情况下,您定义的任何版本约束都会被忽略。对源码依赖使用 "*" 可以明确表示版本由工作区继承。
当您在查询包目录下执行 codeql pack install 时,会将合适的 codeql/cpp-all 版本下载到本地包缓存中。同时,会生成一个包含已解析的 codeql/cpp-all 版本的 codeql-pack.lock.yml 文件。由于 my-company/my-library 是通过源码依赖解析的,锁文件中不会出现它的条目。codeql-pack.lock.yml 文件大致如下所示
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 包时使用的容器注册表。参见 发布和使用 CodeQL 包。
每个 provide 或 ignore 条目必须映射到相应的 qlpack.yml 文件所在位置。所有 glob 模式均相对于包含工作区文件的目录定义。有关此文件中接受的模式列表,请参阅 @actions/glob。
例如,下面的 codeql-workspace.yml 文件定义了一个工作区,其中包含 codeql-packs 目录下递归发现的所有 CodeQL 包,但排除了 experimental 目录中的包。registries 区块指定 codeql/* 包应从 https://ghcr.io/v2/ 下载,该地址是 GitHub 的默认容器注册表。其余所有包则应从并发布到 GHE_HOSTNAME 所指的注册表。
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 来列出工作区中包含的所有包。
在 qlpack.yml 文件中使用 ${workspace} 作为版本范围
工作区中的 CodeQL 包可以使用特殊的 ${workspace}、~${workspace} 和 ^${workspace} 版本范围占位符。这些占位符表示该包依赖于工作区中当前所在的指定包的版本。此占位符通常用于库包内部的依赖,以确保在发布时,它们的 qlpack.yml 中的依赖版本能够反映当时工作区的状态。
示例
请参考同一工作区中的以下两个库包示例
name: my-company/my-library
library: true
version: 1.2.3
dependencies:
my-company/my-library2: ${workspace}
name: my-company/my-library2
library: true
version: 4.5.6
当 my-company/my-library 发布到 GitHub 容器注册表时,已发布的 qlpack.yml 文件中 my-company/my-library2 依赖的版本将被写为 4.5.6。
同理,如果源包中将依赖写为 my-company/my-library2: ^${workspace},在发布后,已发布的 qlpack.yml 文件中该依赖的版本将写为 ^4.5.6,这表明 >= 4.5.6 且 < 5.0.0 的所有版本都与该库包兼容。
如果源包中将依赖写为 my-company/my-library2: ~${workspace},在发布后,已发布的 qlpack.yml 文件中该依赖的版本将写为 ~4.5.6,这表明 >= 4.5.6 且 < 4.6.0 的所有版本都与该库包兼容。