Compare commits

..

87 Commits

Author SHA1 Message Date
Michael B. Gale 26812c842e Add tests for getOrInitCodeQL 2026-02-24 20:23:22 +00:00
Michael B. Gale 6d90f4c71e Avoid using a global for getOrInitCodeQL 2026-02-24 20:09:10 +00:00
Michael B. Gale 37f3bfc967 Move getOrInitCodeQL to upload-sarif 2026-02-24 20:00:03 +00:00
Michael B. Gale b30d90c496 Tidy up imports 2026-02-24 19:53:44 +00:00
Michael B. Gale 503c5b9421 Merge remote-tracking branch 'origin/main' into mbg/upload-sarif/fix-codeql-multi-init 2026-02-24 19:52:40 +00:00
Michael B. Gale 28737ec792 Merge pull request #3503 from github/mbg/ff/make-connection-checks-default
Remove FF gate for connection checks
2026-02-24 17:26:42 +00:00
Henry Mercer e5f9d3b55e Merge pull request #3487 from github/henrymercer/overlay-status
Cache first failure building an overlay base DB to avoid repeated failures
2026-02-24 17:19:19 +00:00
Henry Mercer dc00a6f08f Improve error message 2026-02-24 16:47:42 +00:00
Henry Mercer ab56c02e0c Merge pull request #3497 from github/henrymercer/eslint-v9
Update eslint to v9
2026-02-24 14:38:34 +00:00
Michael B. Gale c59e24e20a Prevent combineSarifFilesUsingCLI initialising CodeQL instance more than once 2026-02-24 14:36:30 +00:00
Michael B. Gale 7cbb19ece7 Refactor minimalInitCodeQL out of combineSarifFilesUsingCLI 2026-02-24 13:52:41 +00:00
Michael B. Gale 25bde03dfb Remove FF gate for connection checks 2026-02-24 11:18:51 +00:00
Michael B. Gale c4dca28336 Merge pull request #3502 from github/mbg/remove-ccr
Remove all CCR-specific code and tests
2026-02-24 10:58:49 +00:00
Michael B. Gale 1aad2787ec Update PR template 2026-02-24 10:36:28 +00:00
Michael B. Gale b6cf67a711 Remove CCR e2e check 2026-02-24 10:34:09 +00:00
Michael B. Gale f59338d600 Remove isCCR 2026-02-24 10:33:23 +00:00
Henry Mercer 2a07b6e3c7 Merge branch 'main' into henrymercer/eslint-v9 2026-02-23 19:01:30 +00:00
Henry Mercer fba33f686a Enable tseslint strict rules 2026-02-23 19:00:06 +00:00
Henry Mercer 48094d2b6e Explicitly include eslint recommended rules 2026-02-23 18:43:10 +00:00
Michael B. Gale cb4e075f11 Merge pull request #3501 from github/mbg/ci/dont-label-merged 2026-02-23 15:41:07 +00:00
Henry Mercer 1847416575 Merge pull request #3498 from github/henrymercer/overlay-resource-checks-v2
Add feature flag for more lenient overlay resource checks
2026-02-23 15:22:02 +00:00
Michael B. Gale 11dd746d70 Don't run label-pr-size once a PR has been merged 2026-02-23 15:09:13 +00:00
Michael B. Gale a754a57c21 Merge pull request #3500 from github/mbg/fixup/version-pinning
Minor improvements to "Keeping the CodeQL Action up to date" section
2026-02-23 14:19:30 +00:00
Michael B. Gale 466da5ec2d Slight wording change 2026-02-23 12:00:58 +00:00
Michael B. Gale 0a9b98b511 Highlight that this for advanced setups 2026-02-23 11:59:08 +00:00
Michael B. Gale bce7dc4616 v3 => v4 2026-02-23 11:58:25 +00:00
Michael B. Gale b13ab62bc0 Remove extra blank line 2026-02-23 11:57:23 +00:00
Sam Robson 4ea06e96f5 Merge pull request #3499 from github/sam-robson/document-version-pinning-risk
docs: guidance on keeping the CodeQL Action up to date
2026-02-23 10:34:02 +00:00
Sam Robson c9223eb0a0 Merge branch 'main' into sam-robson/document-version-pinning-risk 2026-02-23 10:05:57 +00:00
Sam Robson f0767c48a1 docs: risks of pinning 2026-02-20 20:15:14 +00:00
Henry Mercer 4e71011f44 Add feature flag for more lenient overlay resource checks 2026-02-20 18:26:14 +00:00
Henry Mercer 710e294578 Merge pull request #3489 from github/dependabot/npm_and_yarn/npm-minor-37a5b5ae66
Bump the npm-minor group with 6 updates
2026-02-20 17:12:00 +00:00
Henry Mercer b948539dd4 Use import-x/no-cycle 2026-02-20 16:34:03 +00:00
Henry Mercer c54531587d Update eslint to v9 2026-02-20 15:57:26 +00:00
Michael B. Gale 559d85d1fa Merge pull request #3477 from github/mbg/features/offline-features 2026-02-20 15:36:07 +00:00
Michael B. Gale 8e010557a9 Merge pull request #3495 from github/mergeback/v4.32.4-to-main-89a39a4e 2026-02-20 15:02:14 +00:00
github-actions[bot] 37d6d1ca27 Rebuild 2026-02-20 14:32:21 +00:00
github-actions[bot] 68b53dc641 Update changelog and version after v4.32.4 2026-02-20 14:17:35 +00:00
Michael B. Gale 89a39a4e59 Merge pull request #3494 from github/update-v4.32.4-39ba80c47 2026-02-20 14:15:31 +00:00
Michael B. Gale e5d84c885c Apply remaining review suggestions 2026-02-20 13:54:55 +00:00
Michael B. Gale 0c202097b5 Apply suggestions from code review
Co-authored-by: Henry Mercer <henrymercer@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 13:51:55 +00:00
Michael B. Gale 314172e5a1 Fix typo 2026-02-20 13:11:54 +00:00
Michael B. Gale cdda72d36b Add changelog entries 2026-02-20 13:07:14 +00:00
github-actions[bot] cfda84cc55 Update changelog for v4.32.4 2026-02-20 12:42:43 +00:00
Michael B. Gale 39ba80c475 Merge pull request #3493 from github/update-bundle/codeql-bundle-v2.24.2
Update default bundle to 2.24.2
2026-02-20 11:01:00 +00:00
github-actions[bot] 00150dad95 Add changelog note 2026-02-20 10:44:41 +00:00
github-actions[bot] d97dce6561 Update default bundle to codeql-bundle-v2.24.2 2026-02-20 10:44:31 +00:00
Michael B. Gale 50fdbb9ec8 Merge pull request #3492 from github/henrymercer/new-repository-properties-ff
Use new feature flag for repository properties
2026-02-20 10:43:26 +00:00
Henry Mercer f7905e8415 Use new feature flag for repository properties 2026-02-19 18:30:50 +00:00
Henry Mercer 4191f52110 Address review comments 2026-02-19 17:57:08 +00:00
github-actions[bot] 79a913656c Rebuild 2026-02-18 17:55:38 +00:00
dependabot[bot] 167b47e60c Bump the npm-minor group with 6 updates
Bumps the npm-minor group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [semver](https://github.com/npm/node-semver) | `7.7.3` | `7.7.4` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.54.0` | `8.55.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.54.0` | `8.56.0` |
| [esbuild](https://github.com/evanw/esbuild) | `0.27.2` | `0.27.3` |
| [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) | `62.5.0` | `62.5.4` |
| [nock](https://github.com/nock/nock) | `14.0.10` | `14.0.11` |


Updates `semver` from 7.7.3 to 7.7.4
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.7.3...v7.7.4)

Updates `@typescript-eslint/eslint-plugin` from 8.54.0 to 8.55.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.55.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.54.0 to 8.56.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.56.0/packages/parser)

Updates `esbuild` from 0.27.2 to 0.27.3
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.2...v0.27.3)

Updates `eslint-plugin-jsdoc` from 62.5.0 to 62.5.4
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v62.5.0...v62.5.4)

Updates `nock` from 14.0.10 to 14.0.11
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v14.0.10...v14.0.11)

---
updated-dependencies:
- dependency-name: semver
  dependency-version: 7.7.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.55.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.56.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor
- dependency-name: esbuild
  dependency-version: 0.27.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: eslint-plugin-jsdoc
  dependency-version: 62.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
- dependency-name: nock
  dependency-version: 14.0.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-18 17:53:34 +00:00
Michael B. Gale 09bd46dda5 Fix typos in comments 2026-02-17 17:18:09 +00:00
Michael B. Gale b927a69f96 Merge remote-tracking branch 'origin/main' into mbg/features/offline-features 2026-02-17 17:14:08 +00:00
Henry Mercer 898ae16413 Improve log message 2026-02-17 15:55:15 +00:00
Henry Mercer fa56ea8dc0 Extract status file path helper 2026-02-17 15:55:13 +00:00
Henry Mercer 657f337cd1 Add tests for shouldSkipOverlayAnalysis 2026-02-17 15:55:05 +00:00
Henry Mercer 05d4e25296 Avoid mutating languages array in overlay status functions
Use [...languages].sort() instead of languages.sort() to avoid
mutating the caller's array as a side effect.
2026-02-17 15:55:05 +00:00
Henry Mercer 5c583bbb19 Include diagnostics in bundle 2026-02-17 15:55:02 +00:00
Henry Mercer 554b93127b More error message improvements 2026-02-17 15:55:01 +00:00
Henry Mercer 3dd1275368 Improve error messages 2026-02-17 15:55:01 +00:00
Henry Mercer d24014a749 Tweak diagnostic message 2026-02-17 15:55:00 +00:00
Henry Mercer cc0dce044b Improve diagnostic message wording 2026-02-17 15:55:00 +00:00
Henry Mercer ef58c00dfe Only store overlay status if analysis failed 2026-02-17 15:54:59 +00:00
Henry Mercer 7b7a951e08 Add status page diagnostic when overlay skipped 2026-02-17 15:54:58 +00:00
Henry Mercer 0c47ae1c18 Sort doc URLs 2026-02-17 15:54:58 +00:00
Henry Mercer 6c405c2562 Be more explicit about attempt to build overlay DB 2026-02-17 15:54:57 +00:00
Henry Mercer 827bba691f Introduce feature flags for saving and checking status 2026-02-17 15:54:57 +00:00
Henry Mercer 96961e0ee3 Save overlay status to Actions cache 2026-02-17 15:54:53 +00:00
Henry Mercer ebad062f08 Skip overlay analysis based on cached status 2026-02-17 15:54:31 +00:00
Henry Mercer e275d63e1d Generalise status to multiple languages 2026-02-17 15:54:06 +00:00
Henry Mercer 69c2819972 Add save and restore methods 2026-02-17 15:54:06 +00:00
Henry Mercer d28d9967fe Compute cache key for overlay language status 2026-02-17 15:54:06 +00:00
Henry Mercer d1bdc0ea05 Create separate directory for overlay source code 2026-02-17 15:54:03 +00:00
Michael B. Gale ab2580041c Merge remote-tracking branch 'origin/main' into mbg/features/offline-features 2026-02-17 09:54:34 +00:00
Michael B. Gale db834c9e1d Use OfflineFeatures when !supportsFeatureFlags as well 2026-02-15 16:03:48 +00:00
Michael B. Gale 7af50a43c1 Restore test improvements from previous PR 2026-02-15 15:57:02 +00:00
Michael B. Gale 60dee3dbd3 Log when using OfflineFeatures for CCR 2026-02-15 15:55:03 +00:00
Michael B. Gale 0874cf9f8b Change FFs not supported log message 2026-02-15 15:51:06 +00:00
Michael B. Gale bc76ceafaf Add test to check that OfflineFeatures doesn't use the API client 2026-02-15 15:40:23 +00:00
Michael B. Gale 377300bcda Add mockCCR helper to testing-utils 2026-02-15 15:40:23 +00:00
Michael B. Gale ee8360df59 Move FF test utils out of main file 2026-02-15 15:40:23 +00:00
Michael B. Gale 9dcfdf2c9c Return OfflineFeatures for CCR 2026-02-15 15:40:22 +00:00
Michael B. Gale 2c9bc45d46 Abstract over FeatureEnablement implementations with initFeatures 2026-02-15 15:40:21 +00:00
Michael B. Gale 368f322a09 Add OfflineFeatures class 2026-02-15 15:40:20 +00:00
Michael B. Gale 5283c3ba5a Move getDefaultCliVersion out of GitHubFeatureFlags
It doesn't need to be in there since it doesn't depend on the API itself and call `getDefaultCliVersionFromFlags` directly
2026-02-15 15:40:19 +00:00
Michael B. Gale ea1a400e13 Revert "Merge pull request #3476 from github/henrymercer/retry-auth-errors"
This reverts commit 9658e23e5b, reversing
changes made to 2d6b98c7cf.
2026-02-15 15:39:04 +00:00
56 changed files with 14009 additions and 13972 deletions
+3 -2
View File
@@ -23,13 +23,13 @@ For internal use only. Please select the risk level of this change:
Workflow types:
- **Advanced setup** - Impacts users who have custom CodeQL workflows.
- **Managed** - Impacts users with `dynamic` workflows (Default Setup, CCR, ...).
- **Managed** - Impacts users with `dynamic` workflows (Default Setup, Code Quality, ...).
Products:
- **Code Scanning** - The changes impact analyses when `analysis-kinds: code-scanning`.
- **Code Quality** - The changes impact analyses when `analysis-kinds: code-quality`.
- **CCR** - The changes impact analyses for Copilot Code Reviews.
- **Other first-party** - The changes impact other first-party analyses.
- **Third-party analyses** - The changes affect the `upload-sarif` action.
Environments:
@@ -54,6 +54,7 @@ Environments:
- **Feature flags** - All new or changed code paths can be fully disabled with corresponding feature flags.
- **Rollback** - Change can only be disabled by rolling back the release or releasing a new version with a fix.
- **Development/testing only** - This change cannot cause any failures in production.
- **Other** - Please provide details.
#### How will you know if something goes wrong after this change is released?
-87
View File
@@ -1,87 +0,0 @@
# Warning: This file is generated automatically, and should not be modified.
# Instead, please modify the template in the pr-checks directory and run:
# pr-checks/sync.sh
# to regenerate this file.
name: PR Check - CCR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GO111MODULE: auto
on:
push:
branches:
- main
- releases/v*
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
schedule:
- cron: '0 5 * * *'
workflow_dispatch:
inputs: {}
workflow_call:
inputs: {}
defaults:
run:
shell: bash
concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
group: ccr-${{github.ref}}
jobs:
ccr:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
version: stable-v2.17.6
- os: ubuntu-latest
version: stable-v2.18.4
- os: ubuntu-latest
version: stable-v2.19.4
- os: ubuntu-latest
version: stable-v2.20.7
- os: ubuntu-latest
version: stable-v2.21.4
- os: ubuntu-latest
version: stable-v2.22.4
- os: ubuntu-latest
version: default
- os: ubuntu-latest
version: linked
- os: ubuntu-latest
version: nightly-latest
name: CCR
if: github.triggering_actor != 'dependabot[bot]'
permissions:
contents: read
security-events: read
timeout-minutes: 45
runs-on: ${{ matrix.os }}
steps:
- name: Check out repository
uses: actions/checkout@v6
- name: Prepare test
id: prepare-test
uses: ./.github/actions/prepare-test
with:
version: ${{ matrix.version }}
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- uses: ./../action/init
id: init
with:
languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }}
- uses: ./../action/analyze
id: analysis
with:
upload-database: false
env:
CODEQL_ACTION_ANALYSIS_KEY: dynamic/copilot-pull-request-reviewer/codeql-action-test
CODEQL_ACTION_TEST_MODE: true
+1
View File
@@ -17,6 +17,7 @@ jobs:
sizeup:
name: Label PR with size
runs-on: ubuntu-slim
if: github.event.pull_request.merged != true
steps:
- name: Run sizeup
+8
View File
@@ -6,6 +6,14 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
No user facing changes.
## 4.32.4 - 20 Feb 2026
- Update default CodeQL bundle version to [2.24.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.2). [#3493](https://github.com/github/codeql-action/pull/3493)
- Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. [#3473](https://github.com/github/codeql-action/pull/3473)
- When the CodeQL Action is run [with debugging enabled in Default Setup](https://docs.github.com/en/code-security/how-tos/scan-code-for-vulnerabilities/troubleshooting/troubleshooting-analysis-errors/logs-not-detailed-enough#creating-codeql-debugging-artifacts-for-codeql-default-setup) and [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries), the "Setup proxy for registries" step will output additional diagnostic information that can be used for troubleshooting. [#3486](https://github.com/github/codeql-action/pull/3486)
- Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. [#3485](https://github.com/github/codeql-action/pull/3485)
- Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a [nightly CodeQL CLI release](https://github.com/dsp-testing/codeql-cli-nightlies) instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. [#3484](https://github.com/github/codeql-action/pull/3484)
## 4.32.3 - 13 Feb 2026
- Added experimental support for testing connections to [private package registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. [#3466](https://github.com/github/codeql-action/pull/3466)
+6
View File
@@ -80,6 +80,12 @@ We typically release new minor versions of the CodeQL Action and Bundle when a n
See the full list of GHES release and deprecation dates at [GitHub Enterprise Server releases](https://docs.github.com/en/enterprise-server/admin/all-releases#releases-of-github-enterprise-server).
## Keeping the CodeQL Action up to date in advanced setups
If you are using an [advanced setup](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/configuring-advanced-setup-for-code-scanning), we recommend referencing the CodeQL Action using a major version tag (e.g. `v4`) in your workflow file. This ensures your workflow automatically picks up the latest release within that major version, including bug fixes, new features, and updated CodeQL CLI versions.
If you pin to a specific commit SHA or patch version tag, ensure you keep it updated (e.g. via [Dependabot](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot)). Some CodeQL Action features are enabled by server-side flags that may be removed over time, which can cause old versions to lose functionality.
## Troubleshooting
Read about [troubleshooting code scanning](https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning).
+35 -37
View File
@@ -1,27 +1,14 @@
// Automatically generated by running npx @eslint/migrate-config .eslintrc.json
import path from "node:path";
import { fileURLToPath } from "node:url";
import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import { fixupPluginRules } from "@eslint/compat";
import js from "@eslint/js";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import filenames from "eslint-plugin-filenames";
import github from "eslint-plugin-github";
import _import from "eslint-plugin-import";
import { importX, createNodeResolver } from "eslint-plugin-import-x";
import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
import noAsyncForeach from "eslint-plugin-no-async-foreach";
import jsdoc from "eslint-plugin-jsdoc";
import tseslint from "typescript-eslint";
import globals from "globals";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
const githubFlatConfigs = github.getFlatConfigs();
export default [
{
@@ -36,29 +23,29 @@ export default [
".github/**/*",
],
},
...fixupConfigRules(
compat.extends(
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:github/recommended",
"plugin:github/typescript",
"plugin:import/typescript",
),
),
// eslint recommended config
js.configs.recommended,
// Type-checked rules from typescript-eslint
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.strict,
// eslint-plugin-github recommended config
githubFlatConfigs.recommended,
// eslint-plugin-github typescript config
...githubFlatConfigs.typescript,
// import-x TypeScript settings
// This is needed for import-x rules to properly parse TypeScript files.
{
settings: importX.flatConfigs.typescript.settings,
},
{
plugins: {
"@typescript-eslint": fixupPluginRules(typescriptEslint),
filenames: fixupPluginRules(filenames),
github: fixupPluginRules(github),
import: fixupPluginRules(_import),
"no-async-foreach": noAsyncForeach,
"import-x": importX,
"no-async-foreach": fixupPluginRules(noAsyncForeach),
"jsdoc": jsdoc,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 5,
ecmaVersion: "latest",
sourceType: "module",
globals: {
@@ -79,10 +66,16 @@ export default [
typescript: {},
},
"import/ignore": ["sinon", "uuid", "@octokit/plugin-retry", "del", "get-folder-size"],
"import-x/resolver-next": [
createTypeScriptImportResolver(),
createNodeResolver({
extensions: [".ts", ".js", ".json"],
}),
],
},
rules: {
"filenames/match-regex": ["error", "^[a-z0-9-]+(\\.test)?$"],
"github/filenames-match-regex": ["error", "^[a-z0-9-]+(\\.test)?$"],
"i18n-text/no-en": "off",
"import/extensions": [
@@ -94,7 +87,10 @@ export default [
"import/no-amd": "error",
"import/no-commonjs": "error",
"import/no-cycle": "error",
// import/no-cycle does not seem to work with ESLint 9.
// Use import-x/no-cycle from eslint-plugin-import-x instead.
"import/no-cycle": "off",
"import-x/no-cycle": "error",
"import/no-dynamic-require": "error",
"import/no-extraneous-dependencies": [
@@ -132,6 +128,8 @@ export default [
"no-async-foreach/no-async-foreach": "error",
"no-sequences": "error",
"no-shadow": "off",
// This is overly restrictive with unsetting `EnvVar`s
"@typescript-eslint/no-dynamic-delete": "off",
"@typescript-eslint/no-shadow": "error",
"@typescript-eslint/prefer-optional-chain": "error",
"one-var": ["error", "never"],
+47 -34
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -92794,7 +92791,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache4;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -92971,7 +92968,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
function saveCache5(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -98471,8 +98468,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
exports2.restoreCache = restoreCache5;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var path7 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -98529,7 +98526,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache5(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -98673,7 +98670,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache4(paths_1, key_1, options_1) {
function saveCache5(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -160722,9 +160719,6 @@ function getRequiredEnvParam(paramName) {
return value;
}
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
var cachedCodeQlVersion = void 0;
function cacheCodeQlVersion(version) {
@@ -161291,7 +161285,7 @@ function withGroup(groupName, f) {
// src/feature-flags.ts
var semver5 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var fs2 = __toESM(require("fs"));
var path2 = __toESM(require("path"));
var actionsCache = __toESM(require_cache5());
@@ -161461,7 +161455,7 @@ async function isAnalyzingDefaultBranch() {
return currentRef === defaultBranch;
}
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -161675,6 +161669,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -161695,6 +161699,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -161736,18 +161745,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -161759,12 +161763,17 @@ var featureConfig = {
}
};
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -162182,14 +162191,18 @@ ${output}`
await runCli(cmd, codeqlArgs);
}
},
async databaseBundle(databasePath, outputFilePath, databaseName, alsoIncludeRelativePaths) {
async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) {
const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : [];
const args = [
"database",
"bundle",
databasePath,
`--output=${outputFilePath}`,
`--name=${databaseName}`,
...getExtraOptionsFromEnv(["database", "bundle"])
...includeDiagnosticsArgs,
...getExtraOptionsFromEnv(["database", "bundle"], {
ignoringOptions: includeDiagnosticsArgs
})
];
if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) {
args.push(
@@ -162447,7 +162460,7 @@ var core11 = __toESM(require_core());
// src/dependency-caching.ts
var import_path = require("path");
var actionsCache3 = __toESM(require_cache5());
var actionsCache4 = __toESM(require_cache5());
var glob = __toESM(require_glob());
function getJavaTempDependencyDir() {
return (0, import_path.join)(getTemporaryDirectory(), "codeql_java", "repository");
+1171 -2219
View File
File diff suppressed because it is too large Load Diff
+134 -85
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -92794,7 +92791,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache3;
exports2.saveCache = saveCache4;
var core14 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -92971,7 +92968,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache3(cacheId, archivePath, signedUploadURL, options) {
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -98471,8 +98468,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache3;
exports2.saveCache = saveCache3;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
var core14 = __importStar2(require_core());
var path7 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -98529,7 +98526,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache3(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -98673,7 +98670,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache3(paths_1, key_1, options_1) {
function saveCache4(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -102980,9 +102977,6 @@ var HTTPError = class extends Error {
}
};
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function asHTTPError(arg) {
if (typeof arg !== "object" || arg === null || typeof arg.message !== "string") {
@@ -103148,10 +103142,6 @@ function getWorkflowRunAttempt() {
function isSelfHostedRunner() {
return process.env.RUNNER_ENVIRONMENT === "self-hosted";
}
var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer";
function isCCR() {
return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false;
}
function prettyPrintInvocation(cmd, args) {
return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" ");
}
@@ -103695,10 +103685,10 @@ var path3 = __toESM(require("path"));
var semver5 = __toESM(require_semver2());
// src/defaults.json
var bundleVersion = "codeql-bundle-v2.24.1";
var cliVersion = "2.24.1";
var bundleVersion = "codeql-bundle-v2.24.2";
var cliVersion = "2.24.2";
// src/overlay-database-utils.ts
// src/overlay/index.ts
var fs2 = __toESM(require("fs"));
var path2 = __toESM(require("path"));
var actionsCache = __toESM(require_cache5());
@@ -103868,7 +103858,7 @@ async function isAnalyzingDefaultBranch() {
return currentRef === defaultBranch;
}
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -104080,6 +104070,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -104100,6 +104100,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -104141,18 +104146,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -104164,34 +104164,47 @@ var featureConfig = {
}
};
var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
var Features = class {
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
var OfflineFeatures = class {
constructor(logger) {
this.logger = logger;
this.gitHubFeatureFlags = new GitHubFeatureFlags(
gitHubVersion,
repositoryNwo,
path3.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
gitHubFeatureFlags;
async getDefaultCliVersion(variant) {
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
async getDefaultCliVersion(_variant) {
return {
cliVersion,
tagName: bundleVersion
};
}
/**
* Gets the `FeatureConfig` for `feature`.
*/
getFeatureConfig(feature) {
return featureConfig[feature];
}
/**
* Determines whether `feature` is enabled without consulting the GitHub API.
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, the
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const config = featureConfig[feature];
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
return this.getDefaultValue(feature);
}
/**
* Determines whether `feature` is enabled using the CLI and environment variables.
*/
async getOfflineValue(feature, codeql) {
const config = this.getFeatureConfig(feature);
if (!codeql && config.minimumVersion) {
throw new Error(
`Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`
@@ -104241,13 +104254,11 @@ var Features = class {
);
return true;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return void 0;
}
/** Gets the default value of `feature`. */
async getDefaultValue(feature) {
const config = this.getFeatureConfig(feature);
const defaultValue = config.defaultValue;
this.logger.debug(
`Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.`
@@ -104255,9 +104266,51 @@ var Features = class {
return defaultValue;
}
};
var Features = class extends OfflineFeatures {
gitHubFeatureFlags;
constructor(repositoryNwo, tempDir, logger) {
super(logger);
this.gitHubFeatureFlags = new GitHubFeatureFlags(
repositoryNwo,
path3.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
}
return super.getDefaultCliVersion(variant);
}
/**
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return this.getDefaultValue(feature);
}
};
var GitHubFeatureFlags = class {
constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) {
this.gitHubVersion = gitHubVersion;
constructor(repositoryNwo, featureFlagsFile, logger) {
this.repositoryNwo = repositoryNwo;
this.featureFlagsFile = featureFlagsFile;
this.logger = logger;
@@ -104283,15 +104336,6 @@ var GitHubFeatureFlags = class {
}
return version;
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.getDefaultCliVersionFromFlags();
}
return {
cliVersion,
tagName: bundleVersion
};
}
async getDefaultCliVersionFromFlags() {
const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response).map(
@@ -104381,20 +104425,6 @@ var GitHubFeatureFlags = class {
}
}
async loadApiResponse() {
if (!supportsFeatureFlags(this.gitHubVersion.type)) {
this.logger.debug(
"Not running against github.com. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
if (isCCR()) {
this.logger.debug(
"Feature flags are not supported in Copilot Code Review. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
try {
const featuresToRequest = Object.entries(featureConfig).filter(
([, config]) => !config.legacyApi
@@ -104446,13 +104476,28 @@ var GitHubFeatureFlags = class {
function supportsFeatureFlags(githubVariant) {
return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */;
}
function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) {
if (!supportsFeatureFlags(gitHubVersion.type)) {
logger.debug(
"Not running against github.com. Using default values for all features."
);
return new OfflineFeatures(logger);
} else {
return new Features(repositoryNwo, tempDir, logger);
}
}
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache2 = __toESM(require_cache5());
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -104903,14 +104948,18 @@ ${output}`
await runCli(cmd, codeqlArgs);
}
},
async databaseBundle(databasePath, outputFilePath, databaseName, alsoIncludeRelativePaths) {
async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) {
const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : [];
const args = [
"database",
"bundle",
databasePath,
`--output=${outputFilePath}`,
`--name=${databaseName}`,
...getExtraOptionsFromEnv(["database", "bundle"])
...includeDiagnosticsArgs,
...getExtraOptionsFromEnv(["database", "bundle"], {
ignoringOptions: includeDiagnosticsArgs
})
];
if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) {
args.push(
@@ -105197,7 +105246,7 @@ async function setupCppAutobuild(codeql, logger) {
const featureName = "C++ automatic installation of dependencies";
const gitHubVersion = await getGitHubVersion();
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
+4 -4
View File
@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.24.1",
"cliVersion": "2.24.1",
"priorBundleVersion": "codeql-bundle-v2.24.0",
"priorCliVersion": "2.24.0"
"bundleVersion": "codeql-bundle-v2.24.2",
"cliVersion": "2.24.2",
"priorBundleVersion": "codeql-bundle-v2.24.1",
"priorCliVersion": "2.24.1"
}
+2257 -3257
View File
File diff suppressed because it is too large Load Diff
+625 -452
View File
File diff suppressed because it is too large Load Diff
+46 -33
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -92794,7 +92791,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache3;
exports2.saveCache = saveCache4;
var core13 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -92971,7 +92968,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache3(cacheId, archivePath, signedUploadURL, options) {
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -98471,8 +98468,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache3;
exports2.saveCache = saveCache3;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
var core13 = __importStar2(require_core());
var path5 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -98529,7 +98526,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache3(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core13.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -98673,7 +98670,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache3(paths_1, key_1, options_1) {
function saveCache4(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core13.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -102973,9 +102970,6 @@ var HTTPError = class extends Error {
}
};
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function asHTTPError(arg) {
if (typeof arg !== "object" || arg === null || typeof arg.message !== "string") {
@@ -103687,7 +103681,7 @@ function getActionsLogger() {
// src/feature-flags.ts
var semver5 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var fs2 = __toESM(require("fs"));
var path2 = __toESM(require("path"));
var actionsCache = __toESM(require_cache5());
@@ -103857,7 +103851,7 @@ async function isAnalyzingDefaultBranch() {
return currentRef === defaultBranch;
}
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -104067,6 +104061,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -104087,6 +104091,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -104128,18 +104137,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -104151,12 +104155,17 @@ var featureConfig = {
}
};
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -104580,14 +104589,18 @@ ${output}`
await runCli(cmd, codeqlArgs);
}
},
async databaseBundle(databasePath, outputFilePath, databaseName, alsoIncludeRelativePaths) {
async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) {
const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : [];
const args = [
"database",
"bundle",
databasePath,
`--output=${outputFilePath}`,
`--name=${databaseName}`,
...getExtraOptionsFromEnv(["database", "bundle"])
...includeDiagnosticsArgs,
...getExtraOptionsFromEnv(["database", "bundle"], {
ignoringOptions: includeDiagnosticsArgs
})
];
if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) {
args.push(
+134 -85
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -91497,7 +91494,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache3;
exports2.saveCache = saveCache4;
var core13 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -91674,7 +91671,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache3(cacheId, archivePath, signedUploadURL, options) {
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -97174,8 +97171,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache3;
exports2.saveCache = saveCache3;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
var core13 = __importStar2(require_core());
var path9 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -97232,7 +97229,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache3(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core13.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -97376,7 +97373,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache3(paths_1, key_1, options_1) {
function saveCache4(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core13.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -103046,9 +103043,6 @@ var HTTPError = class extends Error {
}
};
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function asHTTPError(arg) {
if (typeof arg !== "object" || arg === null || typeof arg.message !== "string") {
@@ -103265,10 +103259,6 @@ function isSelfHostedRunner() {
function isDynamicWorkflow() {
return getWorkflowEventName() === "dynamic";
}
var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer";
function isCCR() {
return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false;
}
function prettyPrintInvocation(cmd, args) {
return [cmd, ...args].map((x) => x.includes(" ") ? `'${x}'` : x).join(" ");
}
@@ -103566,10 +103556,10 @@ var path4 = __toESM(require("path"));
var semver4 = __toESM(require_semver2());
// src/defaults.json
var bundleVersion = "codeql-bundle-v2.24.1";
var cliVersion = "2.24.1";
var bundleVersion = "codeql-bundle-v2.24.2";
var cliVersion = "2.24.2";
// src/overlay-database-utils.ts
// src/overlay/index.ts
var fs3 = __toESM(require("fs"));
var path3 = __toESM(require("path"));
var actionsCache = __toESM(require_cache5());
@@ -103767,7 +103757,7 @@ function formatDuration(durationMs) {
return `${minutes}m${seconds}s`;
}
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -103980,6 +103970,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -104000,6 +104000,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -104041,18 +104046,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -104064,34 +104064,47 @@ var featureConfig = {
}
};
var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
var Features = class {
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
var OfflineFeatures = class {
constructor(logger) {
this.logger = logger;
this.gitHubFeatureFlags = new GitHubFeatureFlags(
gitHubVersion,
repositoryNwo,
path4.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
gitHubFeatureFlags;
async getDefaultCliVersion(variant) {
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
async getDefaultCliVersion(_variant) {
return {
cliVersion,
tagName: bundleVersion
};
}
/**
* Gets the `FeatureConfig` for `feature`.
*/
getFeatureConfig(feature) {
return featureConfig[feature];
}
/**
* Determines whether `feature` is enabled without consulting the GitHub API.
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, the
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const config = featureConfig[feature];
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
return this.getDefaultValue(feature);
}
/**
* Determines whether `feature` is enabled using the CLI and environment variables.
*/
async getOfflineValue(feature, codeql) {
const config = this.getFeatureConfig(feature);
if (!codeql && config.minimumVersion) {
throw new Error(
`Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`
@@ -104141,13 +104154,11 @@ var Features = class {
);
return true;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return void 0;
}
/** Gets the default value of `feature`. */
async getDefaultValue(feature) {
const config = this.getFeatureConfig(feature);
const defaultValue = config.defaultValue;
this.logger.debug(
`Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.`
@@ -104155,9 +104166,51 @@ var Features = class {
return defaultValue;
}
};
var Features = class extends OfflineFeatures {
gitHubFeatureFlags;
constructor(repositoryNwo, tempDir, logger) {
super(logger);
this.gitHubFeatureFlags = new GitHubFeatureFlags(
repositoryNwo,
path4.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
}
return super.getDefaultCliVersion(variant);
}
/**
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return this.getDefaultValue(feature);
}
};
var GitHubFeatureFlags = class {
constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) {
this.gitHubVersion = gitHubVersion;
constructor(repositoryNwo, featureFlagsFile, logger) {
this.repositoryNwo = repositoryNwo;
this.featureFlagsFile = featureFlagsFile;
this.logger = logger;
@@ -104183,15 +104236,6 @@ var GitHubFeatureFlags = class {
}
return version;
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.getDefaultCliVersionFromFlags();
}
return {
cliVersion,
tagName: bundleVersion
};
}
async getDefaultCliVersionFromFlags() {
const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response).map(
@@ -104281,20 +104325,6 @@ var GitHubFeatureFlags = class {
}
}
async loadApiResponse() {
if (!supportsFeatureFlags(this.gitHubVersion.type)) {
this.logger.debug(
"Not running against github.com. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
if (isCCR()) {
this.logger.debug(
"Feature flags are not supported in Copilot Code Review. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
try {
const featuresToRequest = Object.entries(featureConfig).filter(
([, config]) => !config.legacyApi
@@ -104346,6 +104376,16 @@ var GitHubFeatureFlags = class {
function supportsFeatureFlags(githubVariant) {
return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */;
}
function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) {
if (!supportsFeatureFlags(gitHubVersion.type)) {
logger.debug(
"Not running against github.com. Using default values for all features."
);
return new OfflineFeatures(logger);
} else {
return new Features(repositoryNwo, tempDir, logger);
}
}
// src/init.ts
var toolrunner4 = __toESM(require_toolrunner());
@@ -104677,12 +104717,17 @@ function writeDiagnostic(config, language, diagnostic) {
}
}
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -105990,14 +106035,18 @@ ${output}`
await runCli(cmd, codeqlArgs);
}
},
async databaseBundle(databasePath, outputFilePath, databaseName, alsoIncludeRelativePaths) {
async databaseBundle(databasePath, outputFilePath, databaseName, includeDiagnostics, alsoIncludeRelativePaths) {
const includeDiagnosticsArgs = includeDiagnostics ? ["--include-diagnostics"] : [];
const args = [
"database",
"bundle",
databasePath,
`--output=${outputFilePath}`,
`--name=${databaseName}`,
...getExtraOptionsFromEnv(["database", "bundle"])
...includeDiagnosticsArgs,
...getExtraOptionsFromEnv(["database", "bundle"], {
ignoringOptions: includeDiagnosticsArgs
})
];
if (await this.supportsFeature("bundleSupportsIncludeOption" /* BundleSupportsIncludeOption */)) {
args.push(
@@ -106526,7 +106575,7 @@ async function run(startedAt) {
checkGitHubVersionInRange(gitHubVersion, logger);
checkActionVersion(getActionVersion(), gitHubVersion);
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
+41 -32
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -92794,7 +92791,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache4;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -92971,7 +92968,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
function saveCache5(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -98471,8 +98468,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
exports2.restoreCache = restoreCache5;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var path4 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -98529,7 +98526,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache5(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -98673,7 +98670,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache4(paths_1, key_1, options_1) {
function saveCache5(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -160700,9 +160697,6 @@ function getRequiredEnvParam(paramName) {
return value;
}
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function isInTestMode() {
return process.env["CODEQL_ACTION_TEST_MODE" /* TEST_MODE */] === "true";
@@ -160918,7 +160912,7 @@ function getActionsLogger() {
// src/feature-flags.ts
var semver5 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var actionsCache = __toESM(require_cache5());
// src/git-utils.ts
@@ -160927,7 +160921,7 @@ var toolrunner2 = __toESM(require_toolrunner());
var io3 = __toESM(require_io());
var semver3 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -161081,6 +161075,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -161101,6 +161105,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -161142,18 +161151,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -161165,12 +161169,17 @@ var featureConfig = {
}
};
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -161394,7 +161403,7 @@ var semver7 = __toESM(require_semver2());
var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024;
// src/dependency-caching.ts
var actionsCache3 = __toESM(require_cache5());
var actionsCache4 = __toESM(require_cache5());
var glob = __toESM(require_glob());
// src/artifact-scanner.ts
+129 -86
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -91497,7 +91494,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache3;
exports2.saveCache = saveCache4;
var core12 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -91674,7 +91671,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache3(cacheId, archivePath, signedUploadURL, options) {
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -97174,8 +97171,8 @@ var require_cache5 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache3;
exports2.saveCache = saveCache3;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
var core12 = __importStar2(require_core());
var path5 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -97232,7 +97229,7 @@ var require_cache5 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache3(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core12.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -97376,7 +97373,7 @@ var require_cache5 = __commonJS({
return void 0;
});
}
function saveCache3(paths_1, key_1, options_1) {
function saveCache4(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core12.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -120148,9 +120145,6 @@ var HTTPError = class extends Error {
}
};
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function asHTTPError(arg) {
if (typeof arg !== "object" || arg === null || typeof arg.message !== "string") {
@@ -120284,10 +120278,6 @@ function getWorkflowRunAttempt() {
function isSelfHostedRunner() {
return process.env.RUNNER_ENVIRONMENT === "self-hosted";
}
var CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer";
function isCCR() {
return process.env["CODEQL_ACTION_ANALYSIS_KEY" /* ANALYSIS_KEY */]?.startsWith(CCR_KEY_PREFIX) || false;
}
var persistedInputsKey = "persisted_inputs";
var persistInputs = function() {
const inputEnvironmentVariables = Object.entries(process.env).filter(
@@ -120499,10 +120489,10 @@ var path = __toESM(require("path"));
var semver4 = __toESM(require_semver2());
// src/defaults.json
var bundleVersion = "codeql-bundle-v2.24.1";
var cliVersion = "2.24.1";
var bundleVersion = "codeql-bundle-v2.24.2";
var cliVersion = "2.24.2";
// src/overlay-database-utils.ts
// src/overlay/index.ts
var actionsCache = __toESM(require_cache5());
// src/caching-utils.ts
@@ -120616,7 +120606,7 @@ function getActionsLogger() {
};
}
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -120772,6 +120762,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -120792,6 +120792,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -120833,18 +120838,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -120856,34 +120856,47 @@ var featureConfig = {
}
};
var FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
var Features = class {
constructor(gitHubVersion, repositoryNwo, tempDir, logger) {
var OfflineFeatures = class {
constructor(logger) {
this.logger = logger;
this.gitHubFeatureFlags = new GitHubFeatureFlags(
gitHubVersion,
repositoryNwo,
path.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
gitHubFeatureFlags;
async getDefaultCliVersion(variant) {
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
async getDefaultCliVersion(_variant) {
return {
cliVersion,
tagName: bundleVersion
};
}
/**
* Gets the `FeatureConfig` for `feature`.
*/
getFeatureConfig(feature) {
return featureConfig[feature];
}
/**
* Determines whether `feature` is enabled without consulting the GitHub API.
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, the
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const config = featureConfig[feature];
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
return this.getDefaultValue(feature);
}
/**
* Determines whether `feature` is enabled using the CLI and environment variables.
*/
async getOfflineValue(feature, codeql) {
const config = this.getFeatureConfig(feature);
if (!codeql && config.minimumVersion) {
throw new Error(
`Internal error: A minimum version is specified for feature ${feature}, but no instance of CodeQL was provided.`
@@ -120933,13 +120946,11 @@ var Features = class {
);
return true;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return void 0;
}
/** Gets the default value of `feature`. */
async getDefaultValue(feature) {
const config = this.getFeatureConfig(feature);
const defaultValue = config.defaultValue;
this.logger.debug(
`Feature ${feature} is ${defaultValue ? "enabled" : "disabled"} due to its default value.`
@@ -120947,9 +120958,51 @@ var Features = class {
return defaultValue;
}
};
var Features = class extends OfflineFeatures {
gitHubFeatureFlags;
constructor(repositoryNwo, tempDir, logger) {
super(logger);
this.gitHubFeatureFlags = new GitHubFeatureFlags(
repositoryNwo,
path.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger
);
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
}
return super.getDefaultCliVersion(variant);
}
/**
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature, codeql) {
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== void 0) {
return offlineValue;
}
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== void 0) {
this.logger.debug(
`Feature ${feature} is ${apiValue ? "enabled" : "disabled"} via the GitHub API.`
);
return apiValue;
}
return this.getDefaultValue(feature);
}
};
var GitHubFeatureFlags = class {
constructor(gitHubVersion, repositoryNwo, featureFlagsFile, logger) {
this.gitHubVersion = gitHubVersion;
constructor(repositoryNwo, featureFlagsFile, logger) {
this.repositoryNwo = repositoryNwo;
this.featureFlagsFile = featureFlagsFile;
this.logger = logger;
@@ -120975,15 +121028,6 @@ var GitHubFeatureFlags = class {
}
return version;
}
async getDefaultCliVersion(variant) {
if (supportsFeatureFlags(variant)) {
return await this.getDefaultCliVersionFromFlags();
}
return {
cliVersion,
tagName: bundleVersion
};
}
async getDefaultCliVersionFromFlags() {
const response = await this.getAllFeatures();
const enabledFeatureFlagCliVersions = Object.entries(response).map(
@@ -121073,20 +121117,6 @@ var GitHubFeatureFlags = class {
}
}
async loadApiResponse() {
if (!supportsFeatureFlags(this.gitHubVersion.type)) {
this.logger.debug(
"Not running against github.com. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
if (isCCR()) {
this.logger.debug(
"Feature flags are not supported in Copilot Code Review. Using default values for all features."
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
try {
const featuresToRequest = Object.entries(featureConfig).filter(
([, config]) => !config.legacyApi
@@ -121138,6 +121168,16 @@ var GitHubFeatureFlags = class {
function supportsFeatureFlags(githubVariant) {
return githubVariant === "GitHub.com" /* DOTCOM */ || githubVariant === "GitHub Enterprise Cloud with data residency" /* GHEC_DR */;
}
function initFeatures(gitHubVersion, repositoryNwo, tempDir, logger) {
if (!supportsFeatureFlags(gitHubVersion.type)) {
logger.debug(
"Not running against github.com. Using default values for all features."
);
return new OfflineFeatures(logger);
} else {
return new Features(repositoryNwo, tempDir, logger);
}
}
// src/start-proxy.ts
var path2 = __toESM(require("path"));
@@ -121225,12 +121265,17 @@ var PACK_IDENTIFIER_PATTERN = (function() {
return new RegExp(`^${component}/${component}$`);
})();
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache5());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache5());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -122071,7 +122116,7 @@ async function run(startedAt) {
core11.saveState("proxy-log-file", proxyLogFilePath);
const repositoryNwo = getRepositoryNwo();
const gitHubVersion = await getGitHubVersion();
features = new Features(
features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
@@ -122116,9 +122161,7 @@ async function run(startedAt) {
proxyLogFilePath,
logger
);
if (await features.getValue("start_proxy_connection_checks" /* StartProxyConnectionChecks */)) {
await checkConnections(logger, proxyInfo);
}
await checkConnections(logger, proxyInfo);
await sendSuccessStatusReport(
startedAt,
{
+2383 -2410
View File
File diff suppressed because it is too large Load Diff
+41 -32
View File
@@ -45986,7 +45986,7 @@ var require_package = __commonJS({
"package.json"(exports2, module2) {
module2.exports = {
name: "codeql",
version: "4.32.4",
version: "4.32.5",
private: true,
description: "CodeQL action",
scripts: {
@@ -46031,14 +46031,12 @@ var require_package = __commonJS({
jsonschema: "1.4.1",
long: "^5.3.2",
"node-forge": "^1.3.3",
semver: "^7.7.3",
semver: "^7.7.4",
uuid: "^13.0.0"
},
devDependencies: {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -46048,21 +46046,20 @@ var require_package = __commonJS({
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
ava: "^6.4.1",
esbuild: "^0.27.2",
eslint: "^8.57.1",
esbuild: "^0.27.3",
eslint: "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
glob: "^11.1.0",
nock: "^14.0.10",
globals: "^16.5.0",
nock: "^14.0.11",
sinon: "^21.0.1",
typescript: "^5.9.3"
typescript: "^5.9.3",
"typescript-eslint": "^8.56.0"
},
overrides: {
"@actions/tool-cache": {
@@ -154776,7 +154773,7 @@ var require_cacheHttpClient = __commonJS({
exports2.getCacheEntry = getCacheEntry;
exports2.downloadCache = downloadCache;
exports2.reserveCache = reserveCache;
exports2.saveCache = saveCache4;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var http_client_1 = require_lib();
var auth_1 = require_auth();
@@ -154953,7 +154950,7 @@ Other caches with similar key:`);
}));
});
}
function saveCache4(cacheId, archivePath, signedUploadURL, options) {
function saveCache5(cacheId, archivePath, signedUploadURL, options) {
return __awaiter2(this, void 0, void 0, function* () {
const uploadOptions = (0, options_1.getUploadOptions)(options);
if (uploadOptions.useAzureSdk) {
@@ -156227,8 +156224,8 @@ var require_cache6 = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.FinalizeCacheError = exports2.ReserveCacheError = exports2.ValidationError = void 0;
exports2.isFeatureAvailable = isFeatureAvailable;
exports2.restoreCache = restoreCache4;
exports2.saveCache = saveCache4;
exports2.restoreCache = restoreCache5;
exports2.saveCache = saveCache5;
var core14 = __importStar2(require_core());
var path3 = __importStar2(require("path"));
var utils = __importStar2(require_cacheUtils());
@@ -156285,7 +156282,7 @@ var require_cache6 = __commonJS({
return !!process.env["ACTIONS_CACHE_URL"];
}
}
function restoreCache4(paths_1, primaryKey_1, restoreKeys_1, options_1) {
function restoreCache5(paths_1, primaryKey_1, restoreKeys_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -156429,7 +156426,7 @@ var require_cache6 = __commonJS({
return void 0;
});
}
function saveCache4(paths_1, key_1, options_1) {
function saveCache5(paths_1, key_1, options_1) {
return __awaiter2(this, arguments, void 0, function* (paths, key, options, enableCrossOsArchive = false) {
const cacheServiceVersion = (0, config_1.getCacheServiceVersion)();
core14.debug(`Cache service version: ${cacheServiceVersion}`);
@@ -160700,9 +160697,6 @@ function getRequiredEnvParam(paramName) {
return value;
}
var ConfigurationError = class extends Error {
constructor(message) {
super(message);
}
};
function isInTestMode() {
return process.env["CODEQL_ACTION_TEST_MODE" /* TEST_MODE */] === "true";
@@ -161076,7 +161070,7 @@ function withGroup(groupName, f) {
// src/feature-flags.ts
var semver5 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var actionsCache = __toESM(require_cache6());
// src/git-utils.ts
@@ -161085,7 +161079,7 @@ var toolrunner2 = __toESM(require_toolrunner());
var io3 = __toESM(require_io());
var semver3 = __toESM(require_semver2());
// src/overlay-database-utils.ts
// src/overlay/index.ts
var CODEQL_OVERLAY_MINIMUM_VERSION = "2.23.8";
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB = 7500;
var OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_BYTES = OVERLAY_BASE_DATABASE_MAX_UPLOAD_SIZE_MB * 1e6;
@@ -161243,6 +161237,16 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: void 0
},
["overlay_analysis_status_check" /* OverlayAnalysisStatusCheck */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: void 0
},
["overlay_analysis_status_save" /* OverlayAnalysisStatusSave */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: void 0
},
["overlay_analysis_go" /* OverlayAnalysisGo */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -161263,6 +161267,11 @@ var featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: void 0
},
["overlay_analysis_resource_checks_v2" /* OverlayAnalysisResourceChecksV2 */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: void 0
},
["overlay_analysis_ruby" /* OverlayAnalysisRuby */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -161304,18 +161313,13 @@ var featureConfig = {
// cannot be found when interpreting results.
minimumVersion: void 0
},
["start_proxy_connection_checks" /* StartProxyConnectionChecks */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: void 0
},
["upload_overlay_db_to_api" /* UploadOverlayDbToApi */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
minimumVersion: void 0,
toolsFeature: "bundleSupportsOverlay" /* BundleSupportsOverlay */
},
["use_repository_properties" /* UseRepositoryProperties */]: {
["use_repository_properties_v2" /* UseRepositoryProperties */]: {
defaultValue: false,
envVar: "CODEQL_ACTION_USE_REPOSITORY_PROPERTIES",
minimumVersion: void 0
@@ -161327,12 +161331,17 @@ var featureConfig = {
}
};
// src/trap-caching.ts
// src/overlay/status.ts
var actionsCache2 = __toESM(require_cache6());
// src/trap-caching.ts
var actionsCache3 = __toESM(require_cache6());
// src/config-utils.ts
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 2e4;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1e6;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14e3;
var OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES = OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1e6;
var OVERLAY_MINIMUM_MEMORY_MB = 5 * 1024;
var OVERLAY_ANALYSIS_FEATURES = {
actions: "overlay_analysis_actions" /* OverlayAnalysisActions */,
@@ -161379,7 +161388,7 @@ var semver7 = __toESM(require_semver2());
var STREAMING_HIGH_WATERMARK_BYTES = 4 * 1024 * 1024;
// src/dependency-caching.ts
var actionsCache3 = __toESM(require_cache6());
var actionsCache4 = __toESM(require_cache6());
var glob = __toESM(require_glob2());
// src/artifact-scanner.ts
+3437 -3369
View File
File diff suppressed because it is too large Load Diff
+2071 -1367
View File
File diff suppressed because it is too large Load Diff
+10 -13
View File
@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "4.32.4",
"version": "4.32.5",
"private": true,
"description": "CodeQL action",
"scripts": {
@@ -45,14 +45,12 @@
"jsonschema": "1.4.1",
"long": "^5.3.2",
"node-forge": "^1.3.3",
"semver": "^7.7.3",
"semver": "^7.7.4",
"uuid": "^13.0.0"
},
"devDependencies": {
"@ava/typescript": "6.0.0",
"@eslint/compat": "^2.0.2",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@octokit/types": "^16.0.0",
"@types/archiver": "^7.0.0",
@@ -62,21 +60,20 @@
"@types/node-forge": "^1.3.14",
"@types/semver": "^7.7.1",
"@types/sinon": "^21.0.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.48.0",
"ava": "^6.4.1",
"esbuild": "^0.27.2",
"eslint": "^8.57.1",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"eslint-import-resolver-typescript": "^3.8.7",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-github": "^5.1.8",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-github": "^6.0.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^62.5.0",
"eslint-plugin-no-async-foreach": "^0.1.1",
"glob": "^11.1.0",
"nock": "^14.0.10",
"globals": "^16.5.0",
"nock": "^14.0.11",
"sinon": "^21.0.1",
"typescript": "^5.9.3"
"typescript": "^5.9.3",
"typescript-eslint": "^8.56.0"
},
"overrides": {
"@actions/tool-cache": {
-16
View File
@@ -1,16 +0,0 @@
name: "CCR"
description: "A standard analysis in CCR mode"
env:
CODEQL_ACTION_ANALYSIS_KEY: "dynamic/copilot-pull-request-reviewer/codeql-action-test"
steps:
- uses: ./../action/init
id: init
with:
languages: javascript
tools: ${{ steps.prepare-test.outputs.tools-url }}
- uses: ./../action/analyze
id: analysis
with:
upload-database: false
-9
View File
@@ -5,7 +5,6 @@ import {
fixCodeQualityCategory,
getPullRequestBranches,
isAnalyzingPullRequest,
isCCR,
isDefaultSetup,
isDynamicWorkflow,
} from "./actions-util";
@@ -257,16 +256,8 @@ test("isDynamicWorkflow() returns true if event name is `dynamic`", (t) => {
t.false(isDynamicWorkflow());
});
test("isCCR() returns true when expected", (t) => {
process.env.GITHUB_EVENT_NAME = "dynamic";
process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer";
t.assert(isCCR());
t.false(isDefaultSetup());
});
test("isDefaultSetup() returns true when expected", (t) => {
process.env.GITHUB_EVENT_NAME = "dynamic";
process.env[EnvVar.ANALYSIS_KEY] = "dynamic/github-code-scanning";
t.assert(isDefaultSetup());
t.false(isCCR());
});
+1 -10
View File
@@ -8,7 +8,6 @@ import * as io from "@actions/io";
import { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package";
import type { Config } from "./config-utils";
import { EnvVar } from "./environment";
import { Logger } from "./logging";
import {
doesDirectoryExist,
@@ -255,15 +254,7 @@ export function isDynamicWorkflow(): boolean {
/** Determines whether we are running in default setup. */
export function isDefaultSetup(): boolean {
return isDynamicWorkflow() && !isCCR();
}
/* The analysis key prefix used for CCR. */
const CCR_KEY_PREFIX = "dynamic/copilot-pull-request-reviewer";
/** Determines whether we are running in CCR. */
export function isCCR(): boolean {
return process.env[EnvVar.ANALYSIS_KEY]?.startsWith(CCR_KEY_PREFIX) || false;
return isDynamicWorkflow();
}
export function prettyPrintInvocation(cmd: string, args: string[]): string {
+5 -3
View File
@@ -30,10 +30,10 @@ import {
} from "./dependency-caching";
import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { Features } from "./feature-flags";
import { initFeatures } from "./feature-flags";
import { KnownLanguage } from "./languages";
import { getActionsLogger, Logger } from "./logging";
import { cleanupAndUploadOverlayBaseDatabaseToCache } from "./overlay-database-utils";
import { cleanupAndUploadOverlayBaseDatabaseToCache } from "./overlay";
import { getRepositoryNwo } from "./repository";
import * as statusReport from "./status-report";
import {
@@ -293,7 +293,7 @@ async function run(startedAt: Date) {
util.checkActionVersion(actionsUtil.getActionVersion(), gitHubVersion);
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
actionsUtil.getTemporaryDirectory(),
@@ -363,7 +363,9 @@ async function run(startedAt: Date) {
uploadResults = await postProcessAndUploadSarif(
logger,
config.tempDir,
features,
async () => codeql,
uploadKind,
checkoutPath,
outputDir,
+1 -1
View File
@@ -24,7 +24,7 @@ import { EnvVar } from "./environment";
import { FeatureEnablement, Feature } from "./feature-flags";
import { KnownLanguage, Language } from "./languages";
import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { OverlayDatabaseMode } from "./overlay";
import { DatabaseCreationTimings, EventReport } from "./status-report";
import { endTracingForCluster } from "./tracer-config";
import * as util from "./util";
+2 -2
View File
@@ -6,7 +6,7 @@ import { CodeQL, getCodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { DocUrl } from "./doc-url";
import { EnvVar } from "./environment";
import { Feature, featureConfig, Features } from "./feature-flags";
import { Feature, featureConfig, initFeatures } from "./feature-flags";
import { KnownLanguage, Language } from "./languages";
import { Logger } from "./logging";
import { getRepositoryNwo } from "./repository";
@@ -117,7 +117,7 @@ export async function setupCppAutobuild(codeql: CodeQL, logger: Logger) {
const featureName = "C++ automatic installation of dependencies";
const gitHubVersion = await getGitHubVersion();
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
+10 -2
View File
@@ -28,7 +28,7 @@ import {
OverlayDatabaseMode,
writeBaseDatabaseOidsFile,
writeOverlayChangesFile,
} from "./overlay-database-utils";
} from "./overlay";
import * as setupCodeql from "./setup-codeql";
import { ZstdAvailability } from "./tar";
import { ToolsDownloadStatusReport } from "./tools-download";
@@ -160,6 +160,7 @@ export interface CodeQL {
databasePath: string,
outputFilePath: string,
dbName: string,
includeDiagnostics: boolean,
alsoIncludeRelativePaths: string[],
): Promise<void>;
/**
@@ -912,15 +913,22 @@ async function getCodeQLForCmd(
databasePath: string,
outputFilePath: string,
databaseName: string,
includeDiagnostics: boolean,
alsoIncludeRelativePaths: string[],
): Promise<void> {
const includeDiagnosticsArgs = includeDiagnostics
? ["--include-diagnostics"]
: [];
const args = [
"database",
"bundle",
databasePath,
`--output=${outputFilePath}`,
`--name=${databaseName}`,
...getExtraOptionsFromEnv(["database", "bundle"]),
...includeDiagnosticsArgs,
...getExtraOptionsFromEnv(["database", "bundle"], {
ignoringOptions: includeDiagnosticsArgs,
}),
];
if (
await this.supportsFeature(ToolsFeature.BundleSupportsIncludeOption)
+118 -5
View File
@@ -18,10 +18,8 @@ import * as gitUtils from "./git-utils";
import { GitVersionInfo } from "./git-utils";
import { KnownLanguage, Language } from "./languages";
import { getRunnerLogger } from "./logging";
import {
CODEQL_OVERLAY_MINIMUM_VERSION,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { CODEQL_OVERLAY_MINIMUM_VERSION, OverlayDatabaseMode } from "./overlay";
import * as overlayStatus from "./overlay/status";
import { parseRepositoryNwo } from "./repository";
import {
setupTests,
@@ -984,6 +982,7 @@ interface OverlayDatabaseModeTestSetup {
codeScanningConfig: configUtils.UserConfig;
diskUsage: DiskUsage | undefined;
memoryFlagValue: number;
shouldSkipOverlayAnalysisDueToCachedStatus: boolean;
}
const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
@@ -1005,6 +1004,7 @@ const defaultOverlayDatabaseModeTestSetup: OverlayDatabaseModeTestSetup = {
numTotalBytes: 100_000_000_000,
},
memoryFlagValue: 6920,
shouldSkipOverlayAnalysisDueToCachedStatus: false,
};
const getOverlayDatabaseModeMacro = test.macro({
@@ -1015,6 +1015,7 @@ const getOverlayDatabaseModeMacro = test.macro({
expected: {
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
skippedDueToCachedStatus?: boolean;
},
) => {
return await withTmpDir(async (tempDir) => {
@@ -1039,6 +1040,10 @@ const getOverlayDatabaseModeMacro = test.macro({
sinon.stub(util, "checkDiskUsage").resolves(setup.diskUsage);
sinon
.stub(overlayStatus, "shouldSkipOverlayAnalysis")
.resolves(setup.shouldSkipOverlayAnalysisDueToCachedStatus);
// Mock feature flags
const features = createFeatures(setup.features);
@@ -1081,7 +1086,10 @@ const getOverlayDatabaseModeMacro = test.macro({
logger,
);
t.deepEqual(result, expected);
t.deepEqual(result, {
skippedDueToCachedStatus: false,
...expected,
});
} finally {
// Restore the original environment
process.env = originalEnv;
@@ -1261,6 +1269,71 @@ test(
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if runner disk space is below v2 limit and v2 resource checks enabled",
{
languages: [KnownLanguage.javascript],
features: [
Feature.OverlayAnalysis,
Feature.OverlayAnalysisCodeScanningJavascript,
Feature.OverlayAnalysisResourceChecksV2,
],
isDefaultBranch: true,
diskUsage: {
numAvailableBytes: 5_000_000_000,
numTotalBytes: 100_000_000_000,
},
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"Overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks enabled",
{
languages: [KnownLanguage.javascript],
features: [
Feature.OverlayAnalysis,
Feature.OverlayAnalysisCodeScanningJavascript,
Feature.OverlayAnalysisResourceChecksV2,
],
isDefaultBranch: true,
diskUsage: {
numAvailableBytes: 15_000_000_000,
numTotalBytes: 100_000_000_000,
},
},
{
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
useOverlayDatabaseCaching: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if runner disk space is between v2 and v1 limits and v2 resource checks not enabled",
{
languages: [KnownLanguage.javascript],
features: [
Feature.OverlayAnalysis,
Feature.OverlayAnalysisCodeScanningJavascript,
],
isDefaultBranch: true,
diskUsage: {
numAvailableBytes: 15_000_000_000,
numTotalBytes: 100_000_000_000,
},
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch if memory flag is too low",
@@ -1298,6 +1371,46 @@ test(
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when cached status indicates previous failure",
{
languages: [KnownLanguage.javascript],
features: [
Feature.OverlayAnalysis,
Feature.OverlayAnalysisJavascript,
Feature.OverlayAnalysisStatusCheck,
],
isDefaultBranch: true,
shouldSkipOverlayAnalysisDueToCachedStatus: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
skippedDueToCachedStatus: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay analysis on PR when cached status indicates previous failure",
{
languages: [KnownLanguage.javascript],
features: [
Feature.OverlayAnalysis,
Feature.OverlayAnalysisJavascript,
Feature.OverlayAnalysisStatusCheck,
],
isPullRequest: true,
shouldSkipOverlayAnalysisDueToCachedStatus: true,
},
{
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
skippedDueToCachedStatus: true,
},
);
test(
getOverlayDatabaseModeMacro,
"No overlay-base database on default branch when code-scanning feature enabled with disable-default-queries",
+110 -24
View File
@@ -7,7 +7,7 @@ import * as yaml from "js-yaml";
import {
getActionVersion,
isAnalyzingPullRequest,
isCCR,
isDynamicWorkflow,
} from "./actions-util";
import {
AnalysisConfig,
@@ -27,9 +27,11 @@ import {
} from "./config/db-config";
import {
addNoLanguageDiagnostic,
makeDiagnostic,
makeTelemetryDiagnostic,
} from "./diagnostics";
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
import { DocUrl } from "./doc-url";
import { EnvVar } from "./environment";
import * as errorMessages from "./error-messages";
import { Feature, FeatureEnablement } from "./feature-flags";
@@ -44,10 +46,8 @@ import {
} from "./git-utils";
import { KnownLanguage, Language } from "./languages";
import { Logger } from "./logging";
import {
CODEQL_OVERLAY_MINIMUM_VERSION,
OverlayDatabaseMode,
} from "./overlay-database-utils";
import { CODEQL_OVERLAY_MINIMUM_VERSION, OverlayDatabaseMode } from "./overlay";
import { shouldSkipOverlayAnalysis } from "./overlay/status";
import { RepositoryNwo } from "./repository";
import { ToolsFeature } from "./tools-features";
import { downloadTrapCaches } from "./trap-caching";
@@ -63,6 +63,7 @@ import {
getErrorMessage,
isInTestMode,
joinAtMost,
DiskUsage,
} from "./util";
export * from "./config/db-config";
@@ -78,6 +79,15 @@ const OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB = 20000;
const OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES =
OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_MB * 1_000_000;
/**
* The v2 minimum available disk space (in MB) required to perform overlay
* analysis. This is a lower threshold than the v1 limit, allowing overlay
* analysis to run on runners with less available disk space.
*/
const OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB = 14000;
const OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES =
OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_MB * 1_000_000;
/**
* The minimum memory (in MB) that must be available for CodeQL to perform overlay
* analysis. If CodeQL will be given less memory than this threshold, then the
@@ -675,21 +685,26 @@ async function isOverlayAnalysisFeatureEnabled(
* and the maximum memory CodeQL will be allowed to use.
*/
async function runnerSupportsOverlayAnalysis(
diskUsage: DiskUsage | undefined,
ramInput: string | undefined,
logger: Logger,
useV2ResourceChecks: boolean,
): Promise<boolean> {
const diskUsage = await checkDiskUsage(logger);
const minimumDiskSpaceBytes = useV2ResourceChecks
? OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_V2_BYTES
: OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES;
if (
diskUsage === undefined ||
diskUsage.numAvailableBytes < OVERLAY_MINIMUM_AVAILABLE_DISK_SPACE_BYTES
diskUsage.numAvailableBytes < minimumDiskSpaceBytes
) {
const diskSpaceMb =
diskUsage === undefined
? 0
: Math.round(diskUsage.numAvailableBytes / 1_000_000);
const minimumDiskSpaceMb = Math.round(minimumDiskSpaceBytes / 1_000_000);
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
`due to insufficient disk space (${diskSpaceMb} MB).`,
`due to insufficient disk space (${diskSpaceMb} MB, needed ${minimumDiskSpaceMb} MB).`,
);
return false;
}
@@ -698,7 +713,7 @@ async function runnerSupportsOverlayAnalysis(
if (memoryFlagValue < OVERLAY_MINIMUM_MEMORY_MB) {
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
`due to insufficient memory for CodeQL analysis (${memoryFlagValue} MB).`,
`due to insufficient memory for CodeQL analysis (${memoryFlagValue} MB, needed ${OVERLAY_MINIMUM_MEMORY_MB} MB).`,
);
return false;
}
@@ -740,9 +755,11 @@ export async function getOverlayDatabaseMode(
): Promise<{
overlayDatabaseMode: OverlayDatabaseMode;
useOverlayDatabaseCaching: boolean;
skippedDueToCachedStatus: boolean;
}> {
let overlayDatabaseMode = OverlayDatabaseMode.None;
let useOverlayDatabaseCaching = false;
let skippedDueToCachedStatus = false;
const modeEnv = process.env.CODEQL_OVERLAY_DATABASE_MODE;
// Any unrecognized CODEQL_OVERLAY_DATABASE_MODE value will be ignored and
@@ -769,11 +786,43 @@ export async function getOverlayDatabaseMode(
Feature.OverlayAnalysisSkipResourceChecks,
codeql,
));
const useV2ResourceChecks = await features.getValue(
Feature.OverlayAnalysisResourceChecksV2,
);
const checkOverlayStatus = await features.getValue(
Feature.OverlayAnalysisStatusCheck,
);
const diskUsage =
performResourceChecks || checkOverlayStatus
? await checkDiskUsage(logger)
: undefined;
if (
performResourceChecks &&
!(await runnerSupportsOverlayAnalysis(ramInput, logger))
!(await runnerSupportsOverlayAnalysis(
diskUsage,
ramInput,
logger,
useV2ResourceChecks,
))
) {
overlayDatabaseMode = OverlayDatabaseMode.None;
} else if (checkOverlayStatus && diskUsage === undefined) {
logger.warning(
`Unable to determine disk usage, therefore setting overlay database mode to ${OverlayDatabaseMode.None}.`,
);
overlayDatabaseMode = OverlayDatabaseMode.None;
} else if (
checkOverlayStatus &&
diskUsage &&
(await shouldSkipOverlayAnalysis(codeql, languages, diskUsage, logger))
) {
logger.info(
`Setting overlay database mode to ${OverlayDatabaseMode.None} ` +
"because overlay analysis previously failed with this combination of languages, " +
"disk space, and CodeQL version.",
);
overlayDatabaseMode = OverlayDatabaseMode.None;
skippedDueToCachedStatus = true;
} else if (isAnalyzingPullRequest()) {
overlayDatabaseMode = OverlayDatabaseMode.Overlay;
useOverlayDatabaseCaching = true;
@@ -794,6 +843,7 @@ export async function getOverlayDatabaseMode(
const nonOverlayAnalysis = {
overlayDatabaseMode: OverlayDatabaseMode.None,
useOverlayDatabaseCaching: false,
skippedDueToCachedStatus,
};
if (overlayDatabaseMode === OverlayDatabaseMode.None) {
@@ -858,6 +908,7 @@ export async function getOverlayDatabaseMode(
return {
overlayDatabaseMode,
useOverlayDatabaseCaching,
skippedDueToCachedStatus,
};
}
@@ -964,10 +1015,13 @@ export async function initConfig(
}
}
// If we are in CCR or the corresponding FF is enabled, try to determine
// If we are in a dynamic workflow or the corresponding FF is enabled, try to determine
// which files in the repository are marked as generated and add them to
// the `paths-ignore` configuration.
if ((await features.getValue(Feature.IgnoreGeneratedFiles)) && isCCR()) {
if (
(await features.getValue(Feature.IgnoreGeneratedFiles)) &&
isDynamicWorkflow()
) {
try {
const generatedFilesCheckStartedAt = performance.now();
const generatedFiles = await getGeneratedFiles(inputs.sourceRoot);
@@ -1001,18 +1055,21 @@ export async function initConfig(
// and queries, which in turn depends on the user config and the augmentation
// properties. So we need to calculate the overlay database mode after the
// rest of the config has been populated.
const { overlayDatabaseMode, useOverlayDatabaseCaching } =
await getOverlayDatabaseMode(
inputs.codeql,
inputs.features,
config.languages,
inputs.sourceRoot,
config.buildMode,
inputs.ramInput,
config.computedConfig,
gitVersion,
logger,
);
const {
overlayDatabaseMode,
useOverlayDatabaseCaching,
skippedDueToCachedStatus: overlaySkippedDueToCachedStatus,
} = await getOverlayDatabaseMode(
inputs.codeql,
inputs.features,
config.languages,
inputs.sourceRoot,
config.buildMode,
inputs.ramInput,
config.computedConfig,
gitVersion,
logger,
);
logger.info(
`Using overlay database mode: ${overlayDatabaseMode} ` +
`${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
@@ -1020,6 +1077,35 @@ export async function initConfig(
config.overlayDatabaseMode = overlayDatabaseMode;
config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
if (overlaySkippedDueToCachedStatus) {
addNoLanguageDiagnostic(
config,
makeDiagnostic(
"codeql-action/overlay-skipped-due-to-cached-status",
"Skipped improved incremental analysis because it failed previously with similar hardware resources",
{
attributes: {
languages: config.languages,
},
markdownMessage:
`Improved incremental analysis was skipped because it previously failed for this repository ` +
`with CodeQL version ${(await inputs.codeql.getVersion()).version} on a runner with similar hardware resources. ` +
"Improved incremental analysis may require a significant amount of disk space for some repositories. " +
"If you want to enable improved incremental analysis, increase the disk space available " +
"to the runner. If that doesn't help, contact GitHub Support for further assistance.\n\n" +
"Improved incremental analysis will be automatically retried when the next version of CodeQL is released. " +
`You can also manually trigger a retry by [removing](${DocUrl.DELETE_ACTIONS_CACHE_ENTRIES}) \`codeql-overlay-status-*\` entries from the Actions cache.`,
severity: "note",
visibility: {
cliSummaryTable: true,
statusPage: true,
telemetry: true,
},
},
),
);
}
if (
overlayDatabaseMode === OverlayDatabaseMode.Overlay ||
(await shouldPerformDiffInformedAnalysis(
+4 -2
View File
@@ -8,7 +8,7 @@ import { Config } from "./config-utils";
import { Feature, FeatureEnablement } from "./feature-flags";
import * as gitUtils from "./git-utils";
import { Logger, withGroupAsync } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { OverlayDatabaseMode } from "./overlay";
import { RepositoryNwo } from "./repository";
import * as util from "./util";
import { bundleDb, CleanupLevel, parseGitHubUrl } from "./util";
@@ -101,7 +101,9 @@ export async function cleanupAndUploadDatabases(
// Although we are uploading arbitrary file contents to the API, it's worth
// noting that it's the API's job to validate that the contents is acceptable.
// This API method is available to anyone with write access to the repo.
const bundledDb = await bundleDb(config, language, codeql, language);
const bundledDb = await bundleDb(config, language, codeql, language, {
includeDiagnostics: false,
});
bundledDbSize = fs.statSync(bundledDb).size;
const bundledDbReadStream = fs.createReadStream(bundledDb);
const commitOid = await gitUtils.getCommitOid(
+1
View File
@@ -429,6 +429,7 @@ async function createDatabaseBundleCli(
language,
codeql,
`${config.debugDatabaseName}-${language}`,
{ includeDiagnostics: true },
);
return databaseBundlePath;
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.24.1",
"cliVersion": "2.24.1",
"priorBundleVersion": "codeql-bundle-v2.24.0",
"priorCliVersion": "2.24.0"
"bundleVersion": "codeql-bundle-v2.24.2",
"cliVersion": "2.24.2",
"priorBundleVersion": "codeql-bundle-v2.24.1",
"priorCliVersion": "2.24.1"
}
+2 -2
View File
@@ -8,7 +8,7 @@ import {
shouldPerformDiffInformedAnalysis,
exportedForTesting,
} from "./diff-informed-analysis-utils";
import { Feature, Features } from "./feature-flags";
import { Feature, initFeatures } from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
@@ -63,7 +63,7 @@ const testShouldPerformDiffInformedAnalysis = test.macro({
delete process.env.CODEQL_ACTION_DIFF_INFORMED_QUERIES;
}
const features = new Features(
const features = initFeatures(
testCase.gitHubVersion,
parseRepositoryNwo("github/example"),
tmpDir,
+3 -2
View File
@@ -5,10 +5,11 @@
export enum DocUrl {
ASSIGNING_PERMISSIONS_TO_JOBS = "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs",
AUTOMATIC_BUILD_FAILED = "https://docs.github.com/en/code-security/code-scanning/troubleshooting-code-scanning/automatic-build-failed",
CODEQL_BUILD_MODES = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes",
DEFINE_ENV_VARIABLES = "https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow",
DELETE_ACTIONS_CACHE_ENTRIES = "https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manage-caches#deleting-cache-entries",
SCANNING_ON_PUSH = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#scanning-on-push",
SPECIFY_BUILD_STEPS_MANUALLY = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#about-specifying-build-steps-manually",
TRACK_CODE_SCANNING_ALERTS_ACROSS_RUNS = "https://docs.github.com/en/enterprise-cloud@latest/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning#providing-data-to-track-code-scanning-alerts-across-runs",
CODEQL_BUILD_MODES = "https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages#codeql-build-modes",
SYSTEM_REQUIREMENTS = "https://codeql.github.com/docs/codeql-overview/system-requirements/",
TRACK_CODE_SCANNING_ALERTS_ACROSS_RUNS = "https://docs.github.com/en/code-security/reference/code-scanning/sarif-support-for-code-scanning#data-for-preventing-duplicated-alerts",
}
+17 -112
View File
@@ -1,33 +1,31 @@
import * as fs from "fs";
import * as path from "path";
import test, { ExecutionContext } from "ava";
import test from "ava";
import * as defaults from "./defaults.json";
import { EnvVar } from "./environment";
import {
Feature,
featureConfig,
FeatureEnablement,
Features,
FEATURE_FLAGS_FILE_NAME,
FeatureConfig,
FeatureWithoutCLI,
} from "./feature-flags";
import { getRunnerLogger } from "./logging";
import { parseRepositoryNwo } from "./repository";
import {
setUpFeatureFlagTests,
getFeatureIncludingCodeQlIfRequired,
assertAllFeaturesUndefinedInApi,
assertAllFeaturesHaveDefaultValues,
} from "./feature-flags/testing-util";
import {
checkExpectedLogMessages,
getRecordingLogger,
initializeFeatures,
LoggedMessage,
mockCodeQLVersion,
mockFeatureFlagApiEndpoint,
setupActionsVars,
setupTests,
stubFeatureFlagApiEndpoint,
} from "./testing-utils";
import { ToolsFeature } from "./tools-features";
import * as util from "./util";
import { GitHubVariant, initializeEnvironment, withTmpDir } from "./util";
setupTests(test);
@@ -36,11 +34,9 @@ test.beforeEach(() => {
initializeEnvironment("1.2.3");
});
const testRepositoryNwo = parseRepositoryNwo("github/example");
test(`All features use default values if running against GHES`, async (t) => {
await withTmpDir(async (tmpDir) => {
const loggedMessages: LoggedMessage[] = [];
const loggedMessages = [];
const features = setUpFeatureFlagTests(
tmpDir,
getRecordingLogger(loggedMessages),
@@ -48,30 +44,9 @@ test(`All features use default values if running against GHES`, async (t) => {
);
await assertAllFeaturesHaveDefaultValues(t, features);
assertLoggedMessage(
t,
loggedMessages,
checkExpectedLogMessages(t, loggedMessages, [
"Not running against github.com. Using default values for all features.",
);
});
});
test(`All features use default values if running in CCR`, async (t) => {
await withTmpDir(async (tmpDir) => {
const loggedMessages: LoggedMessage[] = [];
const features = setUpFeatureFlagTests(
tmpDir,
getRecordingLogger(loggedMessages),
);
process.env[EnvVar.ANALYSIS_KEY] = "dynamic/copilot-pull-request-reviewer";
await assertAllFeaturesHaveDefaultValues(t, features);
assertLoggedMessage(
t,
loggedMessages,
"Feature flags are not supported in Copilot Code Review. Using default values for all features.",
);
]);
});
});
@@ -553,79 +528,9 @@ test("non-legacy feature flags should not start with codeql_action_", async (t)
}
});
async function assertAllFeaturesHaveDefaultValues(
t: ExecutionContext<unknown>,
features: FeatureEnablement,
) {
for (const feature of Object.values(Feature)) {
t.deepEqual(
await getFeatureIncludingCodeQlIfRequired(features, feature),
featureConfig[feature].defaultValue,
);
}
}
function assertLoggedMessage(
t: ExecutionContext<unknown>,
loggedMessages: LoggedMessage[],
expectedMessage: string,
) {
t.assert(
loggedMessages.find(
(v: LoggedMessage) => v.type === "debug" && v.message === expectedMessage,
) !== undefined,
);
}
function assertAllFeaturesUndefinedInApi(
t: ExecutionContext<unknown>,
loggedMessages: LoggedMessage[],
) {
for (const feature of Object.keys(featureConfig)) {
t.assert(
loggedMessages.find(
(v) =>
v.type === "debug" &&
(v.message as string).includes(feature) &&
(v.message as string).includes("undefined in API response"),
) !== undefined,
);
}
}
function setUpFeatureFlagTests(
tmpDir: string,
logger = getRunnerLogger(true),
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion,
): FeatureEnablement {
setupActionsVars(tmpDir, tmpDir);
return new Features(gitHubVersion, testRepositoryNwo, tmpDir, logger);
}
/**
* Returns an argument to pass to `getValue` that if required includes a CodeQL object meeting the
* minimum version or tool feature requirements specified by the feature.
*/
function getFeatureIncludingCodeQlIfRequired(
features: FeatureEnablement,
feature: Feature,
) {
const config = featureConfig[
feature
] satisfies FeatureConfig as FeatureConfig;
if (
config.minimumVersion === undefined &&
config.toolsFeature === undefined
) {
return features.getValue(feature as FeatureWithoutCLI);
}
return features.getValue(
feature,
mockCodeQLVersion(
"9.9.9",
Object.fromEntries(Object.values(ToolsFeature).map((v) => [v, true])),
),
);
}
test("initFeatures returns a `Features` instance by default", async (t) => {
await withTmpDir(async (tmpDir) => {
const features = setUpFeatureFlagTests(tmpDir);
t.is("Features", features.constructor.name);
});
});
+140 -71
View File
@@ -3,12 +3,11 @@ import * as path from "path";
import * as semver from "semver";
import { isCCR } from "./actions-util";
import { getApiClient } from "./api-client";
import type { CodeQL } from "./codeql";
import * as defaults from "./defaults.json";
import { Logger } from "./logging";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay-database-utils";
import { CODEQL_OVERLAY_MINIMUM_VERSION } from "./overlay";
import { RepositoryNwo } from "./repository";
import { ToolsFeature } from "./tools-features";
import * as util from "./util";
@@ -64,10 +63,13 @@ export enum Feature {
OverlayAnalysisCodeScanningSwift = "overlay_analysis_code_scanning_swift",
OverlayAnalysisCpp = "overlay_analysis_cpp",
OverlayAnalysisCsharp = "overlay_analysis_csharp",
OverlayAnalysisStatusCheck = "overlay_analysis_status_check",
OverlayAnalysisStatusSave = "overlay_analysis_status_save",
OverlayAnalysisGo = "overlay_analysis_go",
OverlayAnalysisJava = "overlay_analysis_java",
OverlayAnalysisJavascript = "overlay_analysis_javascript",
OverlayAnalysisPython = "overlay_analysis_python",
OverlayAnalysisResourceChecksV2 = "overlay_analysis_resource_checks_v2",
OverlayAnalysisRuby = "overlay_analysis_ruby",
OverlayAnalysisRust = "overlay_analysis_rust",
OverlayAnalysisSkipResourceChecks = "overlay_analysis_skip_resource_checks",
@@ -76,9 +78,8 @@ export enum Feature {
QaTelemetryEnabled = "qa_telemetry_enabled",
/** Note that this currently only disables baseline file coverage information. */
SkipFileCoverageOnPrs = "skip_file_coverage_on_prs",
StartProxyConnectionChecks = "start_proxy_connection_checks",
UploadOverlayDbToApi = "upload_overlay_db_to_api",
UseRepositoryProperties = "use_repository_properties",
UseRepositoryProperties = "use_repository_properties_v2",
ValidateDbConfig = "validate_db_config",
}
@@ -256,6 +257,16 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_CSHARP",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisStatusCheck]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_CHECK",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisStatusSave]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_STATUS_SAVE",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisGo]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_GO",
@@ -276,6 +287,11 @@ export const featureConfig = {
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_PYTHON",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisResourceChecksV2]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RESOURCE_CHECKS_V2",
minimumVersion: undefined,
},
[Feature.OverlayAnalysisRuby]: {
defaultValue: false,
envVar: "CODEQL_ACTION_OVERLAY_ANALYSIS_RUBY",
@@ -317,11 +333,6 @@ export const featureConfig = {
// cannot be found when interpreting results.
minimumVersion: undefined,
},
[Feature.StartProxyConnectionChecks]: {
defaultValue: false,
envVar: "CODEQL_ACTION_START_PROXY_CONNECTION_CHECKS",
minimumVersion: undefined,
},
[Feature.UploadOverlayDbToApi]: {
defaultValue: false,
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
@@ -373,51 +384,60 @@ type GitHubFeatureFlagsApiResponse = Partial<Record<Feature, boolean>>;
export const FEATURE_FLAGS_FILE_NAME = "cached-feature-flags.json";
/**
* Determines the enablement status of a number of features.
* If feature enablement is not able to be determined locally, a request to the
* GitHub API is made to determine the enablement status.
* Determines the enablement status of a number of features locally without
* consulting the GitHub API.
*/
export class Features implements FeatureEnablement {
private gitHubFeatureFlags: GitHubFeatureFlags;
constructor(
gitHubVersion: util.GitHubVersion,
repositoryNwo: RepositoryNwo,
tempDir: string,
private readonly logger: Logger,
) {
this.gitHubFeatureFlags = new GitHubFeatureFlags(
gitHubVersion,
repositoryNwo,
path.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger,
);
}
class OfflineFeatures implements FeatureEnablement {
constructor(protected readonly logger: Logger) {}
async getDefaultCliVersion(
variant: util.GitHubVariant,
_variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> {
return await this.gitHubFeatureFlags.getDefaultCliVersion(variant);
return {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
}
/**
* Gets the `FeatureConfig` for `feature`.
*/
getFeatureConfig(feature: Feature): FeatureConfig {
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
// check that the required properties exist using `satisfies`.
return featureConfig[feature] satisfies FeatureConfig as FeatureConfig;
}
/**
* Determines whether `feature` is enabled without consulting the GitHub API.
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, the
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature: Feature, codeql?: CodeQL): Promise<boolean> {
// Narrow the type to FeatureConfig to avoid type errors. To avoid unsafe use of `as`, we
// check that the required properties exist using `satisfies`.
const config = featureConfig[
feature
] satisfies FeatureConfig as FeatureConfig;
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== undefined) {
return offlineValue;
}
return this.getDefaultValue(feature);
}
/**
* Determines whether `feature` is enabled using the CLI and environment variables.
*/
protected async getOfflineValue(
feature: Feature,
codeql?: CodeQL,
): Promise<boolean | undefined> {
const config = this.getFeatureConfig(feature);
if (!codeql && config.minimumVersion) {
throw new Error(
@@ -483,6 +503,68 @@ export class Features implements FeatureEnablement {
return true;
}
return undefined;
}
/** Gets the default value of `feature`. */
protected async getDefaultValue(feature: Feature): Promise<boolean> {
const config = this.getFeatureConfig(feature);
const defaultValue = config.defaultValue;
this.logger.debug(
`Feature ${feature} is ${
defaultValue ? "enabled" : "disabled"
} due to its default value.`,
);
return defaultValue;
}
}
/**
* Determines the enablement status of a number of features.
* If feature enablement is not able to be determined locally, a request to the
* GitHub API is made to determine the enablement status.
*/
class Features extends OfflineFeatures {
private gitHubFeatureFlags: GitHubFeatureFlags;
constructor(repositoryNwo: RepositoryNwo, tempDir: string, logger: Logger) {
super(logger);
this.gitHubFeatureFlags = new GitHubFeatureFlags(
repositoryNwo,
path.join(tempDir, FEATURE_FLAGS_FILE_NAME),
logger,
);
}
async getDefaultCliVersion(
variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> {
if (supportsFeatureFlags(variant)) {
return await this.gitHubFeatureFlags.getDefaultCliVersionFromFlags();
}
return super.getDefaultCliVersion(variant);
}
/**
*
* @param feature The feature to check.
* @param codeql An optional CodeQL object. If provided, and a `minimumVersion` is specified for the
* feature, the version of the CodeQL CLI will be checked against the minimum version.
* If the version is less than the minimum version, the feature will be considered
* disabled. If not provided, and a `minimumVersion` is specified for the feature, then
* this function will throw.
* @returns true if the feature is enabled, false otherwise.
*
* @throws if a `minimumVersion` is specified for the feature, and `codeql` is not provided.
*/
async getValue(feature: Feature, codeql?: CodeQL): Promise<boolean> {
// Check whether the feature is enabled locally.
const offlineValue = await this.getOfflineValue(feature, codeql);
if (offlineValue !== undefined) {
return offlineValue;
}
// Ask the GitHub API if the feature is enabled.
const apiValue = await this.gitHubFeatureFlags.getValue(feature);
if (apiValue !== undefined) {
@@ -494,13 +576,8 @@ export class Features implements FeatureEnablement {
return apiValue;
}
const defaultValue = config.defaultValue;
this.logger.debug(
`Feature ${feature} is ${
defaultValue ? "enabled" : "disabled"
} due to its default value.`,
);
return defaultValue;
// Return the default value.
return this.getDefaultValue(feature);
}
}
@@ -512,7 +589,6 @@ class GitHubFeatureFlags {
private hasAccessedRemoteFeatureFlags: boolean;
constructor(
private readonly gitHubVersion: util.GitHubVersion,
private readonly repositoryNwo: RepositoryNwo,
private readonly featureFlagsFile: string,
private readonly logger: Logger,
@@ -543,18 +619,6 @@ class GitHubFeatureFlags {
return version;
}
async getDefaultCliVersion(
variant: util.GitHubVariant,
): Promise<CodeQLDefaultVersionInfo> {
if (supportsFeatureFlags(variant)) {
return await this.getDefaultCliVersionFromFlags();
}
return {
cliVersion: defaults.cliVersion,
tagName: defaults.bundleVersion,
};
}
async getDefaultCliVersionFromFlags(): Promise<CodeQLDefaultVersionInfo> {
const response = await this.getAllFeatures();
@@ -680,21 +744,6 @@ class GitHubFeatureFlags {
}
private async loadApiResponse(): Promise<GitHubFeatureFlagsApiResponse> {
// Do nothing when not running against github.com
if (!supportsFeatureFlags(this.gitHubVersion.type)) {
this.logger.debug(
"Not running against github.com. Using default values for all features.",
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
if (isCCR()) {
this.logger.debug(
"Feature flags are not supported in Copilot Code Review. Using default values for all features.",
);
this.hasAccessedRemoteFeatureFlags = false;
return {};
}
try {
const featuresToRequest = Object.entries(featureConfig)
.filter(
@@ -764,3 +813,23 @@ function supportsFeatureFlags(githubVariant: util.GitHubVariant): boolean {
githubVariant === util.GitHubVariant.GHEC_DR
);
}
/**
* Initialises an instance of a `FeatureEnablement` implementation. The implementation used
* is determined by the environment we are running in.
*/
export function initFeatures(
gitHubVersion: util.GitHubVersion,
repositoryNwo: RepositoryNwo,
tempDir: string,
logger: Logger,
): FeatureEnablement {
if (!supportsFeatureFlags(gitHubVersion.type)) {
logger.debug(
"Not running against github.com. Using default values for all features.",
);
return new OfflineFeatures(logger);
} else {
return new Features(repositoryNwo, tempDir, logger);
}
}
@@ -0,0 +1,43 @@
import test from "ava";
import * as sinon from "sinon";
import * as apiClient from "../api-client";
import {
checkExpectedLogMessages,
getRecordingLogger,
LoggedMessage,
setupTests,
} from "../testing-utils";
import { GitHubVariant, initializeEnvironment, withTmpDir } from "../util";
import {
assertAllFeaturesHaveDefaultValues,
setUpFeatureFlagTests,
} from "./testing-util";
setupTests(test);
test.beforeEach(() => {
initializeEnvironment("1.2.3");
});
test("OfflineFeatures makes no API requests", async (t) => {
await withTmpDir(async (tmpDir) => {
const loggedMessages: LoggedMessage[] = [];
const logger = getRecordingLogger(loggedMessages);
const features = setUpFeatureFlagTests(tmpDir, logger, {
type: GitHubVariant.GHES,
version: "3.0.0",
});
t.is("OfflineFeatures", features.constructor.name);
sinon
.stub(apiClient, "getApiClient")
.throws(new Error("Should not have called getApiClient"));
await assertAllFeaturesHaveDefaultValues(t, features);
checkExpectedLogMessages(t, loggedMessages, [
"Not running against github.com. Using default values for all features.",
]);
});
});
+87
View File
@@ -0,0 +1,87 @@
import { type ExecutionContext } from "ava";
import {
Feature,
featureConfig,
FeatureConfig,
FeatureEnablement,
FeatureWithoutCLI,
initFeatures,
} from "../feature-flags";
import { getRunnerLogger } from "../logging";
import { parseRepositoryNwo } from "../repository";
import {
LoggedMessage,
mockCodeQLVersion,
setupActionsVars,
} from "../testing-utils";
import { ToolsFeature } from "../tools-features";
import { GitHubVariant } from "../util";
import * as util from "../util";
const testRepositoryNwo = parseRepositoryNwo("github/example");
export async function assertAllFeaturesHaveDefaultValues(
t: ExecutionContext<unknown>,
features: FeatureEnablement,
) {
for (const feature of Object.values(Feature)) {
t.deepEqual(
await getFeatureIncludingCodeQlIfRequired(features, feature),
featureConfig[feature].defaultValue,
);
}
}
export function assertAllFeaturesUndefinedInApi(
t: ExecutionContext<unknown>,
loggedMessages: LoggedMessage[],
) {
for (const feature of Object.keys(featureConfig)) {
t.assert(
loggedMessages.find(
(v) =>
v.type === "debug" &&
(v.message as string).includes(feature) &&
(v.message as string).includes("undefined in API response"),
) !== undefined,
);
}
}
export function setUpFeatureFlagTests(
tmpDir: string,
logger = getRunnerLogger(true),
gitHubVersion = { type: GitHubVariant.DOTCOM } as util.GitHubVersion,
): FeatureEnablement {
setupActionsVars(tmpDir, tmpDir);
return initFeatures(gitHubVersion, testRepositoryNwo, tmpDir, logger);
}
/**
* Returns an argument to pass to `getValue` that if required includes a CodeQL object meeting the
* minimum version or tool feature requirements specified by the feature.
*/
export function getFeatureIncludingCodeQlIfRequired(
features: FeatureEnablement,
feature: Feature,
) {
const config = featureConfig[
feature
] satisfies FeatureConfig as FeatureConfig;
if (
config.minimumVersion === undefined &&
config.toolsFeature === undefined
) {
return features.getValue(feature as FeatureWithoutCLI);
}
return features.getValue(
feature,
mockCodeQLVersion(
"9.9.9",
Object.fromEntries(Object.values(ToolsFeature).map((v) => [v, true])),
),
);
}
+182 -2
View File
@@ -5,9 +5,12 @@ import * as actionsUtil from "./actions-util";
import { AnalysisKind } from "./analyses";
import * as codeql from "./codeql";
import * as configUtils from "./config-utils";
import { EnvVar } from "./environment";
import { Feature } from "./feature-flags";
import * as initActionPostHelper from "./init-action-post-helper";
import { getRunnerLogger } from "./logging";
import { OverlayDatabaseMode } from "./overlay";
import * as overlayStatus from "./overlay/status";
import { parseRepositoryNwo } from "./repository";
import {
createFeatures,
@@ -19,9 +22,11 @@ import * as uploadLib from "./upload-lib";
import * as util from "./util";
import * as workflow from "./workflow";
const NUM_BYTES_PER_GIB = 1024 * 1024 * 1024;
setupTests(test);
test("post: init action with debug mode off", async (t) => {
test("init-post action with debug mode off", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
@@ -55,7 +60,7 @@ test("post: init action with debug mode off", async (t) => {
});
});
test("post: init action with debug mode on", async (t) => {
test("init-post action with debug mode on", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
@@ -308,6 +313,179 @@ test("not uploading failed SARIF when `code-scanning` is not an enabled analysis
);
});
test("saves overlay status when overlay-base analysis did not complete successfully", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
// Ensure analyze did not complete successfully.
delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY];
const diskUsage: util.DiskUsage = {
numAvailableBytes: 100 * NUM_BYTES_PER_GIB,
numTotalBytes: 200 * NUM_BYTES_PER_GIB,
};
sinon.stub(util, "checkDiskUsage").resolves(diskUsage);
const saveOverlayStatusStub = sinon
.stub(overlayStatus, "saveOverlayStatus")
.resolves(true);
const stubCodeQL = codeql.createStubCodeQL({});
await initActionPostHelper.run(
sinon.spy(),
sinon.spy(),
stubCodeQL,
createTestConfig({
debugMode: false,
languages: ["javascript"],
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
}),
parseRepositoryNwo("github/codeql-action"),
createFeatures([Feature.OverlayAnalysisStatusSave]),
getRunnerLogger(true),
);
t.true(
saveOverlayStatusStub.calledOnce,
"saveOverlayStatus should be called exactly once",
);
t.deepEqual(
saveOverlayStatusStub.firstCall.args[0],
stubCodeQL,
"first arg should be the CodeQL instance",
);
t.deepEqual(
saveOverlayStatusStub.firstCall.args[1],
["javascript"],
"second arg should be the languages",
);
t.deepEqual(
saveOverlayStatusStub.firstCall.args[2],
diskUsage,
"third arg should be the disk usage",
);
t.deepEqual(
saveOverlayStatusStub.firstCall.args[3],
{
attemptedToBuildOverlayBaseDatabase: true,
builtOverlayBaseDatabase: false,
},
"fourth arg should be the overlay status recording an unsuccessful build attempt",
);
});
});
test("does not save overlay status when OverlayAnalysisStatusSave feature flag is disabled", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
// Ensure analyze did not complete successfully.
delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY];
sinon.stub(util, "checkDiskUsage").resolves({
numAvailableBytes: 100 * NUM_BYTES_PER_GIB,
numTotalBytes: 200 * NUM_BYTES_PER_GIB,
});
const saveOverlayStatusStub = sinon
.stub(overlayStatus, "saveOverlayStatus")
.resolves(true);
await initActionPostHelper.run(
sinon.spy(),
sinon.spy(),
codeql.createStubCodeQL({}),
createTestConfig({
debugMode: false,
languages: ["javascript"],
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
}),
parseRepositoryNwo("github/codeql-action"),
createFeatures([]),
getRunnerLogger(true),
);
t.true(
saveOverlayStatusStub.notCalled,
"saveOverlayStatus should not be called when OverlayAnalysisStatusSave feature flag is disabled",
);
});
});
test("does not save overlay status when build successful", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
// Mark analyze as having completed successfully.
process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] = "true";
sinon.stub(util, "checkDiskUsage").resolves({
numAvailableBytes: 100 * NUM_BYTES_PER_GIB,
numTotalBytes: 200 * NUM_BYTES_PER_GIB,
});
const saveOverlayStatusStub = sinon
.stub(overlayStatus, "saveOverlayStatus")
.resolves(true);
await initActionPostHelper.run(
sinon.spy(),
sinon.spy(),
codeql.createStubCodeQL({}),
createTestConfig({
debugMode: false,
languages: ["javascript"],
overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
}),
parseRepositoryNwo("github/codeql-action"),
createFeatures([Feature.OverlayAnalysisStatusSave]),
getRunnerLogger(true),
);
t.true(
saveOverlayStatusStub.notCalled,
"saveOverlayStatus should not be called when build completed successfully",
);
});
});
test("does not save overlay status when overlay not enabled", async (t) => {
return await util.withTmpDir(async (tmpDir) => {
process.env["GITHUB_REPOSITORY"] = "github/codeql-action-fake-repository";
process.env["RUNNER_TEMP"] = tmpDir;
delete process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY];
sinon.stub(util, "checkDiskUsage").resolves({
numAvailableBytes: 100 * NUM_BYTES_PER_GIB,
numTotalBytes: 200 * NUM_BYTES_PER_GIB,
});
const saveOverlayStatusStub = sinon
.stub(overlayStatus, "saveOverlayStatus")
.resolves(true);
await initActionPostHelper.run(
sinon.spy(),
sinon.spy(),
codeql.createStubCodeQL({}),
createTestConfig({
debugMode: false,
languages: ["javascript"],
overlayDatabaseMode: OverlayDatabaseMode.None,
}),
parseRepositoryNwo("github/codeql-action"),
createFeatures([]),
getRunnerLogger(true),
);
t.true(
saveOverlayStatusStub.notCalled,
"saveOverlayStatus should not be called when overlay is not enabled",
);
});
});
function createTestWorkflow(
steps: workflow.WorkflowJobStep[],
): workflow.Workflow {
@@ -424,6 +602,8 @@ async function testFailedSarifUpload(
}
t.true(
uploadFiles.calledOnceWith(
sinon.match.string,
codeqlObject,
sinon.match.string,
sinon.match.string,
category,
+69
View File
@@ -11,10 +11,13 @@ import * as dependencyCaching from "./dependency-caching";
import { EnvVar } from "./environment";
import { Feature, FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging";
import { OverlayDatabaseMode } from "./overlay";
import { OverlayStatus, saveOverlayStatus } from "./overlay/status";
import { RepositoryNwo, getRepositoryNwo } from "./repository";
import { JobStatus } from "./status-report";
import * as uploadLib from "./upload-lib";
import {
checkDiskUsage,
delay,
getErrorMessage,
getRequiredEnvParam,
@@ -104,6 +107,8 @@ async function maybeUploadFailedSarif(
logger.info(`Uploading failed SARIF file ${sarifFile}`);
const uploadResult = await uploadLib.uploadFiles(
config.tempDir,
codeql,
sarifFile,
checkoutPath,
category,
@@ -169,6 +174,8 @@ export async function run(
features: FeatureEnablement,
logger: Logger,
) {
await recordOverlayStatus(codeql, config, features, logger);
const uploadFailedSarifResult = await tryUploadSarifIfRunFailed(
config,
repositoryNwo,
@@ -246,6 +253,68 @@ export async function run(
return uploadFailedSarifResult;
}
/**
* If overlay base database creation was attempted but the analysis did not complete
* successfully, save the failure status to the Actions cache so that subsequent runs
* can skip overlay analysis until something changes (e.g. a new CodeQL version).
*/
async function recordOverlayStatus(
codeql: CodeQL,
config: Config,
features: FeatureEnablement,
logger: Logger,
) {
if (
config.overlayDatabaseMode !== OverlayDatabaseMode.OverlayBase ||
process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true" ||
!(await features.getValue(Feature.OverlayAnalysisStatusSave))
) {
return;
}
const overlayStatus: OverlayStatus = {
attemptedToBuildOverlayBaseDatabase: true,
builtOverlayBaseDatabase: false,
};
const diskUsage = await checkDiskUsage(logger);
if (diskUsage === undefined) {
logger.warning(
"Unable to save overlay status to the Actions cache because the available disk space could not be determined.",
);
return;
}
const saved = await saveOverlayStatus(
codeql,
config.languages,
diskUsage,
overlayStatus,
logger,
);
const blurb =
"This job attempted to run with improved incremental analysis but it did not complete successfully. " +
"This may have been due to disk space constraints: using improved incremental analysis can " +
"require a significant amount of disk space for some repositories.";
if (saved) {
logger.error(
`${blurb} ` +
"This failure has been recorded in the Actions cache, so the next CodeQL analysis will run " +
"without improved incremental analysis. If you want to enable improved incremental analysis, " +
"increase the disk space available to the runner. " +
"If that doesn't help, contact GitHub Support for further assistance.",
);
} else {
logger.error(
`${blurb} ` +
"The attempt to save this failure status to the Actions cache failed. The Action will attempt to " +
"run with improved incremental analysis again.",
);
}
}
async function removeUploadedSarif(
uploadFailedSarifResult: UploadFailedSarifResult,
logger: Logger,
+2 -2
View File
@@ -21,7 +21,7 @@ import {
getDependencyCacheUsage,
} from "./dependency-caching";
import { EnvVar } from "./environment";
import { Features } from "./feature-flags";
import { initFeatures } from "./feature-flags";
import * as gitUtils from "./git-utils";
import * as initActionPostHelper from "./init-action-post-helper";
import { getActionsLogger } from "./logging";
@@ -62,7 +62,7 @@ async function run(startedAt: Date) {
checkGitHubVersionInRange(gitHubVersion, logger);
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
+4 -4
View File
@@ -38,7 +38,7 @@ import {
makeTelemetryDiagnostic,
} from "./diagnostics";
import { EnvVar } from "./environment";
import { Feature, FeatureEnablement, Features } from "./feature-flags";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import {
loadPropertiesFromApi,
RepositoryProperties,
@@ -58,7 +58,7 @@ import {
downloadOverlayBaseDatabaseFromCache,
OverlayBaseDatabaseDownloadStats,
OverlayDatabaseMode,
} from "./overlay-database-utils";
} from "./overlay";
import { getRepositoryNwo, RepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
@@ -211,7 +211,7 @@ async function run(startedAt: Date) {
let config: configUtils.Config | undefined;
let configFile: string | undefined;
let codeql: CodeQL;
let features: Features;
let features: FeatureEnablement;
let sourceRoot: string;
let toolsDownloadStatusReport: ToolsDownloadStatusReport | undefined;
let toolsFeatureFlagsValid: boolean | undefined;
@@ -238,7 +238,7 @@ async function run(startedAt: Date) {
const repositoryNwo = getRepositoryNwo();
features = new Features(
features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
@@ -5,12 +5,20 @@ import * as actionsCache from "@actions/cache";
import test from "ava";
import * as sinon from "sinon";
import * as actionsUtil from "./actions-util";
import * as apiClient from "./api-client";
import { ResolveDatabaseOutput } from "./codeql";
import * as gitUtils from "./git-utils";
import { KnownLanguage } from "./languages";
import { getRunnerLogger } from "./logging";
import * as actionsUtil from "../actions-util";
import * as apiClient from "../api-client";
import { ResolveDatabaseOutput } from "../codeql";
import * as gitUtils from "../git-utils";
import { KnownLanguage } from "../languages";
import { getRunnerLogger } from "../logging";
import {
createTestConfig,
mockCodeQLVersion,
setupTests,
} from "../testing-utils";
import * as utils from "../util";
import { withTmpDir } from "../util";
import {
downloadOverlayBaseDatabaseFromCache,
getCacheRestoreKeyPrefix,
@@ -18,14 +26,7 @@ import {
OverlayDatabaseMode,
writeBaseDatabaseOidsFile,
writeOverlayChangesFile,
} from "./overlay-database-utils";
import {
createTestConfig,
mockCodeQLVersion,
setupTests,
} from "./testing-utils";
import * as utils from "./util";
import { withTmpDir } from "./util";
} from ".";
setupTests(test);
@@ -8,13 +8,13 @@ import {
getTemporaryDirectory,
getWorkflowRunAttempt,
getWorkflowRunID,
} from "./actions-util";
import { getAutomationID } from "./api-client";
import { createCacheKeyHash } from "./caching-utils";
import { type CodeQL } from "./codeql";
import { type Config } from "./config-utils";
import { getCommitOid, getFileOidsUnderPath } from "./git-utils";
import { Logger, withGroupAsync } from "./logging";
} from "../actions-util";
import { getAutomationID } from "../api-client";
import { createCacheKeyHash } from "../caching-utils";
import { type CodeQL } from "../codeql";
import { type Config } from "../config-utils";
import { getCommitOid, getFileOidsUnderPath } from "../git-utils";
import { Logger, withGroupAsync } from "../logging";
import {
CleanupLevel,
getBaseDatabaseOidsFilePath,
@@ -23,7 +23,7 @@ import {
isInTestMode,
tryGetFolderBytes,
waitForResultWithTimeLimit,
} from "./util";
} from "../util";
export enum OverlayDatabaseMode {
Overlay = "overlay",
+172
View File
@@ -0,0 +1,172 @@
import * as fs from "fs";
import * as path from "path";
import * as actionsCache from "@actions/cache";
import test from "ava";
import * as sinon from "sinon";
import {
getRecordingLogger,
LoggedMessage,
mockCodeQLVersion,
setupTests,
} from "../testing-utils";
import { DiskUsage, withTmpDir } from "../util";
import { getCacheKey, shouldSkipOverlayAnalysis } from "./status";
setupTests(test);
function makeDiskUsage(totalGiB: number): DiskUsage {
return {
numTotalBytes: totalGiB * 1024 * 1024 * 1024,
numAvailableBytes: 0,
};
}
test("getCacheKey incorporates language, CodeQL version, and disk space", async (t) => {
const codeql = mockCodeQLVersion("2.20.0");
t.is(
await getCacheKey(codeql, ["javascript"], makeDiskUsage(50)),
"codeql-overlay-status-javascript-2.20.0-runner-50GB",
);
t.is(
await getCacheKey(codeql, ["python"], makeDiskUsage(50)),
"codeql-overlay-status-python-2.20.0-runner-50GB",
);
t.is(
await getCacheKey(
mockCodeQLVersion("2.21.0"),
["javascript"],
makeDiskUsage(50),
),
"codeql-overlay-status-javascript-2.21.0-runner-50GB",
);
t.is(
await getCacheKey(codeql, ["javascript"], makeDiskUsage(100)),
"codeql-overlay-status-javascript-2.20.0-runner-100GB",
);
});
test("getCacheKey sorts and joins multiple languages", async (t) => {
const codeql = mockCodeQLVersion("2.20.0");
t.is(
await getCacheKey(codeql, ["python", "javascript"], makeDiskUsage(50)),
"codeql-overlay-status-javascript+python-2.20.0-runner-50GB",
);
t.is(
await getCacheKey(codeql, ["javascript", "python"], makeDiskUsage(50)),
"codeql-overlay-status-javascript+python-2.20.0-runner-50GB",
);
});
test("getCacheKey rounds disk space down to nearest 10 GiB", async (t) => {
const codeql = mockCodeQLVersion("2.20.0");
t.is(
await getCacheKey(codeql, ["javascript"], makeDiskUsage(14)),
"codeql-overlay-status-javascript-2.20.0-runner-10GB",
);
t.is(
await getCacheKey(codeql, ["javascript"], makeDiskUsage(19)),
"codeql-overlay-status-javascript-2.20.0-runner-10GB",
);
});
test("shouldSkipOverlayAnalysis returns false when no cached status exists", async (t) => {
await withTmpDir(async (tmpDir) => {
process.env["RUNNER_TEMP"] = tmpDir;
const codeql = mockCodeQLVersion("2.20.0");
const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages);
sinon.stub(actionsCache, "restoreCache").resolves(undefined);
const result = await shouldSkipOverlayAnalysis(
codeql,
["javascript"],
makeDiskUsage(50),
logger,
);
t.false(result);
t.true(
messages.some(
(m) =>
m.type === "debug" &&
typeof m.message === "string" &&
m.message.includes("No overlay status found in Actions cache."),
),
);
});
});
test("shouldSkipOverlayAnalysis returns true when cached status indicates failed build", async (t) => {
await withTmpDir(async (tmpDir) => {
process.env["RUNNER_TEMP"] = tmpDir;
const codeql = mockCodeQLVersion("2.20.0");
const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages);
const status = {
attemptedToBuildOverlayBaseDatabase: true,
builtOverlayBaseDatabase: false,
};
// Stub restoreCache to write the status file and return a key
sinon.stub(actionsCache, "restoreCache").callsFake(async (paths) => {
const statusFile = paths[0];
await fs.promises.mkdir(path.dirname(statusFile), { recursive: true });
await fs.promises.writeFile(statusFile, JSON.stringify(status));
return "found-key";
});
const result = await shouldSkipOverlayAnalysis(
codeql,
["javascript"],
makeDiskUsage(50),
logger,
);
t.true(result);
});
});
test("shouldSkipOverlayAnalysis returns false when cached status indicates successful build", async (t) => {
await withTmpDir(async (tmpDir) => {
process.env["RUNNER_TEMP"] = tmpDir;
const codeql = mockCodeQLVersion("2.20.0");
const messages: LoggedMessage[] = [];
const logger = getRecordingLogger(messages);
const status = {
attemptedToBuildOverlayBaseDatabase: true,
builtOverlayBaseDatabase: true,
};
sinon.stub(actionsCache, "restoreCache").callsFake(async (paths) => {
const statusFile = paths[0];
await fs.promises.mkdir(path.dirname(statusFile), { recursive: true });
await fs.promises.writeFile(statusFile, JSON.stringify(status));
return "found-key";
});
const result = await shouldSkipOverlayAnalysis(
codeql,
["javascript"],
makeDiskUsage(50),
logger,
);
t.false(result);
t.true(
messages.some(
(m) =>
m.type === "debug" &&
typeof m.message === "string" &&
m.message.includes(
"Cached overlay status does not indicate a previous unsuccessful attempt",
),
),
);
});
});
+190
View File
@@ -0,0 +1,190 @@
/*
* We perform enablement checks for overlay analysis to avoid using it on runners that are too small
* to support it. However these checks cannot avoid every potential issue without being overly
* conservative. Therefore, if our enablement checks enable overlay analysis for a runner that is
* too small, we want to remember that, so that we will not try to use overlay analysis until
* something changes (e.g. a larger runner is provisioned, or a new CodeQL version is released).
*
* We use the Actions cache as a lightweight way of providing this functionality.
*/
import * as fs from "fs";
import * as path from "path";
import * as actionsCache from "@actions/cache";
import { getTemporaryDirectory } from "../actions-util";
import { type CodeQL } from "../codeql";
import { Logger } from "../logging";
import {
DiskUsage,
getErrorMessage,
waitForResultWithTimeLimit,
} from "../util";
/** The maximum time to wait for a cache operation to complete. */
const MAX_CACHE_OPERATION_MS = 30_000;
/** File name for the serialized overlay status. */
const STATUS_FILE_NAME = "overlay-status.json";
/** Path to the local overlay status file. */
function getStatusFilePath(languages: string[]): string {
return path.join(
getTemporaryDirectory(),
"overlay-status",
[...languages].sort().join("+"),
STATUS_FILE_NAME,
);
}
/** Status of an overlay analysis for a group of languages. */
export interface OverlayStatus {
/** Whether the job attempted to build an overlay base database. */
attemptedToBuildOverlayBaseDatabase: boolean;
/** Whether the job successfully built an overlay base database. */
builtOverlayBaseDatabase: boolean;
}
/**
* Whether overlay analysis should be skipped, based on the cached status for the given languages and disk usage.
*/
export async function shouldSkipOverlayAnalysis(
codeql: CodeQL,
languages: string[],
diskUsage: DiskUsage,
logger: Logger,
): Promise<boolean> {
const status = await getOverlayStatus(codeql, languages, diskUsage, logger);
if (status === undefined) {
return false;
}
if (
status.attemptedToBuildOverlayBaseDatabase &&
!status.builtOverlayBaseDatabase
) {
logger.debug(
"Cached overlay status indicates that building an overlay base database was unsuccessful.",
);
return true;
}
logger.debug(
"Cached overlay status does not indicate a previous unsuccessful attempt to build an overlay base database.",
);
return false;
}
/**
* Retrieve overlay status from the Actions cache, if available.
*
* @returns `undefined` if no status was found in the cache (e.g. first run with
* this cache key) or if the cache operation fails.
*/
export async function getOverlayStatus(
codeql: CodeQL,
languages: string[],
diskUsage: DiskUsage,
logger: Logger,
): Promise<OverlayStatus | undefined> {
const cacheKey = await getCacheKey(codeql, languages, diskUsage);
const statusFile = getStatusFilePath(languages);
try {
await fs.promises.mkdir(path.dirname(statusFile), { recursive: true });
const foundKey = await waitForResultWithTimeLimit(
MAX_CACHE_OPERATION_MS,
actionsCache.restoreCache([statusFile], cacheKey),
() => {
logger.warning("Timed out restoring overlay status from cache.");
},
);
if (foundKey === undefined) {
logger.debug("No overlay status found in Actions cache.");
return undefined;
}
if (!fs.existsSync(statusFile)) {
logger.debug(
"Overlay status cache entry found but status file is missing.",
);
return undefined;
}
const contents = await fs.promises.readFile(statusFile, "utf-8");
const parsed: unknown = JSON.parse(contents);
if (
typeof parsed !== "object" ||
parsed === null ||
typeof parsed["attemptedToBuildOverlayBaseDatabase"] !== "boolean" ||
typeof parsed["builtOverlayBaseDatabase"] !== "boolean"
) {
logger.debug(
"Ignoring overlay status cache entry with unexpected format.",
);
return undefined;
}
return parsed as OverlayStatus;
} catch (error) {
logger.warning(
`Failed to restore overlay status from cache: ${getErrorMessage(error)}`,
);
return undefined;
}
}
/**
* Save overlay status to the Actions cache.
*
* @returns `true` if the status was saved successfully, `false` otherwise.
*/
export async function saveOverlayStatus(
codeql: CodeQL,
languages: string[],
diskUsage: DiskUsage,
status: OverlayStatus,
logger: Logger,
): Promise<boolean> {
const cacheKey = await getCacheKey(codeql, languages, diskUsage);
const statusFile = getStatusFilePath(languages);
try {
await fs.promises.mkdir(path.dirname(statusFile), { recursive: true });
await fs.promises.writeFile(statusFile, JSON.stringify(status));
const cacheId = await waitForResultWithTimeLimit(
MAX_CACHE_OPERATION_MS,
actionsCache.saveCache([statusFile], cacheKey),
() => {
logger.warning("Timed out saving overlay status to cache.");
},
);
if (cacheId === undefined) {
return false;
}
logger.debug(`Saved overlay status to Actions cache with key ${cacheKey}`);
return true;
} catch (error) {
logger.warning(
`Failed to save overlay status to cache: ${getErrorMessage(error)}`,
);
return false;
}
}
export async function getCacheKey(
codeql: CodeQL,
languages: string[],
diskUsage: DiskUsage,
): Promise<string> {
// Total disk space, rounded to the nearest 10 GB. This is included in the cache key so that if a
// customer upgrades their runner, we will try again to use overlay analysis, even if the CodeQL
// version has not changed. We round to the nearest 10 GB to work around small differences in disk
// space.
//
// Limitation: this can still flip from "too small" to "large enough" and back again if the disk
// space fluctuates above and below a multiple of 10 GB.
const diskSpaceToNearest10Gb = `${10 * Math.floor(diskUsage.numTotalBytes / (10 * 1024 * 1024 * 1024))}GB`;
// Include the CodeQL version in the cache key so we will try again to use overlay analysis when
// new queries and libraries that may be more efficient are released.
return `codeql-overlay-status-${[...languages].sort().join("+")}-${(await codeql.getVersion()).version}-runner-${diskSpaceToNearest10Gb}`;
}
+2 -2
View File
@@ -10,7 +10,7 @@ import {
import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql";
import { EnvVar } from "./environment";
import { Features } from "./feature-flags";
import { initFeatures } from "./feature-flags";
import { initCodeQL } from "./init";
import { getActionsLogger, Logger } from "./logging";
import { getRepositoryNwo } from "./repository";
@@ -114,7 +114,7 @@ async function run(startedAt: Date): Promise<void> {
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
+4 -6
View File
@@ -5,7 +5,7 @@ import * as core from "@actions/core";
import * as actionsUtil from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { Feature, Features } from "./feature-flags";
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
import { KnownLanguage } from "./languages";
import { getActionsLogger, Logger } from "./logging";
import { getRepositoryNwo } from "./repository";
@@ -32,7 +32,7 @@ async function run(startedAt: Date) {
// possible, and only use safe functions outside.
const logger = getActionsLogger();
let features: Features | undefined;
let features: FeatureEnablement | undefined;
let language: KnownLanguage | undefined;
try {
@@ -47,7 +47,7 @@ async function run(startedAt: Date) {
// Initialise FFs.
const repositoryNwo = getRepositoryNwo();
const gitHubVersion = await getGitHubVersion();
features = new Features(
features = initFeatures(
gitHubVersion,
repositoryNwo,
actionsUtil.getTemporaryDirectory(),
@@ -109,9 +109,7 @@ async function run(startedAt: Date) {
);
// Check that the private registries are reachable.
if (await features.getValue(Feature.StartProxyConnectionChecks)) {
await checkConnections(logger, proxyInfo);
}
await checkConnections(logger, proxyInfo);
// Report success if we have reached this point.
await sendSuccessStatusReport(
+1 -1
View File
@@ -18,7 +18,7 @@ import { DocUrl } from "./doc-url";
import { EnvVar } from "./environment";
import { getRef } from "./git-utils";
import { Logger } from "./logging";
import { OverlayBaseDatabaseDownloadStats } from "./overlay-database-utils";
import { OverlayBaseDatabaseDownloadStats } from "./overlay";
import { getRepositoryNwo } from "./repository";
import { ToolsSource } from "./setup-codeql";
import {
+1 -1
View File
@@ -21,7 +21,7 @@ import {
FeatureEnablement,
} from "./feature-flags";
import { Logger } from "./logging";
import { OverlayDatabaseMode } from "./overlay-database-utils";
import { OverlayDatabaseMode } from "./overlay";
import {
DEFAULT_DEBUG_ARTIFACT_NAME,
DEFAULT_DEBUG_DATABASE_NAME,
+61 -48
View File
@@ -11,8 +11,7 @@ import * as actionsUtil from "./actions-util";
import * as analyses from "./analyses";
import * as api from "./api-client";
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
import { CodeQL, getCodeQL } from "./codeql";
import { getConfig } from "./config-utils";
import { type CodeQL } from "./codeql";
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { FeatureEnablement } from "./feature-flags";
@@ -183,6 +182,44 @@ async function shouldDisableCombineSarifFiles(
return true;
}
/**
* Initialises a `CodeQL` instance that we can use to combine SARIF files.
*/
export async function minimalInitCodeQL(
logger: Logger,
gitHubVersion: GitHubVersion,
features: FeatureEnablement,
): Promise<CodeQL> {
logger.info(
"Initializing CodeQL since the 'init' Action was not called before this step.",
);
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput("external-repository-token"),
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action
apiDetails,
actionsUtil.getTemporaryDirectory(),
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
return initCodeQLResult.codeql;
}
export type CodeQLGetter = () => Promise<CodeQL>;
// Takes a list of paths to sarif files and combines them together using the
// CLI `github merge-results` command when all SARIF files are produced by
// CodeQL. Otherwise, it will fall back to combining the files in the action.
@@ -190,8 +227,10 @@ async function shouldDisableCombineSarifFiles(
async function combineSarifFilesUsingCLI(
sarifFiles: string[],
gitHubVersion: GitHubVersion,
features: FeatureEnablement,
_features: FeatureEnablement,
logger: Logger,
getCodeQL: CodeQLGetter,
tempDir: string,
): Promise<SarifFile> {
logger.info("Combining SARIF files using the CodeQL CLI");
@@ -229,45 +268,10 @@ async function combineSarifFilesUsingCLI(
return combineSarifFiles(sarifFiles, logger);
}
// Initialize CodeQL, either by using the config file from the 'init' step,
// or by initializing it here.
let codeQL: CodeQL;
let tempDir: string = actionsUtil.getTemporaryDirectory();
const config = await getConfig(tempDir, logger);
if (config !== undefined) {
codeQL = await getCodeQL(config.codeQLCmd);
tempDir = config.tempDir;
} else {
logger.info(
"Initializing CodeQL since the 'init' Action was not called before this step.",
);
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput(
"external-repository-token",
),
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action
apiDetails,
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
codeQL = initCodeQLResult.codeql;
}
// Obtain a `CodeQL` instance. For `analyze`, this is typically the instance that was used for running the queries.
// For `upload-sarif`, this either initialises a new instance or returns a previously initialised one if `getCodeQL`
// is called more than once.
const codeQL: CodeQL = await getCodeQL();
const baseTempDir = path.resolve(tempDir, "combined-sarif");
fs.mkdirSync(baseTempDir, { recursive: true });
@@ -673,6 +677,8 @@ export interface PostProcessingResults {
*
* @param logger The logger to use.
* @param features Information about enabled features.
* @param getCodeQL A function to retrieve a `CodeQL` instance.
* @param tempPath A path to a temporary directory.
* @param checkoutPath The path where the repo was checked out at.
* @param sarifPaths The paths of the SARIF files to post-process.
* @param category The analysis category.
@@ -684,6 +690,8 @@ export interface PostProcessingResults {
export async function postProcessSarifFiles(
logger: Logger,
features: FeatureEnablement,
getCodeQL: CodeQLGetter,
tempPath: string,
checkoutPath: string,
sarifPaths: string[],
category: string | undefined,
@@ -708,6 +716,8 @@ export async function postProcessSarifFiles(
gitHubVersion,
features,
logger,
getCodeQL,
tempPath,
);
} else {
const sarifPath = sarifPaths[0];
@@ -768,6 +778,8 @@ export async function writePostProcessedFiles(
* to.
*/
export async function uploadFiles(
tempDir: string,
codeql: CodeQL,
inputSarifPath: string,
checkoutPath: string,
category: string | undefined,
@@ -781,6 +793,8 @@ export async function uploadFiles(
);
return uploadSpecifiedFiles(
tempDir,
codeql,
sarifPaths,
checkoutPath,
category,
@@ -794,6 +808,8 @@ export async function uploadFiles(
* Uploads the given array of SARIF files.
*/
async function uploadSpecifiedFiles(
tempDir: string,
codeql: CodeQL,
sarifPaths: string[],
checkoutPath: string,
category: string | undefined,
@@ -804,6 +820,8 @@ async function uploadSpecifiedFiles(
const processingResults: PostProcessingResults = await postProcessSarifFiles(
logger,
features,
async () => codeql,
tempDir,
checkoutPath,
sarifPaths,
category,
@@ -942,7 +960,6 @@ export async function waitForProcessing(
const client = api.getApiClient();
const statusCheckingStarted = Date.now();
// eslint-disable-next-line no-constant-condition
while (true) {
if (
Date.now() >
@@ -1131,11 +1148,7 @@ function sanitize(str?: string) {
/**
* An error that occurred due to an invalid SARIF upload request.
*/
export class InvalidSarifUploadError extends Error {
constructor(message: string) {
super(message);
}
}
export class InvalidSarifUploadError extends Error {}
function filterAlertsByDiffRange(logger: Logger, sarif: SarifFile): SarifFile {
const diffRanges = readDiffRangesJsonFile(logger);
+23 -7
View File
@@ -1,10 +1,10 @@
import * as core from "@actions/core";
import * as actionsUtil from "./actions-util";
import { getActionVersion, getTemporaryDirectory } from "./actions-util";
import * as analyses from "./analyses";
import { getGitHubVersion } from "./api-client";
import { Features } from "./feature-flags";
import { getConfig } from "./config-utils";
import { initFeatures } from "./feature-flags";
import { Logger, getActionsLogger } from "./logging";
import { getRepositoryNwo } from "./repository";
import {
@@ -17,7 +17,11 @@ import {
isThirdPartyAnalysis,
} from "./status-report";
import * as upload_lib from "./upload-lib";
import { postProcessAndUploadSarif } from "./upload-sarif";
import {
getOrInitCodeQL,
postProcessAndUploadSarif,
UploadSarifState,
} from "./upload-sarif";
import {
ConfigurationError,
checkActionVersion,
@@ -59,21 +63,22 @@ async function run(startedAt: Date) {
// possible, and only use safe functions outside.
const logger = getActionsLogger();
const state: UploadSarifState = { cachedCodeQL: undefined };
try {
initializeEnvironment(getActionVersion());
initializeEnvironment(actionsUtil.getActionVersion());
const gitHubVersion = await getGitHubVersion();
checkActionVersion(getActionVersion(), gitHubVersion);
checkActionVersion(actionsUtil.getActionVersion(), gitHubVersion);
// Make inputs accessible in the `post` step.
actionsUtil.persistInputs();
const repositoryNwo = getRepositoryNwo();
const features = new Features(
const features = initFeatures(
gitHubVersion,
repositoryNwo,
getTemporaryDirectory(),
actionsUtil.getTemporaryDirectory(),
logger,
);
@@ -94,9 +99,20 @@ async function run(startedAt: Date) {
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
const category = actionsUtil.getOptionalInput("category");
// Determine the temporary directory to use. If we are able to read a `Config` from a previous CodeQL Action
// step in the job, then use the temporary directory configured there. Otherwise, use our default.
let tempDir: string = actionsUtil.getTemporaryDirectory();
const config = await getConfig(tempDir, logger);
if (config !== undefined) {
tempDir = config.tempDir;
}
const uploadResults = await postProcessAndUploadSarif(
logger,
tempDir,
features,
() => getOrInitCodeQL(state, logger, gitHubVersion, features, config),
"always",
checkoutPath,
sarifPath,
+99 -2
View File
@@ -5,15 +5,102 @@ import test, { ExecutionContext } from "ava";
import * as sinon from "sinon";
import { AnalysisKind, getAnalysisConfig } from "./analyses";
import { getCodeQLForTesting } from "./codeql";
import * as codeql from "./codeql";
import { getRunnerLogger } from "./logging";
import { createFeatures, setupTests } from "./testing-utils";
import { createFeatures, createTestConfig, setupTests } from "./testing-utils";
import { UploadResult } from "./upload-lib";
import * as uploadLib from "./upload-lib";
import { postProcessAndUploadSarif } from "./upload-sarif";
import {
getOrInitCodeQL,
postProcessAndUploadSarif,
UploadSarifState,
} from "./upload-sarif";
import * as util from "./util";
setupTests(test);
test("getOrInitCodeQL - gets cached CodeQL instance when available", async (t) => {
const cachedCodeQL = await getCodeQLForTesting();
const getCodeQL = sinon.stub(codeql, "getCodeQL").resolves(undefined);
const minimalInitCodeQL = sinon
.stub(uploadLib, "minimalInitCodeQL")
.resolves(undefined);
const result = await getOrInitCodeQL(
{ cachedCodeQL },
getRunnerLogger(true),
{ type: util.GitHubVariant.GHES, version: "3.0" },
createFeatures([]),
undefined,
);
// Neither of the two functions to get a CodeQL instance were called.
t.true(getCodeQL.notCalled);
t.true(minimalInitCodeQL.notCalled);
// But we have an instance that refers to the same object as the one we put into the state.
t.truthy(result);
t.is(result, cachedCodeQL);
});
test("getOrInitCodeQL - uses minimalInitCodeQL when there's no config", async (t) => {
const newInstance = await getCodeQLForTesting();
const getCodeQL = sinon.stub(codeql, "getCodeQL").resolves(undefined);
const minimalInitCodeQL = sinon
.stub(uploadLib, "minimalInitCodeQL")
.resolves(newInstance);
const state: UploadSarifState = { cachedCodeQL: undefined };
const result = await getOrInitCodeQL(
state,
getRunnerLogger(true),
{ type: util.GitHubVariant.GHES, version: "3.0" },
createFeatures([]),
undefined,
);
// Check that the right function was called.
t.true(getCodeQL.notCalled);
t.true(minimalInitCodeQL.calledOnce);
// And that we received the instance that we expected.
t.truthy(result);
t.is(result, newInstance);
// And that it was cached.
t.is(state.cachedCodeQL, newInstance);
});
test("getOrInitCodeQL - uses getCodeQL when there's a config", async (t) => {
const newInstance = await getCodeQLForTesting();
const getCodeQL = sinon.stub(codeql, "getCodeQL").resolves(newInstance);
const minimalInitCodeQL = sinon
.stub(uploadLib, "minimalInitCodeQL")
.resolves(undefined);
const config = createTestConfig({});
const state: UploadSarifState = { cachedCodeQL: undefined };
const result = await getOrInitCodeQL(
state,
getRunnerLogger(true),
{ type: util.GitHubVariant.GHES, version: "3.0" },
createFeatures([]),
config,
);
// Check that the right function was called.
t.true(getCodeQL.calledOnce);
t.true(minimalInitCodeQL.notCalled);
// And that we received the instance that we expected.
t.truthy(result);
t.is(result, newInstance);
// And that it was cached.
t.is(state.cachedCodeQL, newInstance);
});
interface UploadSarifExpectedResult {
uploadResult?: UploadResult;
expectedFiles?: string[];
@@ -31,6 +118,8 @@ function mockPostProcessSarifFiles() {
sinon.match.any,
sinon.match.any,
sinon.match.any,
sinon.match.any,
sinon.match.any,
analysisConfig,
)
.resolves({ sarif: { runs: [] }, analysisKey: "", environment: "" });
@@ -73,7 +162,9 @@ const postProcessAndUploadSarifMacro = test.macro({
const actual = await postProcessAndUploadSarif(
logger,
tempDir,
features,
async () => getCodeQLForTesting(),
"always",
"",
testPath,
@@ -90,6 +181,8 @@ const postProcessAndUploadSarifMacro = test.macro({
postProcessSarifFiles.calledWith(
logger,
features,
sinon.match.func,
tempDir,
sinon.match.any,
analysisKindResult.expectedFiles?.map(toFullPath) ??
fullSarifPaths,
@@ -221,7 +314,9 @@ test("postProcessAndUploadSarif doesn't upload if upload is disabled", async (t)
const actual = await postProcessAndUploadSarif(
logger,
tempDir,
features,
() => getCodeQLForTesting(),
"never",
"",
tempDir,
@@ -248,7 +343,9 @@ test("postProcessAndUploadSarif writes post-processed SARIF files if output dire
const postProcessedOutPath = path.join(tempDir, "post-processed");
const actual = await postProcessAndUploadSarif(
logger,
tempDir,
features,
() => getCodeQLForTesting(),
"never",
"",
tempDir,
+42 -1
View File
@@ -1,20 +1,57 @@
import { UploadKind } from "./actions-util";
import * as analyses from "./analyses";
import type { CodeQL } from "./codeql";
import * as codeql from "./codeql";
import { Config } from "./config-utils";
import { FeatureEnablement } from "./feature-flags";
import { Logger } from "./logging";
import * as upload_lib from "./upload-lib";
import { unsafeEntriesInvariant } from "./util";
import { GitHubVersion, unsafeEntriesInvariant } from "./util";
export interface UploadSarifState {
/** The cached `CodeQL` instance, if any. */
cachedCodeQL: CodeQL | undefined;
}
// Maps analysis kinds to SARIF IDs.
export type UploadSarifResults = Partial<
Record<analyses.AnalysisKind, upload_lib.UploadResult>
>;
/** Get or initialise a `CodeQL` instance for use by the `upload-sarif` action. */
export async function getOrInitCodeQL(
actionState: UploadSarifState,
logger: Logger,
gitHubVersion: GitHubVersion,
features: FeatureEnablement,
config: Config | undefined,
): Promise<CodeQL> {
// Return the cached instance, if we have one.
if (actionState.cachedCodeQL !== undefined) return actionState.cachedCodeQL;
// If we have been able to load a `Config` from an earlier CodeQL Action step in the job,
// then use the CodeQL executable that we have used previously. Otherwise, initialise the
// CLI specifically for `upload-sarif`. Either way, we cache the instance.
if (config !== undefined) {
actionState.cachedCodeQL = await codeql.getCodeQL(config.codeQLCmd);
} else {
actionState.cachedCodeQL = await upload_lib.minimalInitCodeQL(
logger,
gitHubVersion,
features,
);
}
return actionState.cachedCodeQL;
}
/**
* Finds SARIF files in `sarifPath`, post-processes them, and uploads them to the appropriate services.
*
* @param logger The logger to use.
* @param tempPath The path to the temporary directory.
* @param features Information about enabled features.
* @param getCodeQL A function to retrieve a `CodeQL` instance.
* @param uploadKind The kind of upload that is requested.
* @param checkoutPath The path where the repository was checked out at.
* @param sarifPath The path to the file or directory to upload.
@@ -25,7 +62,9 @@ export type UploadSarifResults = Partial<
*/
export async function postProcessAndUploadSarif(
logger: Logger,
tempPath: string,
features: FeatureEnablement,
getCodeQL: upload_lib.CodeQLGetter,
uploadKind: UploadKind,
checkoutPath: string,
sarifPath: string,
@@ -45,6 +84,8 @@ export async function postProcessAndUploadSarif(
const postProcessingResults = await upload_lib.postProcessSarifFiles(
logger,
features,
getCodeQL,
tempPath,
checkoutPath,
sarifFiles,
category,
+3 -5
View File
@@ -690,11 +690,7 @@ export class HTTPError extends Error {
* An Error class that indicates an error that occurred due to
* a misconfiguration of the action or the CodeQL CLI.
*/
export class ConfigurationError extends Error {
constructor(message: string) {
super(message);
}
}
export class ConfigurationError extends Error {}
export function asHTTPError(arg: any): HTTPError | undefined {
if (
@@ -744,6 +740,7 @@ export async function bundleDb(
language: Language,
codeql: CodeQL,
dbName: string,
{ includeDiagnostics }: { includeDiagnostics: boolean },
) {
const databasePath = getCodeQLDatabasePath(config, language);
const databaseBundlePath = path.resolve(config.dbLocation, `${dbName}.zip`);
@@ -774,6 +771,7 @@ export async function bundleDb(
databasePath,
databaseBundlePath,
dbName,
includeDiagnostics,
additionalFiles,
);
return databaseBundlePath;