Skip to main content
我们经常发布文档更新,此页面的翻译可能仍在进行中。 有关最新信息,请访问英语文档

对 CodeQL 工作流进行故障排除

如果 code scanning 设置出现问题,可以使用以下用于解决问题的提示来进行故障排除。

Code scanning 可用于 GitHub Enterprise Server 中的组织拥有的存储库。 此功能需要 GitHub Advanced Security 的许可证。 有关详细信息,请参阅“关于 GitHub 高级安全性”。

注意:本文介绍了此版 GitHub Enterprise Server 的初始发行版中包含的 CodeQL 操作版本和相关 CodeQL CLI 捆绑包中可用的功能。 如果企业使用较新版本的 CodeQL 操作,请参阅本文的 GitHub Enterprise Cloud 版本,了解有关最新功能的信息。 有关使用最新版本的信息,请参阅“为设备配置代码扫描”。

生成详细的调试日志

要生成更详细的日志输出,您可以启用步骤调试日志记录。 有关详细信息,请参阅“启用调试日志记录”。

创建 CodeQL 调试工件

可以获取生成工件来帮助你调试 CodeQL。 调试工件作为名为 debug-artifacts 的工件上传到工作流运行。 数据包含 CodeQL 日志、 CodeQL 数据库以及工作流程生成的任何 SARIF 文件。

这些生成工件将帮助你调试 CodeQL code scanning 的问题。 如果您联系 GitHub 支持人员,他们可能会要求您提供此数据。

创建 CodeQL 调试生成工件

可以通过在工作流中使用标志来创建 CodeQL 调试生成工件。 为此,需要修改 CodeQL 分析工作流程 文件的 init 步骤并设置 debug: true

- name: Initialize CodeQL
  uses: github/codeql-action/init@v2
  with:
    debug: true

编译语言的自动构建失败

如果项目中编译语言的代码自动构建失败,请尝试以下疑难解答步骤。

  • 从 code scanning 工作流中删除 autobuild 步骤,并添加特定构建步骤。 有关编辑工作流的详细信息,请参阅“自定义代码扫描”。 有关替换 autobuild 步骤的详细信息,请参阅“为编译的语言配置 CodeQL 工作流”。

  • 如果您的工作流程未明确指定要分析的语言,则 CodeQL 会隐式检测代码库中支持的语言。 在此配置中,对于编译语言 C/C++、C#、 和 Java,CodeQL 只分析源文件最多的语言。 编辑工作流并添加一个矩阵,以指定要分析的语言。 默认的 CodeQL 分析工作流将使用此类矩阵。

    以下工作流程摘录显示了如何在作业策略中使用矩阵来指定语言,然后在“初始化 CodeQL”步骤中引用每种语言:

    jobs:
      analyze:
        permissions:
          security-events: write
          actions: read
        ...
        strategy:
          fail-fast: false
          matrix:
            language: ['csharp', 'cpp', 'javascript']
    
        steps:
        ...
          - name: Initialize CodeQL
            uses: github/codeql-action/init@v2
            with:
              languages: ${{ matrix.language }}
    

    有关编辑工作流的详细信息,请参阅“自定义代码扫描”。

构建过程中找不到代码

如果工作流失败并出现错误 No source code was seen during the buildThe process '/opt/hostedtoolcache/CodeQL/0.0.0-20200630/x64/codeql/codeql' failed with exit code 32,则表示 CodeQL 无法监视代码。 有几个原因可以解释这种失败:

  1. 存储库可能不包含以 CodeQL 支持的语言编写的源代码。 检查受支持的语言列表,如果是这种情况,请删除 CodeQL 工作流。 有关详细信息,请参阅“关于使用 CodeQL 进行代码扫描”。

  2. 自动语言检测发现了受支持的语言,但仓库中没有该语言的可分析代码。 一个典型的例子是,我们的语言检测服务发现了一个与特定的编程语言相关的文件,例如 .h.gyp 文件,但存储库中没有相应的可执行代码。 要解决此问题,可通过更新 language 矩阵中的语言列表来手动定义要分析的语言。 例如,以下配置将仅分析 Go 和 JavaScript。

    strategy:
      fail-fast: false
      matrix:
        # Override automatic language detection by changing the list below.
        # Supported options are listed in a comment in the default workflow.
        language: ['go', 'javascript']
    

    有关详细信息,请参阅上述“编译语言的自动生成失败”中的工作流提取。

  3. code scanning 工作流正在分析一种编译语言(C、C++、C#、 或 Java),但代码尚未编译。 默认情况下,CodeQL 分析工作流包含 autobuild 步骤,但是,此步骤是一个尽力而为的过程,可能无法成功构建你的代码,具体取决于你的特定构建环境。 如果你删除了 autobuild 步骤但没有手动添加构建步骤,编译也可能会失败。 有关指定生成步骤的详细信息,请参阅“为编译的语言配置 CodeQL 工作流”。

  4. 工作流正在分析一种编译语言(C、C++、C#、 或 Java),但构建的某些部分会缓存以提高性能(最有可能发生在 Gradle 或 Bazel 等构建系统中)。 因为 CodeQL 观察编译器的活动以了解仓库中的数据流,因此 CodeQL 需要进行完整的构建才能执行分析。

  5. 工作流正在分析一种编译语言(C、C++、C#、 或 Java),但编译不会在工作流中的 initanalyze 步骤之间进行。 CodeQL 需要这两个步骤之间发生构建以观察编译器的活动并执行分析。

  6. 编译代码(使用 C、C++、C#、 或 Java)已成功编译,但 CodeQL 未能检测到编译器调用。 最常见原因是:

    • 在独立于 CodeQL 的容器中运行构建过程。 有关详细信息,请参阅“在容器中运行 CodeQL 代码扫描”。
    • 使用 GitHub Actions 外部的分布式构建系统,使用守护进程构建。
    • CodeQL 不知道您使用的特定编译器。

    对于 .NET Framework 项目以及使用 dotnet buildmsbuild 的 C# 项目,应在构建代码时在工作流的 run 步骤中指定 /p:UseSharedCompilation=false

    例如,以下 C# 的配置将在第一个构建步骤中传递标志。

    - run: |
        dotnet build /p:UseSharedCompilation=false
    

    如果您在特定编译器或配置方面遇到其他问题,请联系 你的站点管理员。

有关指定生成步骤的详细信息,请参阅“为编译的语言配置 CodeQL 工作流”。

扫描的代码行数低于预期

对于 C/C++、C#、Go 和 Java 等编译语言,CodeQL 仅扫描在分析过程中生成的文件。 因此,如果某些源代码未正确编译,则扫描的代码行数将低于预期。 这可能是多种原因引起的:

  1. CodeQL autobuild 功能使用启发式方法在存储库中生成代码。 但是,有时这种方法会导致对存储库的分析不完整。 例如,当单个存储库中存在多个 build.sh 命令时,分析可能不完整,因为 autobuild 步骤将仅执行其中一个命令,因此可能无法编译某些源文件。
  2. 某些编译器无法使用 CodeQL ,因此在分析代码时可能会导致问题。 例如,Lombok 项目使用非公共编译器 API 来修改编译器行为。 这些编译器修改中使用的假设不适用于 CodeQL 的 Java 提取器,因此无法分析代码。

如果 CodeQL 分析扫描的代码行数少于预期,则可以尝试使用多种方法来确保编译了所有必需的源文件。

替换 autobuild 步骤

autobuild 步骤替换为将在生产中使用的相同生成命令。 这可以确保 CodeQL 确切地知道如何编译要扫描的所有源文件。 有关详细信息,请参阅“为编译的语言配置 CodeQL 工作流”。

检查 CodeQL 数据库中源文件的副本

您可以通过检查 CodeQL 数据库中包含的源代码副本来了解为什么没有分析某些源文件。 要从 Actions 工作流中获取数据库,请修改 CodeQL 工作流文件的 init 步骤,并设置 debug: true

- name: Initialize CodeQL
  uses: github/codeql-action/init@v2
  with:
    debug: true

这会将数据库作为操作构件上传,您可以将其下载到本地计算机。 有关详细信息,请参阅“将工作流程数据存储为构件”。

该构件将包含由名为 src.zip 的 CodeQL 扫描的源文件存档副本。 如果比较存储库中的源代码文件和 src.zip 中的文件,则可以看到缺少哪些类型的文件。 一旦您知道了哪些类型的文件没有被分析,就更容易理解了如何更改 CodeQL 分析的工作流程。

在生成的代码中找到的警报

对于 Java、C、C++ 和 C# 等编译语言,CodeQL 分析在工作流运行过程中生成的所有代码。 要限制要分析的代码量,请通过在 run 块中指定自己的生成步骤,仅生成要分析的代码。 可以将指定自己的生成步骤与对 pull_requestpush 事件使用 pathspaths-ignore 筛选器相结合,以确保工作流仅在特定代码更改时运行。 有关详细信息,请参阅“GitHub Actions 的工作流语法”。

对于 Go、 JavaScript、Python,和 TypeScript 等语言,CodeQL 分析而不编译源代码,你可以指定其他配置选项来限制要分析的代码量。 有关详细信息,请参阅“自定义代码扫描”。

数据库中的提取错误

CodeQL 团队不断处理关键的提取错误,以确保可以扫描所有源文件。 但是,CodeQL 提取程序偶尔会在数据库创建过程中生成错误。 CodeQL 提供有关在日志文件中创建数据库期间生成的提取错误和警告的信息。 提取诊断信息指示数据库的整体运行状况。 大多数提取程序错误不会显著影响分析。 少量提取程序错误是正常的,通常表示分析状态良好。

但是,如果在数据库创建期间编译的绝大多数文件中看到提取程序错误,则应更详细地查看这些错误,以尝试了解为什么某些源文件未正确提取。

构建耗时过长

如果使用 CodeQL 分析进行的构建花费的时间太长,则可以尝试几种方法来减少构建时间。

增加内存或内核

如果使用自托管运行器运行 CodeQL 分析,您可以增加这些运行器上的内存或内核数。

使用矩阵构建来并行化分析

默认 CodeQL 分析工作流程 使用语言矩阵,这会导致每种语言的分析并行运行。 如果在“初始化 CodeQL”步骤中指定了要直接分析的语言,则将依次进行每种语言的分析。 要加快对多种语言的分析,请修改工作流程以使用矩阵。 有关详细信息,请参阅上述“编译语言的自动生成失败”中的工作流提取。

减少单个工作流程中要分析的代码量

分析时间通常与所分析的代码量成正比。 您可以通过减少一次分析的代码量来缩短分析时间,例如,排除测试代码,或将分析分解为多个工作流程,这些工作流程一次只分析一部分代码。

对于 Java、C、C++ 和 C# 等编译语言,CodeQL 分析在工作流运行过程中生成的所有代码。 要限制要分析的代码量,请通过在 run 块中指定自己的生成步骤,仅生成要分析的代码。 可以将指定自己的生成步骤与对 pull_requestpush 事件使用 pathspaths-ignore 筛选器相结合,以确保工作流仅在特定代码更改时运行。 有关详细信息,请参阅“GitHub Actions 的工作流语法”。

对于 Go、 JavaScript、Python,和 TypeScript 等语言,CodeQL 分析而不编译源代码,你可以指定其他配置选项来限制要分析的代码量。 有关详细信息,请参阅“自定义代码扫描”。

如果你按上文所述将分析拆分为多个工作流,我们仍然建议你至少保留一个按 schedule 运行的工作流分析存储库中的所有代码。 因为 CodeQL 分析组件之间的数据流量,所以某些复杂的安全行为只能在完整的构建中检测到。

仅在 schedule 事件期间运行

如果分析速度太慢,而无法在 pushpull_request 事件期间运行,建议仅在 schedule 事件上触发分析。 有关详细信息,请参阅“了解 GitHub Actions”。

检查工作流程运行的查询套件

默认情况下,每种语言都有三个主要查询套件可用。 如果已优化 CodeQL 数据库生成,但过程仍然太长,则可以减少运行的查询数。 默认查询套件将自动运行;它包含最快的安全查询,误报结果率最低。

除了默认查询之外,您可能还会运行额外的查询或查询套件。 检查工作流是否定义了其他查询套件或要使用 queries 元素运行的其他查询。 您可以尝试禁用其他一个或多个查询套件。 有关详细信息,请参阅“自定义代码扫描”。

错误:“服务器错误”

如果 code scanning 的工作流程运行因服务器错误而失败,请尝试再次运行工作流程。 如果问题仍然存在,请联系 你的站点管理员。

错误:“磁盘不足”或“内存不足”

在非常大的项目中, CodeQL 运行器上的磁盘或内存可能会耗尽。 如果遇到此问题,请尝试增加运行器上的内存。

错误:“不是 .ql 文件、.qls 文件、目录或查询包规范”

如果 CodeQL 在工作流中请求的位置找不到命名查询、查询套件或查询包,则会出现此错误。 此错误有两个常见的原因。

  • 工作流中有拼写错误。
  • 工作流通过路径引用的资源被重命名、删除或移动到新位置。

验证资源的位置后,可以更新工作流以指定正确的位置。

警告:“不再需要 git checkout HEAD^2”

如果您使用的是旧 CodeQL 工作流程,您可能会在输出中收到来自“初始化 CodeQL”操作的以下警告:

Warning: 1 issue was detected with this workflow: git checkout HEAD^2 is no longer
necessary. Please remove this step as Code Scanning recommends analyzing the merge
commit for best results.

通过从 CodeQL 工作流程中删除以下行来修复此问题。 这些行包含在 CodeQL 工作流初始版本中 Analyze 作业的 steps 部分。

        with:
          # We must fetch at least the immediate parents so that if this is
          # a pull request then we can checkout the head.
          fetch-depth: 2

      # If this run was triggered by a pull request event, then checkout
      # the head of the pull request instead of the merge commit.
      - run: git checkout HEAD^2
        if: ${{ github.event_name == 'pull_request' }}

修改后的工作流的 steps 部分将如下所示:

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2

      ...

有关编辑 CodeQL 工作流文件的详细信息,请参阅“自定义代码扫描”。