跳至主要内容

关于 CodeQL 工作区

CodeQL 工作区允许您开发和维护一组相互依赖的 CodeQL 包。

谁可以使用此功能?

CodeQL 可用于以下代码库类型

关于 CodeQL 工作区

当您想要将多个 CodeQL 包组合在一起时,可以使用 CodeQL 工作区。CodeQL 工作区的典型用例是开发一组相互依赖的 CodeQL 库和查询包。有关 CodeQL 包的更多信息,请参阅“使用 CodeQL 包自定义分析”。

CodeQL 工作区的主要优势在于,它使您能够更轻松地开发和维护多个 CodeQL 包。当您使用 CodeQL 工作区时,运行解析查询的 CodeQL 命令时,工作区中的所有 CodeQL 包都可用作彼此的源依赖项。这使得开发、维护和发布多个相关的 CodeQL 包变得更加容易。

在大多数情况下,您应该将 CodeQL 工作区和其中包含的 CodeQL 包存储在一个 Git 代码库中。这使得共享您的 CodeQL 开发环境变得更加容易。

codeql-workspace.yml 文件

CodeQL 工作区由一个 codeql-workspace.yml YAML 文件定义。此文件包含一个 provide 块,以及可选的 ignoreregistries 块。

  • provide 块包含一个 glob 模式列表,用于定义工作区中可用的 CodeQL 包。

  • ignore 块包含一个 glob 模式列表,用于定义工作区中不可用的 CodeQL 包。

  • registries 块包含一个 GHES URL 和包模式列表,用于控制用于发布 CodeQL 包的容器注册表。有关更多信息,请参阅“发布和使用 CodeQL 包”。

provideignore 部分中的每个条目都必须映射到 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-workspace.yml 文件是否包含您期望的 CodeQL 包,请在与您的工作区相同的目录中运行 codeql pack ls 命令。该命令的结果是工作区中所有 CodeQL 包的列表。

源依赖项

源依赖项是 CodeQL 包,它们从本地文件系统(位于 CodeQL 包缓存之外)解析。这些依赖项可以位于同一个 CodeQL 工作区中,也可以使用--additional-packs参数作为路径选项指定。在本地编译和运行查询时,源依赖项会覆盖 CodeQL 包缓存中找到的任何依赖项以及qlpack.yml中定义的版本约束。工作区中对 CodeQL 包的所有引用都将解析为源依赖项。

这在以下情况下特别有用:

  • 您正在运行的查询包的其中一个依赖项尚未发布。从源解析是引用该包的唯一方法。

  • 您正在同时对多个包进行更改,并希望一起测试它们。从源解析可确保您正在使用包含更改的包版本。

CodeQL 工作区和查询解析

当您运行任何解析查询或包的 CodeQL 命令时,工作区中的所有 CodeQL 包都可作为彼此的源依赖项。例如,当您在工作区中的包目录中运行codeql pack install时,任何可以在工作区中找到的依赖项都将被使用,而不是将该依赖项下载到包缓存并将其添加到codeql-pack.lock.yml文件中。有关更多信息,请参阅“创建和使用 CodeQL 包”。

类似地,当您使用codeql pack publish将 CodeQL 查询包发布到 GitHub 容器注册表时,该命令将始终使用工作区中的依赖项,而不是使用本地包缓存中找到的依赖项。

这确保了您对依赖项中的查询库所做的任何本地更改都会自动反映在您从该工作区发布的任何查询包中。

示例

考虑以下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-queriesdependencies块将"*"指定为库包的版本。由于库包已在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 容器注册表。

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文件中my-company/my-library2依赖项的版本将写为^4.5.6,表示版本>= 4.5.6< 5.0.0都与此库包兼容。

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